153cdbc3dSStefano Zampini /* TODOLIST 2eb97c9d2SStefano Zampini 3eb97c9d2SStefano Zampini Solvers 4a0d3c3abSStefano Zampini - Add support for cholesky for coarse solver (similar to local solvers) 5eb97c9d2SStefano Zampini - Propagate ksp prefixes for solvers to mat objects? 6eb97c9d2SStefano Zampini 7eb97c9d2SStefano Zampini User interface 80f202f7eSStefano Zampini - ** DM attached to pc? 9eb97c9d2SStefano Zampini 10eb97c9d2SStefano Zampini Debugging output 11b9b85e73SStefano Zampini - * Better management of verbosity levels of debugging output 12eb97c9d2SStefano Zampini 13eb97c9d2SStefano Zampini Extra 14b9b85e73SStefano Zampini - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)? 15eb97c9d2SStefano Zampini - BDDC with MG framework? 16eb97c9d2SStefano Zampini 17eb97c9d2SStefano Zampini MATIS related operations contained in BDDC code 18eb97c9d2SStefano Zampini - Provide general case for subassembling 19eb97c9d2SStefano Zampini 2053cdbc3dSStefano Zampini */ 210c7d97c5SJed Brown 225e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 235e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h> 243b03a366Sstefano_zampini #include <petscblaslapack.h> 25674ae819SStefano Zampini 2643371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE; 2743371fb9SStefano Zampini 28f3d41395Sstefano_zampini static PetscBool cited = PETSC_FALSE; 29f3d41395Sstefano_zampini static const char citation[] = 30f3d41395Sstefano_zampini "@article{ZampiniPCBDDC,\n" 31f3d41395Sstefano_zampini "author = {Stefano Zampini},\n" 32f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n" 33f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n" 34f3d41395Sstefano_zampini "volume = {38},\n" 35f3d41395Sstefano_zampini "number = {5},\n" 36f3d41395Sstefano_zampini "pages = {S282-S306},\n" 37f3d41395Sstefano_zampini "year = {2016},\n" 38f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n" 39f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n" 40f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n" 41f3d41395Sstefano_zampini "}\n"; 42f3d41395Sstefano_zampini 4343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS]; 4443371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS]; 4543371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS]; 4643371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS]; 478ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS]; 488ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS]; 4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS]; 5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS]; 5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS]; 5243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS]; 5343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS]; 5455c176c0SStefano Zampini PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3]; 5543371fb9SStefano Zampini 56bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET","LUMP","PCBDDCInterfaceExtType","PC_BDDC_INTERFACE_EXT_",NULL}; 57bc960bbfSJed Brown 580369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec); 590369aaf7SStefano Zampini 604416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc) 610c7d97c5SJed Brown { 620c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 63e569e4e1SStefano Zampini PetscInt nt,i; 640c7d97c5SJed Brown 650c7d97c5SJed Brown PetscFunctionBegin; 66d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"BDDC options"); 678eeda7d8SStefano Zampini /* Verbose debugging */ 689566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL)); 69a13144ffSStefano Zampini /* Approximate solvers */ 709566063dSJacob 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)); 71bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) { 729566063dSJacob 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)); 739566063dSJacob 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)); 74bc960bbfSJed Brown } else { 75bc960bbfSJed Brown /* This flag is needed/implied by lumping */ 76bc960bbfSJed Brown pcbddc->switch_static = PETSC_TRUE; 77bc960bbfSJed Brown } 789566063dSJacob 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)); 799566063dSJacob 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)); 806b78500eSPatrick Sanan /* Primal space customization */ 819566063dSJacob 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)); 829566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL)); 839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL)); 849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL)); 859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL)); 869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL)); 879566063dSJacob 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)); 889566063dSJacob 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)); 899566063dSJacob 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)); 909566063dSJacob 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)); 918eeda7d8SStefano Zampini /* Change of basis */ 929566063dSJacob 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)); 939566063dSJacob 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)); 94674ae819SStefano Zampini if (!pcbddc->use_change_of_basis) { 95674ae819SStefano Zampini pcbddc->use_change_on_faces = PETSC_FALSE; 96674ae819SStefano Zampini } 978eeda7d8SStefano Zampini /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL)); 999566063dSJacob 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)); 100e569e4e1SStefano Zampini i = pcbddc->coarsening_ratio; 1019566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL)); 1029566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc,i)); 103e569e4e1SStefano Zampini i = pcbddc->max_levels; 1049566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL)); 1059566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc,i)); 1069566063dSJacob 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)); 1079566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL)); 1089566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL)); 1099566063dSJacob 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)); 1109566063dSJacob 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)); 1119566063dSJacob 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)); 1129566063dSJacob 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)); 1139566063dSJacob 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)); 1149566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL)); 1159566063dSJacob 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)); 116bd2a564bSStefano Zampini nt = 2; 1179566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL)); 118bd2a564bSStefano Zampini if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0]; 1199566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL)); 1209566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL)); 1219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL)); 1229566063dSJacob 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)); 1239566063dSJacob 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)); 1249566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_change","Compute the pressure change of basis explicitly","none",pcbddc->benign_change_explicit,&pcbddc->benign_change_explicit,NULL)); 1259566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction","Compute the benign correction during PreSolve","none",pcbddc->benign_compute_correction,&pcbddc->benign_compute_correction,NULL)); 1269566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL)); 1279566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL)); 1289566063dSJacob 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)); 1299566063dSJacob 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)); 130d0609cedSBarry Smith PetscOptionsHeadEnd(); 1310c7d97c5SJed Brown PetscFunctionReturn(0); 1320c7d97c5SJed Brown } 1336b78500eSPatrick Sanan 1346b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer) 1356b78500eSPatrick Sanan { 1366b78500eSPatrick Sanan PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 137e9627c49SStefano Zampini PC_IS *pcis = (PC_IS*)pc->data; 13871783a16SStefano Zampini PetscBool isascii; 139e9627c49SStefano Zampini PetscSubcomm subcomm; 140e9627c49SStefano Zampini PetscViewer subviewer; 1416b78500eSPatrick Sanan 1426b78500eSPatrick Sanan PetscFunctionBegin; 1439566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 1446b78500eSPatrick Sanan /* ASCII viewer */ 1456b78500eSPatrick Sanan if (isascii) { 1464b2aedd3SStefano Zampini PetscMPIInt color,rank,size; 147fbad9177SStefano Zampini PetscInt64 loc[7],gsum[6],gmax[6],gmin[6],totbenign; 148e9627c49SStefano Zampini PetscScalar interface_size; 149e9627c49SStefano Zampini PetscReal ratio1=0.,ratio2=0.; 150e9627c49SStefano Zampini Vec counter; 1516b78500eSPatrick Sanan 152b74ba07aSstefano_zampini if (!pc->setupcalled) { 1539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Partial information available: preconditioner has not been setup yet\n")); 154b74ba07aSstefano_zampini } 15563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use verbose output: %" PetscInt_FMT "\n",pcbddc->dbg_flag)); 1569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr)); 1579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr)); 158e9627c49SStefano Zampini if (pcbddc->mat_graph->twodim) { 1599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Connectivity graph topological dimension: 2\n")); 160e9627c49SStefano Zampini } else { 1619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Connectivity graph topological dimension: 3\n")); 162e9627c49SStefano Zampini } 163aefa1729SStefano Zampini if (pcbddc->graphmaxcount != PETSC_MAX_INT) { 16463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Graph max count: %" PetscInt_FMT "\n",pcbddc->graphmaxcount)); 165aefa1729SStefano Zampini } 1669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Corner selection: %d (selected %d)\n",pcbddc->corner_selection,pcbddc->corner_selected)); 16763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use vertices: %d (vertex size %" PetscInt_FMT ")\n",pcbddc->use_vertices,pcbddc->vertex_size)); 1689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use edges: %d\n",pcbddc->use_edges)); 1699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use faces: %d\n",pcbddc->use_faces)); 1709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use true near null space: %d\n",pcbddc->use_nnsp_true)); 1719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single)); 1729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis)); 1739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces)); 1749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix)); 1759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix)); 1769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs)); 1779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static)); 1789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick)); 1799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Interface extension: %s\n",PCBDDCInterfaceExtTypes[pcbddc->interface_extension])); 18063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Multilevel max levels: %" PetscInt_FMT "\n",pcbddc->max_levels)); 18163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Multilevel coarsening ratio: %" PetscInt_FMT "\n",pcbddc->coarsening_ratio)); 1829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates)); 1839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling)); 1849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows)); 1859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat)); 1869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild)); 18763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n",pcbddc->sub_schurs_layers)); 1889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj)); 189bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) { 19063a3b9bcSJacob 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])); 191bd2a564bSStefano Zampini } else { 19263a3b9bcSJacob 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])); 193bd2a564bSStefano Zampini } 19463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Min constraints / connected component: %" PetscInt_FMT "\n",pcbddc->adaptive_nmin)); 19563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Max constraints / connected component: %" PetscInt_FMT "\n",pcbddc->adaptive_nmax)); 1969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur)); 1979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal)); 19863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n",pcbddc->coarse_adj_red)); 19963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n",pcbddc->coarse_eqs_per_proc)); 2009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter)); 2019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit)); 2029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Benign subspace trick is active: %d\n",pcbddc->benign_have_null)); 2039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux)); 204b74ba07aSstefano_zampini if (!pc->setupcalled) PetscFunctionReturn(0); 2056b78500eSPatrick Sanan 206fbad9177SStefano Zampini /* compute interface size */ 2079566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B,1.0)); 2089566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat,&counter,NULL)); 2099566063dSJacob Faibussowitsch PetscCall(VecSet(counter,0.0)); 2109566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE)); 2119566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE)); 2129566063dSJacob Faibussowitsch PetscCall(VecSum(counter,&interface_size)); 2139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&counter)); 214fbad9177SStefano Zampini 215fbad9177SStefano Zampini /* compute some statistics on the domain decomposition */ 216e9627c49SStefano Zampini gsum[0] = 1; 217fbad9177SStefano Zampini gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0; 218e9627c49SStefano Zampini loc[0] = !!pcis->n; 219e9627c49SStefano Zampini loc[1] = pcis->n - pcis->n_B; 220e9627c49SStefano Zampini loc[2] = pcis->n_B; 221e9627c49SStefano Zampini loc[3] = pcbddc->local_primal_size; 222345ecf6cSStefano Zampini loc[4] = pcis->n; 223fbad9177SStefano Zampini loc[5] = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0); 224fbad9177SStefano Zampini loc[6] = pcbddc->benign_n; 2259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc))); 226fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1; 2279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc))); 228fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT; 2299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc))); 2309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc))); 231e9627c49SStefano Zampini if (pcbddc->coarse_size) { 232e9627c49SStefano Zampini ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size); 233e9627c49SStefano Zampini ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size; 234e9627c49SStefano Zampini } 23563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n",pcbddc->current_level)); 23663a3b9bcSJacob 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)); 23763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n",(PetscInt)ratio1,(PetscInt)ratio2)); 23863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Active processes : %" PetscInt_FMT "\n",(PetscInt)gsum[0])); 23963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Total subdomains : %" PetscInt_FMT "\n",(PetscInt)gsum[5])); 240345ecf6cSStefano Zampini if (pcbddc->benign_have_null) { 24163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Benign subs : %" PetscInt_FMT "\n",(PetscInt)totbenign)); 242345ecf6cSStefano Zampini } 2439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Dofs type :\tMIN\tMAX\tMEAN\n")); 24463a3b9bcSJacob 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]))); 24563a3b9bcSJacob 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]))); 24663a3b9bcSJacob 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]))); 24763a3b9bcSJacob 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]))); 24863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Local subs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n" ,(PetscInt)gmin[5],(PetscInt)gmax[5])); 2499566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 25015579a77SStefano Zampini 2519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank)); 25215579a77SStefano Zampini 25315579a77SStefano Zampini /* local solvers */ 2549566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer)); 255dd400576SPatrick Sanan if (rank == 0) { 2569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n")); 2579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2589566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_D,subviewer)); 2599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n")); 2619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2629566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_R,subviewer)); 2639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2649566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 26515579a77SStefano Zampini } 2669566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer)); 2679566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 268e9627c49SStefano Zampini 269fbad9177SStefano Zampini /* the coarse problem can be handled by a different communicator */ 270e9627c49SStefano Zampini if (pcbddc->coarse_ksp) color = 1; 271e9627c49SStefano Zampini else color = 0; 2729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size)); 2739566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm)); 2749566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm,PetscMin(size,2))); 2759566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm,color,rank)); 2769566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer)); 277e9627c49SStefano Zampini if (color == 1) { 2789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n")); 2799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2809566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->coarse_ksp,subviewer)); 2819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2829566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 283e9627c49SStefano Zampini } 2849566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 2869566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 287e9627c49SStefano Zampini } 2886b78500eSPatrick Sanan PetscFunctionReturn(0); 2896b78500eSPatrick Sanan } 290a13144ffSStefano Zampini 2911e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 292a13144ffSStefano Zampini { 293a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 294a13144ffSStefano Zampini 295a13144ffSStefano Zampini PetscFunctionBegin; 2969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)G)); 2979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 298a13144ffSStefano Zampini pcbddc->discretegradient = G; 299a13144ffSStefano Zampini pcbddc->nedorder = order > 0 ? order : -order; 300495a2a07SStefano Zampini pcbddc->nedfield = field; 3011e0482f5SStefano Zampini pcbddc->nedglobal = global; 3021e0482f5SStefano Zampini pcbddc->conforming = conforming; 303a13144ffSStefano Zampini PetscFunctionReturn(0); 304a13144ffSStefano Zampini } 305a13144ffSStefano Zampini 306a13144ffSStefano Zampini /*@ 307a13144ffSStefano Zampini PCBDDCSetDiscreteGradient - Sets the discrete gradient 308a13144ffSStefano Zampini 309a13144ffSStefano Zampini Collective on PC 310a13144ffSStefano Zampini 311a13144ffSStefano Zampini Input Parameters: 312a13144ffSStefano Zampini + pc - the preconditioning context 313a13144ffSStefano Zampini . G - the discrete gradient matrix (should be in AIJ format) 314a13144ffSStefano Zampini . order - the order of the Nedelec space (1 for the lowest order) 315495a2a07SStefano Zampini . field - the field id of the Nedelec dofs (not used if the fields have not been specified) 3161e0482f5SStefano Zampini . global - the type of global ordering for the rows of G 317a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not 318a13144ffSStefano Zampini 319a13144ffSStefano Zampini Level: advanced 320a13144ffSStefano Zampini 32195452b02SPatrick Sanan Notes: 32295452b02SPatrick Sanan The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry. 323495a2a07SStefano Zampini For variable order spaces, the order should be set to zero. 3241e0482f5SStefano Zampini If global is true, the rows of G should be given in global ordering for the whole dofs; 3251e0482f5SStefano Zampini if false, the ordering should be global for the Nedelec field. 3261e0482f5SStefano 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 3271e0482f5SStefano Zampini and geid the one for the Nedelec field. 328a13144ffSStefano Zampini 32916b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()` 330a13144ffSStefano Zampini @*/ 3311e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 332a13144ffSStefano Zampini { 333a13144ffSStefano Zampini PetscFunctionBegin; 334a13144ffSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 335a13144ffSStefano Zampini PetscValidHeaderSpecific(G,MAT_CLASSID,2); 336a13144ffSStefano Zampini PetscValidLogicalCollectiveInt(pc,order,3); 3371e0482f5SStefano Zampini PetscValidLogicalCollectiveInt(pc,field,4); 3381e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc,global,5); 3391e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc,conforming,6); 3401e0482f5SStefano Zampini PetscCheckSameComm(pc,1,G,2); 341cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming)); 342a13144ffSStefano Zampini PetscFunctionReturn(0); 343a13144ffSStefano Zampini } 344a13144ffSStefano Zampini 3458ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 346a198735bSStefano Zampini { 347a198735bSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 3486b78500eSPatrick Sanan 349a198735bSStefano Zampini PetscFunctionBegin; 3509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)divudotp)); 3519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 352a198735bSStefano Zampini pcbddc->divudotp = divudotp; 3538ae0ca82SStefano Zampini pcbddc->divudotp_trans = trans; 354a198735bSStefano Zampini pcbddc->compute_nonetflux = PETSC_TRUE; 355a198735bSStefano Zampini if (vl2l) { 3569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2l)); 3579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 358a198735bSStefano Zampini pcbddc->divudotp_vl2l = vl2l; 359a198735bSStefano Zampini } 360a198735bSStefano Zampini PetscFunctionReturn(0); 361a198735bSStefano Zampini } 3623d996552SStefano Zampini 363a198735bSStefano Zampini /*@ 364a198735bSStefano Zampini PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx 365a198735bSStefano Zampini 366a198735bSStefano Zampini Collective on PC 367a198735bSStefano Zampini 368a198735bSStefano Zampini Input Parameters: 369a198735bSStefano Zampini + pc - the preconditioning context 370a198735bSStefano Zampini . divudotp - the matrix (must be of type MATIS) 3718ae0ca82SStefano Zampini . trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space. 37205a3bf82SStefano Zampini - vl2l - optional index set describing the local (wrt the local matrix in divudotp) to local (wrt the local matrix in the preconditioning matrix) map for the velocities 373a198735bSStefano Zampini 374a198735bSStefano Zampini Level: advanced 375a198735bSStefano Zampini 37695452b02SPatrick Sanan Notes: 37795452b02SPatrick Sanan This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries 37805a3bf82SStefano Zampini If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix 379a198735bSStefano Zampini 380db781477SPatrick Sanan .seealso: `PCBDDC` 381a198735bSStefano Zampini @*/ 3828ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 383a198735bSStefano Zampini { 384a198735bSStefano Zampini PetscBool ismatis; 385a198735bSStefano Zampini 386a198735bSStefano Zampini PetscFunctionBegin; 387a198735bSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 388a198735bSStefano Zampini PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2); 389a198735bSStefano Zampini PetscCheckSameComm(pc,1,divudotp,2); 3908ae0ca82SStefano Zampini PetscValidLogicalCollectiveBool(pc,trans,3); 3911b24a7afSStefano Zampini if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4); 3929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis)); 39328b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS"); 394cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l)); 395a198735bSStefano Zampini PetscFunctionReturn(0); 396a198735bSStefano Zampini } 3972d505d7fSStefano Zampini 3981dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior) 399b9b85e73SStefano Zampini { 400b9b85e73SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 401b9b85e73SStefano Zampini 402b9b85e73SStefano Zampini PetscFunctionBegin; 4039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)change)); 4049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 405b9b85e73SStefano Zampini pcbddc->user_ChangeOfBasisMatrix = change; 4061dd7afcfSStefano Zampini pcbddc->change_interior = interior; 407b9b85e73SStefano Zampini PetscFunctionReturn(0); 408b9b85e73SStefano Zampini } 40932fe681dSStefano Zampini 410b9b85e73SStefano Zampini /*@ 411906d46d4SStefano Zampini PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 412b9b85e73SStefano Zampini 413b9b85e73SStefano Zampini Collective on PC 414b9b85e73SStefano Zampini 415b9b85e73SStefano Zampini Input Parameters: 416b9b85e73SStefano Zampini + pc - the preconditioning context 4171dd7afcfSStefano Zampini . change - the change of basis matrix 4181dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs 419b9b85e73SStefano Zampini 420b9b85e73SStefano Zampini Level: intermediate 421b9b85e73SStefano Zampini 422b9b85e73SStefano Zampini Notes: 423b9b85e73SStefano Zampini 424db781477SPatrick Sanan .seealso: `PCBDDC` 425b9b85e73SStefano Zampini @*/ 4261dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior) 427b9b85e73SStefano Zampini { 428b9b85e73SStefano Zampini PetscFunctionBegin; 429b9b85e73SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 430b9b85e73SStefano Zampini PetscValidHeaderSpecific(change,MAT_CLASSID,2); 431906d46d4SStefano Zampini PetscCheckSameComm(pc,1,change,2); 432906d46d4SStefano Zampini if (pc->mat) { 433906d46d4SStefano Zampini PetscInt rows_c,cols_c,rows,cols; 4349566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat,&rows,&cols)); 4359566063dSJacob Faibussowitsch PetscCall(MatGetSize(change,&rows_c,&cols_c)); 43663a3b9bcSJacob 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); 43763a3b9bcSJacob 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); 4389566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat,&rows,&cols)); 4399566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(change,&rows_c,&cols_c)); 44063a3b9bcSJacob 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); 44163a3b9bcSJacob 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); 442906d46d4SStefano Zampini } 443cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior)); 444b9b85e73SStefano Zampini PetscFunctionReturn(0); 445b9b85e73SStefano Zampini } 4462d505d7fSStefano Zampini 44730368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices) 44830368db7SStefano Zampini { 44930368db7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 45056282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 45130368db7SStefano Zampini 45230368db7SStefano Zampini PetscFunctionBegin; 4539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 45456282151SStefano Zampini if (pcbddc->user_primal_vertices) { 4559566063dSJacob Faibussowitsch PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal)); 45656282151SStefano Zampini } 4579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 4589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 45930368db7SStefano Zampini pcbddc->user_primal_vertices = PrimalVertices; 46056282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 46130368db7SStefano Zampini PetscFunctionReturn(0); 46230368db7SStefano Zampini } 463ab8c8b98SStefano Zampini 46430368db7SStefano Zampini /*@ 46530368db7SStefano Zampini PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC 46630368db7SStefano Zampini 46730368db7SStefano Zampini Collective 46830368db7SStefano Zampini 46930368db7SStefano Zampini Input Parameters: 47030368db7SStefano Zampini + pc - the preconditioning context 47130368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty) 47230368db7SStefano Zampini 47330368db7SStefano Zampini Level: intermediate 47430368db7SStefano Zampini 47530368db7SStefano Zampini Notes: 47630368db7SStefano Zampini Any process can list any global node 47730368db7SStefano Zampini 478db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 47930368db7SStefano Zampini @*/ 48030368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices) 48130368db7SStefano Zampini { 48230368db7SStefano Zampini PetscFunctionBegin; 48330368db7SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 48430368db7SStefano Zampini PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 48530368db7SStefano Zampini PetscCheckSameComm(pc,1,PrimalVertices,2); 486cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices)); 48730368db7SStefano Zampini PetscFunctionReturn(0); 48830368db7SStefano Zampini } 4892d505d7fSStefano Zampini 4903100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is) 4913100ebe3SStefano Zampini { 4923100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 4933100ebe3SStefano Zampini 4943100ebe3SStefano Zampini PetscFunctionBegin; 4953100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices; 4963100ebe3SStefano Zampini PetscFunctionReturn(0); 4973100ebe3SStefano Zampini } 4983100ebe3SStefano Zampini 4993100ebe3SStefano Zampini /*@ 5003100ebe3SStefano Zampini PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS() 5013100ebe3SStefano Zampini 5023100ebe3SStefano Zampini Collective 5033100ebe3SStefano Zampini 5043100ebe3SStefano Zampini Input Parameters: 5053100ebe3SStefano Zampini . pc - the preconditioning context 5063100ebe3SStefano Zampini 5073100ebe3SStefano Zampini Output Parameters: 5083100ebe3SStefano Zampini . is - index set of primal vertices in global numbering (NULL if not set) 5093100ebe3SStefano Zampini 5103100ebe3SStefano Zampini Level: intermediate 5113100ebe3SStefano Zampini 5123100ebe3SStefano Zampini Notes: 5133100ebe3SStefano Zampini 514db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 5153100ebe3SStefano Zampini @*/ 5163100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) 5173100ebe3SStefano Zampini { 5183100ebe3SStefano Zampini PetscFunctionBegin; 5193100ebe3SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5203100ebe3SStefano Zampini PetscValidPointer(is,2); 521cac4c232SBarry Smith PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is)); 5223100ebe3SStefano Zampini PetscFunctionReturn(0); 5233100ebe3SStefano Zampini } 5243100ebe3SStefano Zampini 525674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 526674ae819SStefano Zampini { 527674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 52856282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 5291e6b0712SBarry Smith 530674ae819SStefano Zampini PetscFunctionBegin; 5319566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 53256282151SStefano Zampini if (pcbddc->user_primal_vertices_local) { 5339566063dSJacob Faibussowitsch PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal)); 53456282151SStefano Zampini } 5359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 5369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 53730368db7SStefano Zampini pcbddc->user_primal_vertices_local = PrimalVertices; 53856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 539674ae819SStefano Zampini PetscFunctionReturn(0); 540674ae819SStefano Zampini } 5413100ebe3SStefano Zampini 542674ae819SStefano Zampini /*@ 54328509bceSStefano Zampini PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC 544674ae819SStefano Zampini 54517eb1463SStefano Zampini Collective 546674ae819SStefano Zampini 547674ae819SStefano Zampini Input Parameters: 548674ae819SStefano Zampini + pc - the preconditioning context 54917eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty) 550674ae819SStefano Zampini 551674ae819SStefano Zampini Level: intermediate 552674ae819SStefano Zampini 553674ae819SStefano Zampini Notes: 554674ae819SStefano Zampini 555db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 556674ae819SStefano Zampini @*/ 557674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 558674ae819SStefano Zampini { 559674ae819SStefano Zampini PetscFunctionBegin; 560674ae819SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 561674ae819SStefano Zampini PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 56217eb1463SStefano Zampini PetscCheckSameComm(pc,1,PrimalVertices,2); 563cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices)); 564674ae819SStefano Zampini PetscFunctionReturn(0); 565674ae819SStefano Zampini } 5662d505d7fSStefano Zampini 5673100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) 5683100ebe3SStefano Zampini { 5693100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 5703100ebe3SStefano Zampini 5713100ebe3SStefano Zampini PetscFunctionBegin; 5723100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices_local; 5733100ebe3SStefano Zampini PetscFunctionReturn(0); 5743100ebe3SStefano Zampini } 5753100ebe3SStefano Zampini 5763100ebe3SStefano Zampini /*@ 5773100ebe3SStefano Zampini PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS() 5783100ebe3SStefano Zampini 5793100ebe3SStefano Zampini Collective 5803100ebe3SStefano Zampini 5813100ebe3SStefano Zampini Input Parameters: 5823100ebe3SStefano Zampini . pc - the preconditioning context 5833100ebe3SStefano Zampini 5843100ebe3SStefano Zampini Output Parameters: 5853100ebe3SStefano Zampini . is - index set of primal vertices in local numbering (NULL if not set) 5863100ebe3SStefano Zampini 5873100ebe3SStefano Zampini Level: intermediate 5883100ebe3SStefano Zampini 5893100ebe3SStefano Zampini Notes: 5903100ebe3SStefano Zampini 591db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()` 5923100ebe3SStefano Zampini @*/ 5933100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) 5943100ebe3SStefano Zampini { 5953100ebe3SStefano Zampini PetscFunctionBegin; 5963100ebe3SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5973100ebe3SStefano Zampini PetscValidPointer(is,2); 598cac4c232SBarry Smith PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is)); 5993100ebe3SStefano Zampini PetscFunctionReturn(0); 6003100ebe3SStefano Zampini } 6013100ebe3SStefano Zampini 6024fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k) 6034fad6a16SStefano Zampini { 6044fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 6054fad6a16SStefano Zampini 6064fad6a16SStefano Zampini PetscFunctionBegin; 6074fad6a16SStefano Zampini pcbddc->coarsening_ratio = k; 6084fad6a16SStefano Zampini PetscFunctionReturn(0); 6094fad6a16SStefano Zampini } 6101e6b0712SBarry Smith 6114fad6a16SStefano Zampini /*@ 61228509bceSStefano Zampini PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel 6134fad6a16SStefano Zampini 6144fad6a16SStefano Zampini Logically collective on PC 6154fad6a16SStefano Zampini 6164fad6a16SStefano Zampini Input Parameters: 6174fad6a16SStefano Zampini + pc - the preconditioning context 61828509bceSStefano Zampini - k - coarsening ratio (H/h at the coarser level) 6194fad6a16SStefano Zampini 6200f202f7eSStefano Zampini Options Database Keys: 62167b8a455SSatish Balay . -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening 6224fad6a16SStefano Zampini 6234fad6a16SStefano Zampini Level: intermediate 6244fad6a16SStefano Zampini 6254fad6a16SStefano Zampini Notes: 6260f202f7eSStefano Zampini Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level 6274fad6a16SStefano Zampini 628db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()` 6294fad6a16SStefano Zampini @*/ 6304fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k) 6314fad6a16SStefano Zampini { 6324fad6a16SStefano Zampini PetscFunctionBegin; 6334fad6a16SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 6342b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc,k,2); 635cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k)); 6364fad6a16SStefano Zampini PetscFunctionReturn(0); 6374fad6a16SStefano Zampini } 6382b510759SStefano Zampini 639b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 640b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg) 641b8ffe317SStefano Zampini { 642b8ffe317SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 643b8ffe317SStefano Zampini 644b8ffe317SStefano Zampini PetscFunctionBegin; 64585c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = flg; 646b8ffe317SStefano Zampini PetscFunctionReturn(0); 647b8ffe317SStefano Zampini } 648b8ffe317SStefano Zampini 649b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg) 6502b510759SStefano Zampini { 6512b510759SStefano Zampini PetscFunctionBegin; 6522b510759SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 653b8ffe317SStefano Zampini PetscValidLogicalCollectiveBool(pc,flg,2); 654cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg)); 6552b510759SStefano Zampini PetscFunctionReturn(0); 6562b510759SStefano Zampini } 6571e6b0712SBarry Smith 6582b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level) 6594fad6a16SStefano Zampini { 6604fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 6614fad6a16SStefano Zampini 6624fad6a16SStefano Zampini PetscFunctionBegin; 6632b510759SStefano Zampini pcbddc->current_level = level; 6644fad6a16SStefano Zampini PetscFunctionReturn(0); 6654fad6a16SStefano Zampini } 6661e6b0712SBarry Smith 667b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level) 668b8ffe317SStefano Zampini { 669b8ffe317SStefano Zampini PetscFunctionBegin; 670b8ffe317SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 671b8ffe317SStefano Zampini PetscValidLogicalCollectiveInt(pc,level,2); 672cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level)); 673b8ffe317SStefano Zampini PetscFunctionReturn(0); 674b8ffe317SStefano Zampini } 675b8ffe317SStefano Zampini 6762b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels) 6772b510759SStefano Zampini { 6782b510759SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 6792b510759SStefano Zampini 6802b510759SStefano Zampini PetscFunctionBegin; 6817827d75bSBarry 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); 6822b510759SStefano Zampini pcbddc->max_levels = levels; 6832b510759SStefano Zampini PetscFunctionReturn(0); 6842b510759SStefano Zampini } 6852b510759SStefano Zampini 6864fad6a16SStefano Zampini /*@ 68737ebbdf7SStefano Zampini PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC 6884fad6a16SStefano Zampini 6894fad6a16SStefano Zampini Logically collective on PC 6904fad6a16SStefano Zampini 6914fad6a16SStefano Zampini Input Parameters: 6924fad6a16SStefano Zampini + pc - the preconditioning context 69337ebbdf7SStefano Zampini - levels - the maximum number of levels 6944fad6a16SStefano Zampini 6950f202f7eSStefano Zampini Options Database Keys: 69667b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel 6974fad6a16SStefano Zampini 6984fad6a16SStefano Zampini Level: intermediate 6994fad6a16SStefano Zampini 7004fad6a16SStefano Zampini Notes: 70137ebbdf7SStefano Zampini The default value is 0, that gives the classical two-levels BDDC 7024fad6a16SStefano Zampini 703db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()` 7044fad6a16SStefano Zampini @*/ 7052b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels) 7064fad6a16SStefano Zampini { 7074fad6a16SStefano Zampini PetscFunctionBegin; 7084fad6a16SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 7092b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc,levels,2); 710cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels)); 7114fad6a16SStefano Zampini PetscFunctionReturn(0); 7124fad6a16SStefano Zampini } 7131e6b0712SBarry Smith 7143b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries) 7153b03a366Sstefano_zampini { 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)); 72156282151SStefano Zampini if (pcbddc->DirichletBoundaries) { 7229566063dSJacob Faibussowitsch PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal)); 72356282151SStefano Zampini } 724a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 72736e030ebSStefano Zampini pcbddc->DirichletBoundaries = DirichletBoundaries; 72856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7293b03a366Sstefano_zampini PetscFunctionReturn(0); 7303b03a366Sstefano_zampini } 7311e6b0712SBarry Smith 7323b03a366Sstefano_zampini /*@ 73328509bceSStefano Zampini PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem. 7343b03a366Sstefano_zampini 735785d1243SStefano Zampini Collective 7363b03a366Sstefano_zampini 7373b03a366Sstefano_zampini Input Parameters: 7383b03a366Sstefano_zampini + pc - the preconditioning context 739785d1243SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries 7403b03a366Sstefano_zampini 7413b03a366Sstefano_zampini Level: intermediate 7423b03a366Sstefano_zampini 7430f202f7eSStefano Zampini Notes: 7440f202f7eSStefano Zampini Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node 7453b03a366Sstefano_zampini 746db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7473b03a366Sstefano_zampini @*/ 7483b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries) 7493b03a366Sstefano_zampini { 7503b03a366Sstefano_zampini PetscFunctionBegin; 7513b03a366Sstefano_zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 752674ae819SStefano Zampini PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 753785d1243SStefano Zampini PetscCheckSameComm(pc,1,DirichletBoundaries,2); 754cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries)); 7553b03a366Sstefano_zampini PetscFunctionReturn(0); 7563b03a366Sstefano_zampini } 7571e6b0712SBarry Smith 75882ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries) 7593b03a366Sstefano_zampini { 7603b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 76156282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7623b03a366Sstefano_zampini 7633b03a366Sstefano_zampini PetscFunctionBegin; 7649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 76556282151SStefano Zampini if (pcbddc->DirichletBoundariesLocal) { 7669566063dSJacob Faibussowitsch PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal)); 76756282151SStefano Zampini } 768a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 771785d1243SStefano Zampini pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 77256282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7733b03a366Sstefano_zampini PetscFunctionReturn(0); 7743b03a366Sstefano_zampini } 7753b03a366Sstefano_zampini 7763b03a366Sstefano_zampini /*@ 77782ba6b80SStefano Zampini PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering. 7783b03a366Sstefano_zampini 779785d1243SStefano Zampini Collective 7803b03a366Sstefano_zampini 7813b03a366Sstefano_zampini Input Parameters: 7823b03a366Sstefano_zampini + pc - the preconditioning context 78382ba6b80SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering) 7843b03a366Sstefano_zampini 7853b03a366Sstefano_zampini Level: intermediate 7863b03a366Sstefano_zampini 7873b03a366Sstefano_zampini Notes: 7883b03a366Sstefano_zampini 789db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7903b03a366Sstefano_zampini @*/ 79182ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries) 7923b03a366Sstefano_zampini { 7933b03a366Sstefano_zampini PetscFunctionBegin; 7943b03a366Sstefano_zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 7953b03a366Sstefano_zampini PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 79682ba6b80SStefano Zampini PetscCheckSameComm(pc,1,DirichletBoundaries,2); 797cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries)); 7983b03a366Sstefano_zampini PetscFunctionReturn(0); 7993b03a366Sstefano_zampini } 8003b03a366Sstefano_zampini 80153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries) 8020c7d97c5SJed Brown { 8030c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 80456282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 8050c7d97c5SJed Brown 8060c7d97c5SJed Brown PetscFunctionBegin; 8079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 80856282151SStefano Zampini if (pcbddc->NeumannBoundaries) { 8099566063dSJacob Faibussowitsch PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal)); 81056282151SStefano Zampini } 811a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 8129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 8139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 81436e030ebSStefano Zampini pcbddc->NeumannBoundaries = NeumannBoundaries; 81556282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 8160c7d97c5SJed Brown PetscFunctionReturn(0); 8170c7d97c5SJed Brown } 8181e6b0712SBarry Smith 81957527edcSJed Brown /*@ 82028509bceSStefano Zampini PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem. 82157527edcSJed Brown 822785d1243SStefano Zampini Collective 82357527edcSJed Brown 82457527edcSJed Brown Input Parameters: 82557527edcSJed Brown + pc - the preconditioning context 826785d1243SStefano Zampini - NeumannBoundaries - parallel IS defining the Neumann boundaries 82757527edcSJed Brown 82857527edcSJed Brown Level: intermediate 82957527edcSJed Brown 8300f202f7eSStefano Zampini Notes: 8310f202f7eSStefano Zampini Any process can list any global node 83257527edcSJed Brown 833db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()` 83457527edcSJed Brown @*/ 83553cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries) 8360c7d97c5SJed Brown { 8370c7d97c5SJed Brown PetscFunctionBegin; 8380c7d97c5SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 839674ae819SStefano Zampini PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 840785d1243SStefano Zampini PetscCheckSameComm(pc,1,NeumannBoundaries,2); 841cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries)); 84253cdbc3dSStefano Zampini PetscFunctionReturn(0); 84353cdbc3dSStefano Zampini } 8441e6b0712SBarry Smith 84582ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries) 8460c7d97c5SJed Brown { 8470c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 84856282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 8490c7d97c5SJed Brown 8500c7d97c5SJed Brown PetscFunctionBegin; 8519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 85256282151SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 8539566063dSJacob Faibussowitsch PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal)); 85456282151SStefano Zampini } 855a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 8569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 8579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 858785d1243SStefano Zampini pcbddc->NeumannBoundariesLocal = NeumannBoundaries; 85956282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 8600c7d97c5SJed Brown PetscFunctionReturn(0); 8610c7d97c5SJed Brown } 8620c7d97c5SJed Brown 8630c7d97c5SJed Brown /*@ 86482ba6b80SStefano Zampini PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering. 8650c7d97c5SJed Brown 866785d1243SStefano Zampini Collective 8670c7d97c5SJed Brown 8680c7d97c5SJed Brown Input Parameters: 8690c7d97c5SJed Brown + pc - the preconditioning context 87082ba6b80SStefano Zampini - NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering) 8710c7d97c5SJed Brown 8720c7d97c5SJed Brown Level: intermediate 8730c7d97c5SJed Brown 8740c7d97c5SJed Brown Notes: 8750c7d97c5SJed Brown 876db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()` 8770c7d97c5SJed Brown @*/ 87882ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries) 8790c7d97c5SJed Brown { 8800c7d97c5SJed Brown PetscFunctionBegin; 8810c7d97c5SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 8820c7d97c5SJed Brown PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 88382ba6b80SStefano Zampini PetscCheckSameComm(pc,1,NeumannBoundaries,2); 884cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries)); 88553cdbc3dSStefano Zampini PetscFunctionReturn(0); 88653cdbc3dSStefano Zampini } 88753cdbc3dSStefano Zampini 888da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries) 889da1bb401SStefano Zampini { 890da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 891da1bb401SStefano Zampini 892da1bb401SStefano Zampini PetscFunctionBegin; 893da1bb401SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundaries; 894da1bb401SStefano Zampini PetscFunctionReturn(0); 895da1bb401SStefano Zampini } 8961e6b0712SBarry Smith 897da1bb401SStefano Zampini /*@ 898785d1243SStefano Zampini PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries 899da1bb401SStefano Zampini 900785d1243SStefano Zampini Collective 901785d1243SStefano Zampini 902785d1243SStefano Zampini Input Parameters: 903785d1243SStefano Zampini . pc - the preconditioning context 904785d1243SStefano Zampini 905785d1243SStefano Zampini Output Parameters: 906785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries 907785d1243SStefano Zampini 908785d1243SStefano Zampini Level: intermediate 909785d1243SStefano Zampini 9100f202f7eSStefano Zampini Notes: 9110f202f7eSStefano Zampini The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries 912785d1243SStefano Zampini 913db781477SPatrick Sanan .seealso: `PCBDDC` 914785d1243SStefano Zampini @*/ 915785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries) 916785d1243SStefano Zampini { 917785d1243SStefano Zampini PetscFunctionBegin; 918785d1243SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 919cac4c232SBarry Smith PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries)); 920785d1243SStefano Zampini PetscFunctionReturn(0); 921785d1243SStefano Zampini } 922785d1243SStefano Zampini 923785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries) 924785d1243SStefano Zampini { 925785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 926785d1243SStefano Zampini 927785d1243SStefano Zampini PetscFunctionBegin; 928785d1243SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 929785d1243SStefano Zampini PetscFunctionReturn(0); 930785d1243SStefano Zampini } 931785d1243SStefano Zampini 932da1bb401SStefano Zampini /*@ 93382ba6b80SStefano Zampini PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering) 934da1bb401SStefano Zampini 935785d1243SStefano Zampini Collective 936da1bb401SStefano Zampini 937da1bb401SStefano Zampini Input Parameters: 93828509bceSStefano Zampini . pc - the preconditioning context 939da1bb401SStefano Zampini 940da1bb401SStefano Zampini Output Parameters: 94128509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 942da1bb401SStefano Zampini 943da1bb401SStefano Zampini Level: intermediate 944da1bb401SStefano Zampini 945da1bb401SStefano Zampini Notes: 9460f202f7eSStefano Zampini The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetDirichletBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetDirichletBoundaries). 9470f202f7eSStefano Zampini In the latter case, the IS will be available after PCSetUp. 948da1bb401SStefano Zampini 949db781477SPatrick Sanan .seealso: `PCBDDC` 950da1bb401SStefano Zampini @*/ 95182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries) 952da1bb401SStefano Zampini { 953da1bb401SStefano Zampini PetscFunctionBegin; 954da1bb401SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 955cac4c232SBarry Smith PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries)); 956da1bb401SStefano Zampini PetscFunctionReturn(0); 957da1bb401SStefano Zampini } 9581e6b0712SBarry Smith 95953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries) 96053cdbc3dSStefano Zampini { 96153cdbc3dSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 96253cdbc3dSStefano Zampini 96353cdbc3dSStefano Zampini PetscFunctionBegin; 96453cdbc3dSStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundaries; 96553cdbc3dSStefano Zampini PetscFunctionReturn(0); 96653cdbc3dSStefano Zampini } 9671e6b0712SBarry Smith 96853cdbc3dSStefano Zampini /*@ 969785d1243SStefano Zampini PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries 97053cdbc3dSStefano Zampini 971785d1243SStefano Zampini Collective 972785d1243SStefano Zampini 973785d1243SStefano Zampini Input Parameters: 974785d1243SStefano Zampini . pc - the preconditioning context 975785d1243SStefano Zampini 976785d1243SStefano Zampini Output Parameters: 977785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries 978785d1243SStefano Zampini 979785d1243SStefano Zampini Level: intermediate 980785d1243SStefano Zampini 9810f202f7eSStefano Zampini Notes: 9820f202f7eSStefano Zampini The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries 983785d1243SStefano Zampini 984db781477SPatrick Sanan .seealso: `PCBDDC` 985785d1243SStefano Zampini @*/ 986785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries) 987785d1243SStefano Zampini { 988785d1243SStefano Zampini PetscFunctionBegin; 989785d1243SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 990cac4c232SBarry Smith PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries)); 991785d1243SStefano Zampini PetscFunctionReturn(0); 992785d1243SStefano Zampini } 993785d1243SStefano Zampini 994785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries) 995785d1243SStefano Zampini { 996785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 997785d1243SStefano Zampini 998785d1243SStefano Zampini PetscFunctionBegin; 999785d1243SStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 1000785d1243SStefano Zampini PetscFunctionReturn(0); 1001785d1243SStefano Zampini } 1002785d1243SStefano Zampini 100353cdbc3dSStefano Zampini /*@ 100482ba6b80SStefano Zampini PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering) 100553cdbc3dSStefano Zampini 1006785d1243SStefano Zampini Collective 100753cdbc3dSStefano Zampini 100853cdbc3dSStefano Zampini Input Parameters: 100928509bceSStefano Zampini . pc - the preconditioning context 101053cdbc3dSStefano Zampini 101153cdbc3dSStefano Zampini Output Parameters: 101228509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 101353cdbc3dSStefano Zampini 101453cdbc3dSStefano Zampini Level: intermediate 101553cdbc3dSStefano Zampini 101653cdbc3dSStefano Zampini Notes: 10170f202f7eSStefano Zampini The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetNeumannBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetNeumannBoundaries). 10180f202f7eSStefano Zampini In the latter case, the IS will be available after PCSetUp. 101953cdbc3dSStefano Zampini 1020db781477SPatrick Sanan .seealso: `PCBDDC` 102153cdbc3dSStefano Zampini @*/ 102282ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries) 102353cdbc3dSStefano Zampini { 102453cdbc3dSStefano Zampini PetscFunctionBegin; 102553cdbc3dSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1026cac4c232SBarry Smith PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries)); 10270c7d97c5SJed Brown PetscFunctionReturn(0); 10280c7d97c5SJed Brown } 10291e6b0712SBarry Smith 10301a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 103136e030ebSStefano Zampini { 103236e030ebSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1033da1bb401SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 103456282151SStefano Zampini PetscBool same_data = PETSC_FALSE; 103536e030ebSStefano Zampini 103636e030ebSStefano Zampini PetscFunctionBegin; 10378687889aSStefano Zampini if (!nvtxs) { 103804194a47SStefano Zampini if (copymode == PETSC_OWN_POINTER) { 10399566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 10409566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 104104194a47SStefano Zampini } 10429566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 10438687889aSStefano Zampini PetscFunctionReturn(0); 10448687889aSStefano Zampini } 104566da6bd7Sstefano_zampini if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */ 104656282151SStefano Zampini if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE; 104756282151SStefano Zampini if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) { 10489566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data)); 10492d505d7fSStefano Zampini if (same_data) { 10509566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data)); 10512d505d7fSStefano Zampini } 105256282151SStefano Zampini } 105356282151SStefano Zampini } 105456282151SStefano Zampini if (!same_data) { 1055674ae819SStefano Zampini /* free old CSR */ 10569566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 1057674ae819SStefano Zampini /* get CSR into graph structure */ 1058da1bb401SStefano Zampini if (copymode == PETSC_COPY_VALUES) { 10599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nvtxs+1,&mat_graph->xadj)); 10609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy)); 10619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1)); 10629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs])); 1063a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1064da1bb401SStefano Zampini } else if (copymode == PETSC_OWN_POINTER) { 10651a83f524SJed Brown mat_graph->xadj = (PetscInt*)xadj; 10661a83f524SJed Brown mat_graph->adjncy = (PetscInt*)adjncy; 1067a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1068a1dbd327SStefano Zampini } else if (copymode == PETSC_USE_POINTER) { 1069a1dbd327SStefano Zampini mat_graph->xadj = (PetscInt*)xadj; 1070a1dbd327SStefano Zampini mat_graph->adjncy = (PetscInt*)adjncy; 1071a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_FALSE; 107263a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d",copymode); 1073575ad6abSStefano Zampini mat_graph->nvtxs_csr = nvtxs; 107456282151SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 107556282151SStefano Zampini } 107636e030ebSStefano Zampini PetscFunctionReturn(0); 107736e030ebSStefano Zampini } 10781e6b0712SBarry Smith 107936e030ebSStefano Zampini /*@ 108054fffbccSStefano Zampini PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom. 108136e030ebSStefano Zampini 108236e030ebSStefano Zampini Not collective 108336e030ebSStefano Zampini 108436e030ebSStefano Zampini Input Parameters: 108554fffbccSStefano Zampini + pc - the preconditioning context. 108654fffbccSStefano Zampini . nvtxs - number of local vertices of the graph (i.e., the number of local dofs). 108754fffbccSStefano Zampini . xadj, adjncy - the connectivity of the dofs in CSR format. 108854fffbccSStefano Zampini - copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER. 108936e030ebSStefano Zampini 109036e030ebSStefano Zampini Level: intermediate 109136e030ebSStefano Zampini 109295452b02SPatrick Sanan Notes: 109395452b02SPatrick Sanan A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative. 109436e030ebSStefano Zampini 109516b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode` 109636e030ebSStefano Zampini @*/ 10971a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 109836e030ebSStefano Zampini { 10990a545947SLisandro Dalcin void (*f)(void) = NULL; 110036e030ebSStefano Zampini 110136e030ebSStefano Zampini PetscFunctionBegin; 110236e030ebSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 11038687889aSStefano Zampini if (nvtxs) { 1104674ae819SStefano Zampini PetscValidIntPointer(xadj,3); 11051633d1f0SStefano Zampini if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4); 11068687889aSStefano Zampini } 1107cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode)); 1108575ad6abSStefano Zampini /* free arrays if PCBDDC is not the PC type */ 11099566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f)); 1110575ad6abSStefano Zampini if (!f && copymode == PETSC_OWN_POINTER) { 11119566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 11129566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 1113da1bb401SStefano Zampini } 111436e030ebSStefano Zampini PetscFunctionReturn(0); 111536e030ebSStefano Zampini } 11161e6b0712SBarry Smith 111763602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 111863602bcaSStefano Zampini { 111963602bcaSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 112063602bcaSStefano Zampini PetscInt i; 112156282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 112263602bcaSStefano Zampini 112363602bcaSStefano Zampini PetscFunctionBegin; 112456282151SStefano Zampini if (pcbddc->n_ISForDofsLocal == n_is) { 112556282151SStefano Zampini for (i=0;i<n_is;i++) { 112656282151SStefano Zampini PetscBool isequalt; 11279566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt)); 112856282151SStefano Zampini if (!isequalt) break; 112956282151SStefano Zampini } 113056282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 113156282151SStefano Zampini } 113256282151SStefano Zampini for (i=0;i<n_is;i++) { 11339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 113456282151SStefano Zampini } 113563602bcaSStefano Zampini /* Destroy ISes if they were already set */ 113663602bcaSStefano Zampini for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 11379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 113863602bcaSStefano Zampini } 11399566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 1140a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 114163602bcaSStefano Zampini for (i=0;i<pcbddc->n_ISForDofs;i++) { 11429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 114363602bcaSStefano Zampini } 11449566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 114563602bcaSStefano Zampini pcbddc->n_ISForDofs = 0; 114663602bcaSStefano Zampini /* allocate space then set */ 1147d02579f5SStefano Zampini if (n_is) { 11489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofsLocal)); 1149d02579f5SStefano Zampini } 115063602bcaSStefano Zampini for (i=0;i<n_is;i++) { 115163602bcaSStefano Zampini pcbddc->ISForDofsLocal[i] = ISForDofs[i]; 115263602bcaSStefano Zampini } 115363602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = n_is; 115463602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 115556282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 115663602bcaSStefano Zampini PetscFunctionReturn(0); 115763602bcaSStefano Zampini } 115863602bcaSStefano Zampini 115963602bcaSStefano Zampini /*@ 116063602bcaSStefano Zampini PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix 116163602bcaSStefano Zampini 116263602bcaSStefano Zampini Collective 116363602bcaSStefano Zampini 116463602bcaSStefano Zampini Input Parameters: 116563602bcaSStefano Zampini + pc - the preconditioning context 11660f202f7eSStefano Zampini . n_is - number of index sets defining the fields 11670f202f7eSStefano Zampini - ISForDofs - array of IS describing the fields in local ordering 116863602bcaSStefano Zampini 116963602bcaSStefano Zampini Level: intermediate 117063602bcaSStefano Zampini 11710f202f7eSStefano Zampini Notes: 11720f202f7eSStefano Zampini n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 117363602bcaSStefano Zampini 1174db781477SPatrick Sanan .seealso: `PCBDDC` 117563602bcaSStefano Zampini @*/ 117663602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[]) 117763602bcaSStefano Zampini { 117863602bcaSStefano Zampini PetscInt i; 117963602bcaSStefano Zampini 118063602bcaSStefano Zampini PetscFunctionBegin; 118163602bcaSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 118263602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc,n_is,2); 118363602bcaSStefano Zampini for (i=0;i<n_is;i++) { 118463602bcaSStefano Zampini PetscCheckSameComm(pc,1,ISForDofs[i],3); 118563602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 118663602bcaSStefano Zampini } 1187cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs)); 118863602bcaSStefano Zampini PetscFunctionReturn(0); 118963602bcaSStefano Zampini } 119063602bcaSStefano Zampini 11919c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 11929c0446d6SStefano Zampini { 11939c0446d6SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 11949c0446d6SStefano Zampini PetscInt i; 119556282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 11969c0446d6SStefano Zampini 11979c0446d6SStefano Zampini PetscFunctionBegin; 119856282151SStefano Zampini if (pcbddc->n_ISForDofs == n_is) { 119956282151SStefano Zampini for (i=0;i<n_is;i++) { 120056282151SStefano Zampini PetscBool isequalt; 12019566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt)); 120256282151SStefano Zampini if (!isequalt) break; 120356282151SStefano Zampini } 120456282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 120556282151SStefano Zampini } 120656282151SStefano Zampini for (i=0;i<n_is;i++) { 12079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 120856282151SStefano Zampini } 1209da1bb401SStefano Zampini /* Destroy ISes if they were already set */ 12109c0446d6SStefano Zampini for (i=0;i<pcbddc->n_ISForDofs;i++) { 12119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 12129c0446d6SStefano Zampini } 12139566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 1214a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 121563602bcaSStefano Zampini for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 12169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 121763602bcaSStefano Zampini } 12189566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 121963602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = 0; 1220da1bb401SStefano Zampini /* allocate space then set */ 1221d02579f5SStefano Zampini if (n_is) { 12229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofs)); 1223d02579f5SStefano Zampini } 12249c0446d6SStefano Zampini for (i=0;i<n_is;i++) { 1225da1bb401SStefano Zampini pcbddc->ISForDofs[i] = ISForDofs[i]; 12269c0446d6SStefano Zampini } 12279c0446d6SStefano Zampini pcbddc->n_ISForDofs = n_is; 122863602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 122956282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 12309c0446d6SStefano Zampini PetscFunctionReturn(0); 12319c0446d6SStefano Zampini } 12321e6b0712SBarry Smith 12339c0446d6SStefano Zampini /*@ 123463602bcaSStefano Zampini PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix 12359c0446d6SStefano Zampini 123663602bcaSStefano Zampini Collective 12379c0446d6SStefano Zampini 12389c0446d6SStefano Zampini Input Parameters: 12399c0446d6SStefano Zampini + pc - the preconditioning context 12400f202f7eSStefano Zampini . n_is - number of index sets defining the fields 12410f202f7eSStefano Zampini - ISForDofs - array of IS describing the fields in global ordering 12429c0446d6SStefano Zampini 12439c0446d6SStefano Zampini Level: intermediate 12449c0446d6SStefano Zampini 12450f202f7eSStefano Zampini Notes: 12460f202f7eSStefano Zampini Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 12479c0446d6SStefano Zampini 1248db781477SPatrick Sanan .seealso: `PCBDDC` 12499c0446d6SStefano Zampini @*/ 12509c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[]) 12519c0446d6SStefano Zampini { 12522b510759SStefano Zampini PetscInt i; 12539c0446d6SStefano Zampini 12549c0446d6SStefano Zampini PetscFunctionBegin; 12559c0446d6SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 125663602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc,n_is,2); 12572b510759SStefano Zampini for (i=0;i<n_is;i++) { 125863602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 1259a011d5a7Sstefano_zampini PetscCheckSameComm(pc,1,ISForDofs[i],3); 12602b510759SStefano Zampini } 1261cac4c232SBarry Smith PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs)); 12629c0446d6SStefano Zampini PetscFunctionReturn(0); 12639c0446d6SStefano Zampini } 1264906d46d4SStefano Zampini 1265534831adSStefano Zampini /* 1266534831adSStefano Zampini PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 1267534831adSStefano Zampini guess if a transformation of basis approach has been selected. 12689c0446d6SStefano Zampini 1269534831adSStefano Zampini Input Parameter: 1270966d8056SPierre Jolivet + pc - the preconditioner context 1271534831adSStefano Zampini 1272534831adSStefano Zampini Application Interface Routine: PCPreSolve() 1273534831adSStefano Zampini 1274534831adSStefano Zampini Notes: 1275534831adSStefano Zampini The interface routine PCPreSolve() is not usually called directly by 1276534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1277534831adSStefano Zampini */ 1278534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1279534831adSStefano Zampini { 1280534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1281534831adSStefano Zampini PC_IS *pcis = (PC_IS*)(pc->data); 12823972b0daSStefano Zampini Vec used_vec; 1283fcb54b1cSPierre Jolivet PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed; 1284534831adSStefano Zampini 1285534831adSStefano Zampini PetscFunctionBegin; 12861f4df5f7SStefano Zampini /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */ 128785c4d303SStefano Zampini if (ksp) { 1288fcb54b1cSPierre Jolivet PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp,&iscg,KSPCG,KSPGROPPCG,KSPPIPECG,KSPPIPELCG,KSPPIPECGRR,"")); 12893bf6e316SStefano Zampini if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) { 12909566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE)); 129185c4d303SStefano Zampini } 129285c4d303SStefano Zampini } 12933bf6e316SStefano Zampini if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) { 12949566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE)); 1295fc17d649SStefano Zampini } 12961f4df5f7SStefano Zampini 129785c4d303SStefano Zampini /* Creates parallel work vectors used in presolve */ 129862a6ff1dSStefano Zampini if (!pcbddc->original_rhs) { 12999566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs)); 130062a6ff1dSStefano Zampini } 130162a6ff1dSStefano Zampini if (!pcbddc->temp_solution) { 13029566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution)); 130362a6ff1dSStefano Zampini } 13048d00608fSStefano Zampini 130527b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_FALSE; 13063972b0daSStefano Zampini if (x) { 13079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)x)); 13083972b0daSStefano Zampini used_vec = x; 13098d00608fSStefano Zampini } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 13109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution)); 13113972b0daSStefano Zampini used_vec = pcbddc->temp_solution; 13129566063dSJacob Faibussowitsch PetscCall(VecSet(used_vec,0.0)); 131327b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 13149566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs,pcbddc->original_rhs)); 1315266e20e9SStefano Zampini save_rhs = PETSC_FALSE; 1316266e20e9SStefano Zampini pcbddc->eliminate_dirdofs = PETSC_TRUE; 13173972b0daSStefano Zampini } 13188efcfb23SStefano Zampini 13198efcfb23SStefano Zampini /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 13203972b0daSStefano Zampini if (ksp) { 1321a0cb1b98SStefano Zampini /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 13229566063dSJacob Faibussowitsch PetscCall(KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero)); 13238efcfb23SStefano Zampini if (!pcbddc->ksp_guess_nonzero) { 13249566063dSJacob Faibussowitsch PetscCall(VecSet(used_vec,0.0)); 13253972b0daSStefano Zampini } 13263972b0daSStefano Zampini } 13273308cffdSStefano Zampini 13288d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 13293972b0daSStefano Zampini /* Take into account zeroed rows -> change rhs and store solution removed */ 133070c64980SStefano Zampini if (rhs && pcbddc->eliminate_dirdofs) { 13313975b054SStefano Zampini IS dirIS = NULL; 13323975b054SStefano Zampini 1333a07ea27aSStefano Zampini /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 13349566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS)); 13353975b054SStefano Zampini if (dirIS) { 1336906d46d4SStefano Zampini Mat_IS *matis = (Mat_IS*)pc->pmat->data; 1337785d1243SStefano Zampini PetscInt dirsize,i,*is_indices; 13382b095fd8SStefano Zampini PetscScalar *array_x; 13392b095fd8SStefano Zampini const PetscScalar *array_diagonal; 1340785d1243SStefano Zampini 13419566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(pc->pmat,pcis->vec1_global)); 13429566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global)); 13439566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD)); 13449566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD)); 13459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 13469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 13479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS,&dirsize)); 13489566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N,&array_x)); 13499566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->vec2_N,&array_diagonal)); 13509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS,(const PetscInt**)&is_indices)); 13512fa5cd67SKarl Rupp for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 13529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS,(const PetscInt**)&is_indices)); 13539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->vec2_N,&array_diagonal)); 13549566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N,&array_x)); 13559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE)); 13569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE)); 13578d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 13589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 13598efcfb23SStefano Zampini } 1360a07ea27aSStefano Zampini } 1361b76ba322SStefano Zampini 13628efcfb23SStefano Zampini /* remove the computed solution or the initial guess from the rhs */ 13638d00608fSStefano Zampini if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) { 136427b6a85dSStefano Zampini /* save the original rhs */ 136527b6a85dSStefano Zampini if (save_rhs) { 13669566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs,pcbddc->original_rhs)); 136727b6a85dSStefano Zampini save_rhs = PETSC_FALSE; 13688d00608fSStefano Zampini } 13698d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 13709566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec,-1.0)); 13719566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs)); 13729566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec,-1.0)); 13739566063dSJacob Faibussowitsch PetscCall(VecCopy(used_vec,pcbddc->temp_solution)); 137427b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 1375*1baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_FALSE)); 13763308cffdSStefano Zampini } 13779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&used_vec)); 1378b76ba322SStefano Zampini 1379fc17d649SStefano Zampini /* compute initial vector in benign space if needed 138027b6a85dSStefano Zampini and remove non-benign solution from the rhs */ 138127b6a85dSStefano Zampini benign_correction_computed = PETSC_FALSE; 138208af2428SStefano Zampini if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) { 13831f4df5f7SStefano Zampini /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1) 13841f4df5f7SStefano Zampini Recursively apply BDDC in the multilevel case */ 13850369aaf7SStefano Zampini if (!pcbddc->benign_vec) { 13869566063dSJacob Faibussowitsch PetscCall(VecDuplicate(rhs,&pcbddc->benign_vec)); 13870369aaf7SStefano Zampini } 1388c69e9cc1SStefano Zampini /* keep applying coarse solver unless we no longer have benign subdomains */ 1389c69e9cc1SStefano Zampini pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE; 139027b6a85dSStefano Zampini if (!pcbddc->benign_skip_correction) { 13919566063dSJacob Faibussowitsch PetscCall(PCApply_BDDC(pc,rhs,pcbddc->benign_vec)); 13923bca92a6SStefano Zampini benign_correction_computed = PETSC_TRUE; 1393*1baa6e33SBarry Smith if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec)); 13949566063dSJacob Faibussowitsch PetscCall(VecScale(pcbddc->benign_vec,-1.0)); 139527b6a85dSStefano Zampini /* store the original rhs if not done earlier */ 1396*1baa6e33SBarry Smith if (save_rhs) PetscCall(VecSwap(rhs,pcbddc->original_rhs)); 139727b6a85dSStefano Zampini if (pcbddc->rhs_change) { 13989566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs)); 139927b6a85dSStefano Zampini } else { 14009566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs)); 140127b6a85dSStefano Zampini } 14020369aaf7SStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 140327b6a85dSStefano Zampini } 140427b6a85dSStefano Zampini pcbddc->benign_apply_coarse_only = PETSC_FALSE; 14054df7a6bfSStefano Zampini } else { 14069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 14070369aaf7SStefano Zampini } 14082d4c4fecSStefano Zampini 14092d4c4fecSStefano Zampini /* dbg output */ 1410a198735bSStefano Zampini if (pcbddc->dbg_flag && benign_correction_computed) { 14111f4df5f7SStefano Zampini Vec v; 1412c69e9cc1SStefano Zampini 14139566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&v)); 1414c69e9cc1SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 14159566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v)); 1416c69e9cc1SStefano Zampini } else { 14179566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs,v)); 1418c69e9cc1SStefano Zampini } 14199566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE)); 142063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %" PetscInt_FMT ": is the correction benign?\n",pcbddc->current_level)); 14219566063dSJacob Faibussowitsch PetscCall(PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer)); 14229566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 14239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 14241f4df5f7SStefano Zampini } 14250369aaf7SStefano Zampini 14260369aaf7SStefano Zampini /* set initial guess if using PCG */ 14278ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 14280369aaf7SStefano Zampini if (x && pcbddc->use_exact_dirichlet_trick) { 14299566063dSJacob Faibussowitsch PetscCall(VecSet(x,0.0)); 14301dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 143127b6a85dSStefano Zampini if (benign_correction_computed) { /* we have already saved the changed rhs */ 14329566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 14331dd7afcfSStefano Zampini } else { 14349566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global)); 14351dd7afcfSStefano Zampini } 14369566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14379566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14381dd7afcfSStefano Zampini } else { 14399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14411dd7afcfSStefano Zampini } 14429566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 14439566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D)); 14449566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 14459566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 14461dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 14479566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global,0.)); 14489566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE)); 14499566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE)); 14509566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x)); 14511dd7afcfSStefano Zampini } else { 14529566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE)); 14539566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE)); 14541dd7afcfSStefano Zampini } 1455*1baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_TRUE)); 14568ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_TRUE; 1457266e20e9SStefano Zampini } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) { 14589566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 14590369aaf7SStefano Zampini } 1460534831adSStefano Zampini PetscFunctionReturn(0); 1461534831adSStefano Zampini } 1462906d46d4SStefano Zampini 1463534831adSStefano Zampini /* 1464534831adSStefano Zampini PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1465534831adSStefano Zampini approach has been selected. Also, restores rhs to its original state. 1466534831adSStefano Zampini 1467534831adSStefano Zampini Input Parameter: 1468966d8056SPierre Jolivet + pc - the preconditioner context 1469534831adSStefano Zampini 1470534831adSStefano Zampini Application Interface Routine: PCPostSolve() 1471534831adSStefano Zampini 1472534831adSStefano Zampini Notes: 1473534831adSStefano Zampini The interface routine PCPostSolve() is not usually called directly by 1474534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1475534831adSStefano Zampini */ 1476534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1477534831adSStefano Zampini { 1478534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1479534831adSStefano Zampini 1480534831adSStefano Zampini PetscFunctionBegin; 14813972b0daSStefano Zampini /* add solution removed in presolve */ 14826bcfc461SStefano Zampini if (x && pcbddc->rhs_change) { 148327b6a85dSStefano Zampini if (pcbddc->temp_solution_used) { 14849566063dSJacob Faibussowitsch PetscCall(VecAXPY(x,1.0,pcbddc->temp_solution)); 1485af140850Sstefano_zampini } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) { 14869566063dSJacob Faibussowitsch PetscCall(VecAXPY(x,-1.0,pcbddc->benign_vec)); 14873425bc38SStefano Zampini } 1488af140850Sstefano_zampini /* restore to original state (not for FETI-DP) */ 1489af140850Sstefano_zampini if (ksp) pcbddc->temp_solution_used = PETSC_FALSE; 149027b6a85dSStefano Zampini } 149127b6a85dSStefano Zampini 1492266e20e9SStefano Zampini /* restore rhs to its original state (not needed for FETI-DP) */ 14938d00608fSStefano Zampini if (rhs && pcbddc->rhs_change) { 14949566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs,pcbddc->original_rhs)); 14958d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 1496af140850Sstefano_zampini } 14978efcfb23SStefano Zampini /* restore ksp guess state */ 14988efcfb23SStefano Zampini if (ksp) { 14999566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero)); 15008ae0ca82SStefano Zampini /* reset flag for exact dirichlet trick */ 15018ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 1502af140850Sstefano_zampini } 1503534831adSStefano Zampini PetscFunctionReturn(0); 1504534831adSStefano Zampini } 1505af140850Sstefano_zampini 15060c7d97c5SJed Brown /* 15070c7d97c5SJed Brown PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 15080c7d97c5SJed Brown by setting data structures and options. 15090c7d97c5SJed Brown 15100c7d97c5SJed Brown Input Parameter: 151153cdbc3dSStefano Zampini + pc - the preconditioner context 15120c7d97c5SJed Brown 15130c7d97c5SJed Brown Application Interface Routine: PCSetUp() 15140c7d97c5SJed Brown 15150c7d97c5SJed Brown Notes: 15160c7d97c5SJed Brown The interface routine PCSetUp() is not usually called directly by 15170c7d97c5SJed Brown the user, but instead is called by PCApply() if necessary. 15180c7d97c5SJed Brown */ 151953cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc) 15200c7d97c5SJed Brown { 15210c7d97c5SJed Brown PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 1522c703fcc7SStefano Zampini PCBDDCSubSchurs sub_schurs; 15235e8657edSStefano Zampini Mat_IS* matis; 152408122e43SStefano Zampini MatNullSpace nearnullspace; 152535509ce9Sstefano_zampini Mat lA; 152635509ce9Sstefano_zampini IS lP,zerodiag = NULL; 152791e8d312SStefano Zampini PetscInt nrows,ncols; 152886bfa4cfSStefano Zampini PetscMPIInt size; 1529c703fcc7SStefano Zampini PetscBool computesubschurs; 15308de1fae6SStefano Zampini PetscBool computeconstraintsmatrix; 15313b03f7bbSStefano Zampini PetscBool new_nearnullspace_provided,ismatis,rl; 15320c7d97c5SJed Brown 15330c7d97c5SJed Brown PetscFunctionBegin; 15349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis)); 153528b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS"); 15369566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat,&nrows,&ncols)); 15377827d75bSBarry Smith PetscCheck(nrows == ncols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix"); 15389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size)); 153986bfa4cfSStefano Zampini 15405e8657edSStefano Zampini matis = (Mat_IS*)pc->pmat->data; 1541f4ddd8eeSStefano Zampini /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 15423b03a366Sstefano_zampini /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 154371582508SStefano Zampini Also, BDDC builds its own KSP for the Dirichlet problem */ 15443b03f7bbSStefano Zampini rl = pcbddc->recompute_topography; 15453b03f7bbSStefano Zampini if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE; 15461c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 1547c83e1ba7SStefano Zampini if (pcbddc->recompute_topography) { 1548c83e1ba7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 1549c83e1ba7SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1550c83e1ba7SStefano Zampini } else { 15518de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_FALSE; 1552c83e1ba7SStefano Zampini } 1553b087196eSStefano Zampini 1554b087196eSStefano Zampini /* check parameters' compatibility */ 1555b7ab4a40SStefano Zampini if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE; 1556bd2a564bSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0); 155786bfa4cfSStefano Zampini pcbddc->use_deluxe_scaling = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1); 155886bfa4cfSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_selection && size > 1); 1559bf3a8328SStefano Zampini pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined); 1560862806e4SStefano Zampini if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1561862806e4SStefano Zampini 15625a95e1ceSStefano Zampini computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 156316909a7fSStefano Zampini 156471582508SStefano Zampini /* activate all connected components if the netflux has been requested */ 1565bb05f991SStefano Zampini if (pcbddc->compute_nonetflux) { 1566bb05f991SStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 1567bb05f991SStefano Zampini pcbddc->use_edges = PETSC_TRUE; 1568bb05f991SStefano Zampini pcbddc->use_faces = PETSC_TRUE; 1569bb05f991SStefano Zampini } 1570bb05f991SStefano Zampini 1571f4ddd8eeSStefano Zampini /* Get stdout for dbg */ 157270cf5478SStefano Zampini if (pcbddc->dbg_flag) { 157370cf5478SStefano Zampini if (!pcbddc->dbg_viewer) { 157458a03d70SStefano Zampini pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 1575f4ddd8eeSStefano Zampini } 15769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 15779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level)); 1578f4ddd8eeSStefano Zampini } 1579f4ddd8eeSStefano Zampini 1580c703fcc7SStefano Zampini /* process topology information */ 15819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0)); 158271582508SStefano Zampini if (pcbddc->recompute_topography) { 15839566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalTopologyInfo(pc)); 1584*1baa6e33SBarry Smith if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc)); 1585c703fcc7SStefano Zampini } 15864f819b78SStefano Zampini if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE; 1587a13144ffSStefano Zampini 1588c703fcc7SStefano Zampini /* change basis if requested by the user */ 15895e8657edSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 15905e8657edSStefano Zampini /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 15915e8657edSStefano Zampini pcbddc->use_change_of_basis = PETSC_FALSE; 15929566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix)); 15935e8657edSStefano Zampini } else { 15949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 15959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 15965e8657edSStefano Zampini pcbddc->local_mat = matis->A; 1597d16cbb6bSStefano Zampini } 1598d16cbb6bSStefano Zampini 15994f1b2e48SStefano Zampini /* 1600c703fcc7SStefano Zampini Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick 16014f1b2e48SStefano Zampini This should come earlier then PCISSetUp for extracting the correct subdomain matrices 16024f1b2e48SStefano Zampini */ 16039566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc,PETSC_TRUE)); 1604d16cbb6bSStefano Zampini if (pcbddc->benign_saddle_point) { 16059f47a83aSStefano Zampini PC_IS* pcis = (PC_IS*)pc->data; 16069f47a83aSStefano Zampini 160705b28244SStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE; 16083b03f7bbSStefano Zampini /* detect local saddle point and change the basis in pcbddc->local_mat */ 16099566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag)); 1610a3df083aSStefano Zampini /* pop B0 mat from local mat */ 16119566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE)); 16121dd7afcfSStefano Zampini /* give pcis a hint to not reuse submatrices during PCISCreate */ 16131dd7afcfSStefano Zampini if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) { 16141dd7afcfSStefano Zampini if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) { 16151dd7afcfSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 16161dd7afcfSStefano Zampini } else { 1617a3df083aSStefano Zampini pcis->reusesubmatrices = PETSC_TRUE; 16181dd7afcfSStefano Zampini } 1619a3df083aSStefano Zampini } else { 16209f47a83aSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 1621674ae819SStefano Zampini } 1622a3df083aSStefano Zampini } 162327b6a85dSStefano Zampini 16248037d520SStefano Zampini /* propagate relevant information */ 1625*1baa6e33SBarry Smith if (matis->A->symmetric_set) PetscCall(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric)); 1626*1baa6e33SBarry Smith if (matis->A->spd_set) PetscCall(MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd)); 1627e496cd5dSStefano Zampini 16285e8657edSStefano Zampini /* Set up all the "iterative substructuring" common block without computing solvers */ 16295e8657edSStefano Zampini { 16305e8657edSStefano Zampini Mat temp_mat; 16315e8657edSStefano Zampini 16325e8657edSStefano Zampini temp_mat = matis->A; 16335e8657edSStefano Zampini matis->A = pcbddc->local_mat; 16349566063dSJacob Faibussowitsch PetscCall(PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE)); 16355e8657edSStefano Zampini pcbddc->local_mat = matis->A; 16365e8657edSStefano Zampini matis->A = temp_mat; 16375e8657edSStefano Zampini } 1638684f6988SStefano Zampini 163981d14e9dSStefano Zampini /* Analyze interface */ 164064ac59b8SStefano Zampini if (!pcbddc->graphanalyzed) { 16419566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 16428de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1643345ecf6cSStefano Zampini if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) { 16444247aa23Sstefano_zampini SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling"); 1645345ecf6cSStefano Zampini } 1646a198735bSStefano Zampini if (pcbddc->compute_nonetflux) { 1647669cc0f4SStefano Zampini MatNullSpace nnfnnsp; 1648669cc0f4SStefano Zampini 164928b400f6SJacob Faibussowitsch PetscCheck(pcbddc->divudotp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator"); 16509566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp)); 165171582508SStefano Zampini /* TODO what if a nearnullspace is already attached? */ 16528037d520SStefano Zampini if (nnfnnsp) { 16539566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(pc->pmat,nnfnnsp)); 16549566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nnfnnsp)); 1655669cc0f4SStefano Zampini } 1656674ae819SStefano Zampini } 16578037d520SStefano Zampini } 16589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0)); 1659fb8d54d4SStefano Zampini 16605408967cSStefano Zampini /* check existence of a divergence free extension, i.e. 16615408967cSStefano Zampini b(v_I,p_0) = 0 for all v_I (raise error if not). 16625408967cSStefano Zampini Also, check that PCBDDCBenignGetOrSetP0 works */ 1663ff1f7e73Sstefano_zampini if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) { 16649566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignCheck(pc,zerodiag)); 166509f581a4SStefano Zampini } 16669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 166706f24817SStefano Zampini 1668b96c3477SStefano Zampini /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 1669c703fcc7SStefano Zampini if (computesubschurs && pcbddc->recompute_topography) { 16709566063dSJacob Faibussowitsch PetscCall(PCBDDCInitSubSchurs(pc)); 1671b1b3d7a2SStefano Zampini } 16729d54b7f4SStefano Zampini /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/ 16739d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) { 16749566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingSetUp(pc)); 16759d54b7f4SStefano Zampini } 1676c703fcc7SStefano Zampini 1677c703fcc7SStefano Zampini /* finish setup solvers and do adaptive selection of constraints */ 1678b334f244SStefano Zampini sub_schurs = pcbddc->sub_schurs; 1679b334f244SStefano Zampini if (sub_schurs && sub_schurs->schur_explicit) { 1680*1baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 16819566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE)); 1682d5574798SStefano Zampini } else { 16839566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE)); 1684*1baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 16852070dbb6SStefano Zampini } 168608122e43SStefano Zampini if (pcbddc->adaptive_selection) { 16879566063dSJacob Faibussowitsch PetscCall(PCBDDCAdaptiveSelection(pc)); 16888de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1689b7eb3628SStefano Zampini } 1690684f6988SStefano Zampini 1691f4ddd8eeSStefano Zampini /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1692fb8d54d4SStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 16939566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat,&nearnullspace)); 1694f4ddd8eeSStefano Zampini if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1695f4ddd8eeSStefano Zampini if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1696f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1697f4ddd8eeSStefano Zampini } else { 1698f4ddd8eeSStefano Zampini /* determine if the two nullspaces are different (should be lightweight) */ 1699f4ddd8eeSStefano Zampini if (nearnullspace != pcbddc->onearnullspace) { 1700f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1701165b64e2SStefano Zampini } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1702f4ddd8eeSStefano Zampini PetscInt i; 1703165b64e2SStefano Zampini const Vec *nearnullvecs; 1704165b64e2SStefano Zampini PetscObjectState state; 1705165b64e2SStefano Zampini PetscInt nnsp_size; 17069566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs)); 1707f4ddd8eeSStefano Zampini for (i=0;i<nnsp_size;i++) { 17089566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i],&state)); 1709165b64e2SStefano Zampini if (pcbddc->onearnullvecs_state[i] != state) { 1710f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1711f4ddd8eeSStefano Zampini break; 1712f4ddd8eeSStefano Zampini } 1713f4ddd8eeSStefano Zampini } 1714f4ddd8eeSStefano Zampini } 1715f4ddd8eeSStefano Zampini } 1716f4ddd8eeSStefano Zampini } else { 1717f4ddd8eeSStefano Zampini if (!nearnullspace) { /* both nearnullspaces are null */ 1718f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 1719f4ddd8eeSStefano Zampini } else { /* nearnullspace attached later */ 1720f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1721f4ddd8eeSStefano Zampini } 1722f4ddd8eeSStefano Zampini } 1723f4ddd8eeSStefano Zampini 1724f4ddd8eeSStefano Zampini /* Setup constraints and related work vectors */ 1725727cdba6SStefano Zampini /* reset primal space flags */ 17269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0)); 1727f4ddd8eeSStefano Zampini pcbddc->new_primal_space = PETSC_FALSE; 1728727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_FALSE; 17298de1fae6SStefano Zampini if (computeconstraintsmatrix || new_nearnullspace_provided) { 1730727cdba6SStefano Zampini /* It also sets the primal space flags */ 17319566063dSJacob Faibussowitsch PetscCall(PCBDDCConstraintsSetUp(pc)); 17329543d0ffSStefano Zampini } 1733e7b262bdSStefano Zampini /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 17349566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalWorkVectors(pc)); 17355e8657edSStefano Zampini 17365e8657edSStefano Zampini if (pcbddc->use_change_of_basis) { 17375e8657edSStefano Zampini PC_IS *pcis = (PC_IS*)(pc->data); 17385e8657edSStefano Zampini 17399566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix)); 17404f1b2e48SStefano Zampini if (pcbddc->benign_change) { 17419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 1742c263805aSStefano Zampini /* pop B0 from pcbddc->local_mat */ 17439566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE)); 1744c263805aSStefano Zampini } 17455e8657edSStefano Zampini /* get submatrices */ 17469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 17479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 17489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BB)); 17499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB)); 17509566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB)); 17519566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI)); 17523975b054SStefano Zampini /* set flag in pcis to not reuse submatrices during PCISCreate */ 17533975b054SStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 17549c6a02ceSStefano Zampini } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) { 17559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 17569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 17575e8657edSStefano Zampini pcbddc->local_mat = matis->A; 17585e8657edSStefano Zampini } 175935509ce9Sstefano_zampini 176035509ce9Sstefano_zampini /* interface pressure block row for B_C */ 17619566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP)); 17629566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA)); 176335509ce9Sstefano_zampini if (lA && lP) { 176435509ce9Sstefano_zampini PC_IS* pcis = (PC_IS*)pc->data; 176535509ce9Sstefano_zampini Mat B_BI,B_BB,Bt_BI,Bt_BB; 176635509ce9Sstefano_zampini PetscBool issym; 17679566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(lA,PETSC_SMALL,&issym)); 17686cc1294bSstefano_zampini if (issym) { 17699566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI)); 17709566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB)); 17719566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BI,&Bt_BI)); 17729566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BB,&Bt_BB)); 177335509ce9Sstefano_zampini } else { 17749566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI)); 17759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB)); 17769566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI)); 17779566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB)); 177835509ce9Sstefano_zampini } 17799566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI)); 17809566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB)); 17819566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI)); 17829566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB)); 17839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BI)); 17849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BB)); 17859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BI)); 17869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BB)); 178735509ce9Sstefano_zampini } 17889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0)); 178935509ce9Sstefano_zampini 1790b96c3477SStefano Zampini /* SetUp coarse and local Neumann solvers */ 17919566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpSolvers(pc)); 1792b96c3477SStefano Zampini /* SetUp Scaling operator */ 1793*1baa6e33SBarry Smith if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc)); 1794c703fcc7SStefano Zampini 17951dd7afcfSStefano Zampini /* mark topography as done */ 179656282151SStefano Zampini pcbddc->recompute_topography = PETSC_FALSE; 17970369aaf7SStefano Zampini 17981dd7afcfSStefano Zampini /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */ 17999566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc,PETSC_FALSE)); 18001dd7afcfSStefano Zampini 180158a03d70SStefano Zampini if (pcbddc->dbg_flag) { 18029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level)); 18039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 18042b510759SStefano Zampini } 18050c7d97c5SJed Brown PetscFunctionReturn(0); 18060c7d97c5SJed Brown } 18070c7d97c5SJed Brown 18080c7d97c5SJed Brown /* 180950efa1b5SStefano Zampini PCApply_BDDC - Applies the BDDC operator to a vector. 18100c7d97c5SJed Brown 18110c7d97c5SJed Brown Input Parameters: 18120f202f7eSStefano Zampini + pc - the preconditioner context 18130f202f7eSStefano Zampini - r - input vector (global) 18140c7d97c5SJed Brown 18150c7d97c5SJed Brown Output Parameter: 18160c7d97c5SJed Brown . z - output vector (global) 18170c7d97c5SJed Brown 18180c7d97c5SJed Brown Application Interface Routine: PCApply() 18190c7d97c5SJed Brown */ 182053cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 18210c7d97c5SJed Brown { 18220c7d97c5SJed Brown PC_IS *pcis = (PC_IS*)(pc->data); 18230c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1824b3338236SStefano Zampini Mat lA = NULL; 1825b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 18263b03a366Sstefano_zampini const PetscScalar one = 1.0; 18273b03a366Sstefano_zampini const PetscScalar m_one = -1.0; 18282617d88aSStefano Zampini const PetscScalar zero = 0.0; 18290c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN 18300c7d97c5SJed Brown NN interface preconditioner changed to BDDC 1831b097fa66SStefano Zampini Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 18320c7d97c5SJed Brown 18330c7d97c5SJed Brown PetscFunctionBegin; 18349566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation,&cited)); 1835b3338236SStefano Zampini if (pcbddc->switch_static) { 18369566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA)); 1837b3338236SStefano Zampini } 1838b3338236SStefano Zampini 18391dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 18401dd7afcfSStefano Zampini Vec swap; 184127b6a85dSStefano Zampini 18429566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change)); 18431dd7afcfSStefano Zampini swap = pcbddc->work_change; 18441dd7afcfSStefano Zampini pcbddc->work_change = r; 18451dd7afcfSStefano Zampini r = swap; 18461dd7afcfSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 18479cc2a9b1Sstefano_zampini if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 18489566063dSJacob Faibussowitsch PetscCall(VecCopy(r,pcis->vec1_global)); 18499566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 18501dd7afcfSStefano Zampini } 18511dd7afcfSStefano Zampini } 185227b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 18539566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE)); 1854efc2fbd9SStefano Zampini } 1855bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 18569566063dSJacob Faibussowitsch PetscCall(VecCopy(r,z)); 18570c7d97c5SJed Brown /* First Dirichlet solve */ 18589566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 18599566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 18600c7d97c5SJed Brown /* 18610c7d97c5SJed Brown Assembling right hand side for BDDC operator 1862b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1863674ae819SStefano Zampini - pcis->vec1_B the interface part of the global vector z 18640c7d97c5SJed Brown */ 1865b097fa66SStefano Zampini if (n_D) { 18669566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 18679566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D)); 18689566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 18699566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 18709566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D,m_one)); 187116909a7fSStefano Zampini if (pcbddc->switch_static) { 18729566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N,0.)); 18739566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 18749566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 187516909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 18769566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N)); 187716909a7fSStefano Zampini } else { 18789566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 18799566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec2_N,pcis->vec1_N)); 18809566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 188116909a7fSStefano Zampini } 18829566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 18839566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 18849566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 18859566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 188616909a7fSStefano Zampini } else { 18879566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B)); 188816909a7fSStefano Zampini } 1889b097fa66SStefano Zampini } else { 18909566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B,zero)); 1891b097fa66SStefano Zampini } 18929566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 18939566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 18949566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B)); 1895b76ba322SStefano Zampini } else { 18964fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 18979566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B)); 1898b76ba322SStefano Zampini } 18994fee134fSStefano Zampini } 1900bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 190128b400f6SJacob Faibussowitsch PetscCheck(pcbddc->switch_static,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static"); 19029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 19039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 1904bc960bbfSJed Brown } 1905b76ba322SStefano Zampini 19062617d88aSStefano Zampini /* Apply interface preconditioner 19072617d88aSStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 19089566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE)); 19092617d88aSStefano Zampini 1910674ae819SStefano Zampini /* Apply transpose of partition of unity operator */ 19119566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z)); 1912bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 19139566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19149566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE)); 1915bc960bbfSJed Brown PetscFunctionReturn(0); 1916bc960bbfSJed Brown } 19173b03a366Sstefano_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(MatMult(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(MatMult(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(MatMult(pcis->A_IB,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(MatMult(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(MatMult(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(KSPSolve(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)); 1951efc2fbd9SStefano Zampini 19528ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1953b097fa66SStefano Zampini if (pcbddc->switch_static) { 19549566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D)); 1955b097fa66SStefano Zampini } else { 19569566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D)); 1957b097fa66SStefano Zampini } 19589566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19599566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 1960b097fa66SStefano Zampini } else { 1961b097fa66SStefano Zampini if (pcbddc->switch_static) { 19629566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D)); 1963b097fa66SStefano Zampini } else { 19649566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D,m_one)); 1965b097fa66SStefano Zampini } 19669566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19679566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 1968b097fa66SStefano Zampini } 196927b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 1970*1baa6e33SBarry Smith if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 19719566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE)); 1972efc2fbd9SStefano Zampini } 19731f4df5f7SStefano Zampini 19741dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1975f913dca9SStefano Zampini pcbddc->work_change = r; 19769566063dSJacob Faibussowitsch PetscCall(VecCopy(z,pcbddc->work_change)); 19779566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z)); 19781dd7afcfSStefano Zampini } 19790c7d97c5SJed Brown PetscFunctionReturn(0); 19800c7d97c5SJed Brown } 198150efa1b5SStefano Zampini 198250efa1b5SStefano Zampini /* 198350efa1b5SStefano Zampini PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 198450efa1b5SStefano Zampini 198550efa1b5SStefano Zampini Input Parameters: 19860f202f7eSStefano Zampini + pc - the preconditioner context 19870f202f7eSStefano Zampini - r - input vector (global) 198850efa1b5SStefano Zampini 198950efa1b5SStefano Zampini Output Parameter: 199050efa1b5SStefano Zampini . z - output vector (global) 199150efa1b5SStefano Zampini 199250efa1b5SStefano Zampini Application Interface Routine: PCApplyTranspose() 199350efa1b5SStefano Zampini */ 199450efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z) 199550efa1b5SStefano Zampini { 199650efa1b5SStefano Zampini PC_IS *pcis = (PC_IS*)(pc->data); 199750efa1b5SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1998b3338236SStefano Zampini Mat lA = NULL; 1999b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 200050efa1b5SStefano Zampini const PetscScalar one = 1.0; 200150efa1b5SStefano Zampini const PetscScalar m_one = -1.0; 200250efa1b5SStefano Zampini const PetscScalar zero = 0.0; 200350efa1b5SStefano Zampini 200450efa1b5SStefano Zampini PetscFunctionBegin; 20059566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation,&cited)); 2006b3338236SStefano Zampini if (pcbddc->switch_static) { 20079566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA)); 2008b3338236SStefano Zampini } 20091dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 20101dd7afcfSStefano Zampini Vec swap; 201127b6a85dSStefano Zampini 20129566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change)); 20131dd7afcfSStefano Zampini swap = pcbddc->work_change; 20141dd7afcfSStefano Zampini pcbddc->work_change = r; 20151dd7afcfSStefano Zampini r = swap; 201627b6a85dSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 20178ae0ca82SStefano Zampini if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) { 20189566063dSJacob Faibussowitsch PetscCall(VecCopy(r,pcis->vec1_global)); 20199566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 20201dd7afcfSStefano Zampini } 202127b6a85dSStefano Zampini } 202227b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 20239566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE)); 2024537c1cdfSStefano Zampini } 20258ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 20269566063dSJacob Faibussowitsch PetscCall(VecCopy(r,z)); 202750efa1b5SStefano Zampini /* First Dirichlet solve */ 20289566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 20299566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 203050efa1b5SStefano Zampini /* 203150efa1b5SStefano Zampini Assembling right hand side for BDDC operator 2032b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 203350efa1b5SStefano Zampini - pcis->vec1_B the interface part of the global vector z 203450efa1b5SStefano Zampini */ 2035b097fa66SStefano Zampini if (n_D) { 20369566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 20379566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D)); 20389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 20399566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 20409566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D,m_one)); 204116909a7fSStefano Zampini if (pcbddc->switch_static) { 20429566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N,0.)); 20439566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 20449566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 204516909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 20469566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N)); 204716909a7fSStefano Zampini } else { 20489566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 20499566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N)); 20509566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 205116909a7fSStefano Zampini } 20529566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 20539566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 20549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 20559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 205616909a7fSStefano Zampini } else { 20579566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B)); 205816909a7fSStefano Zampini } 2059b097fa66SStefano Zampini } else { 20609566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B,zero)); 2061b097fa66SStefano Zampini } 20629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 20639566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 20649566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B)); 206550efa1b5SStefano Zampini } else { 20669566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B)); 206750efa1b5SStefano Zampini } 206850efa1b5SStefano Zampini 206950efa1b5SStefano Zampini /* Apply interface preconditioner 207050efa1b5SStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 20719566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE)); 207250efa1b5SStefano Zampini 207350efa1b5SStefano Zampini /* Apply transpose of partition of unity operator */ 20749566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z)); 207550efa1b5SStefano Zampini 207650efa1b5SStefano Zampini /* Second Dirichlet solve and assembling of output */ 20779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 20789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 2079b097fa66SStefano Zampini if (n_B) { 208016909a7fSStefano Zampini if (pcbddc->switch_static) { 20819566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 20829566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 20839566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 20849566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 208516909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 20869566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N)); 208716909a7fSStefano Zampini } else { 20889566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 20899566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N)); 20909566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 209116909a7fSStefano Zampini } 20929566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD)); 20939566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD)); 209416909a7fSStefano Zampini } else { 20959566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D)); 209616909a7fSStefano Zampini } 209716909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 209816909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 20999566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D)); 210016909a7fSStefano Zampini } else { 21019566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N)); 21029566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N)); 21039566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D)); 210416909a7fSStefano Zampini } 2105b097fa66SStefano Zampini } 21069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 21079566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D)); 21089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 21099566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D)); 21108ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 2111b097fa66SStefano Zampini if (pcbddc->switch_static) { 21129566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D)); 2113b097fa66SStefano Zampini } else { 21149566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D)); 2115b097fa66SStefano Zampini } 21169566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 21179566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 2118b097fa66SStefano Zampini } else { 2119b097fa66SStefano Zampini if (pcbddc->switch_static) { 21209566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D)); 2121b097fa66SStefano Zampini } else { 21229566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D,m_one)); 2123b097fa66SStefano Zampini } 21249566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 21259566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 2126b097fa66SStefano Zampini } 212727b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 21289566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE)); 2129537c1cdfSStefano Zampini } 21301dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 2131f913dca9SStefano Zampini pcbddc->work_change = r; 21329566063dSJacob Faibussowitsch PetscCall(VecCopy(z,pcbddc->work_change)); 21339566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z)); 21341dd7afcfSStefano Zampini } 213550efa1b5SStefano Zampini PetscFunctionReturn(0); 213650efa1b5SStefano Zampini } 2137674ae819SStefano Zampini 21389326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc) 2139da1bb401SStefano Zampini { 2140da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 21419326c5c6Sstefano_zampini PC_IS *pcis = (PC_IS*)pc->data; 21429326c5c6Sstefano_zampini KSP kspD,kspR,kspC; 2143da1bb401SStefano Zampini 2144da1bb401SStefano Zampini PetscFunctionBegin; 2145674ae819SStefano Zampini /* free BDDC custom data */ 21469566063dSJacob Faibussowitsch PetscCall(PCBDDCResetCustomization(pc)); 2147674ae819SStefano Zampini /* destroy objects related to topography */ 21489566063dSJacob Faibussowitsch PetscCall(PCBDDCResetTopography(pc)); 214934a97f8cSStefano Zampini /* destroy objects for scaling operator */ 21509566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingDestroy(pc)); 2151674ae819SStefano Zampini /* free solvers stuff */ 21529566063dSJacob Faibussowitsch PetscCall(PCBDDCResetSolvers(pc)); 215362a6ff1dSStefano Zampini /* free global vectors needed in presolve */ 21549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->temp_solution)); 21559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->original_rhs)); 21561dd7afcfSStefano Zampini /* free data created by PCIS */ 21579566063dSJacob Faibussowitsch PetscCall(PCISDestroy(pc)); 21589326c5c6Sstefano_zampini 21599326c5c6Sstefano_zampini /* restore defaults */ 21609326c5c6Sstefano_zampini kspD = pcbddc->ksp_D; 21619326c5c6Sstefano_zampini kspR = pcbddc->ksp_R; 21629326c5c6Sstefano_zampini kspC = pcbddc->coarse_ksp; 21639566063dSJacob Faibussowitsch PetscCall(PetscMemzero(pc->data,sizeof(*pcbddc))); 21649326c5c6Sstefano_zampini pcis->n_neigh = -1; 21659326c5c6Sstefano_zampini pcis->scaling_factor = 1.0; 21669326c5c6Sstefano_zampini pcis->reusesubmatrices = PETSC_TRUE; 21679326c5c6Sstefano_zampini pcbddc->use_local_adj = PETSC_TRUE; 21689326c5c6Sstefano_zampini pcbddc->use_vertices = PETSC_TRUE; 21699326c5c6Sstefano_zampini pcbddc->use_edges = PETSC_TRUE; 21709326c5c6Sstefano_zampini pcbddc->symmetric_primal = PETSC_TRUE; 21719326c5c6Sstefano_zampini pcbddc->vertex_size = 1; 21729326c5c6Sstefano_zampini pcbddc->recompute_topography = PETSC_TRUE; 21739326c5c6Sstefano_zampini pcbddc->coarse_size = -1; 21749326c5c6Sstefano_zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 21759326c5c6Sstefano_zampini pcbddc->coarsening_ratio = 8; 21769326c5c6Sstefano_zampini pcbddc->coarse_eqs_per_proc = 1; 21779326c5c6Sstefano_zampini pcbddc->benign_compute_correction = PETSC_TRUE; 21789326c5c6Sstefano_zampini pcbddc->nedfield = -1; 21799326c5c6Sstefano_zampini pcbddc->nedglobal = PETSC_TRUE; 21809326c5c6Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 21819326c5c6Sstefano_zampini pcbddc->sub_schurs_layers = -1; 21829326c5c6Sstefano_zampini pcbddc->ksp_D = kspD; 21839326c5c6Sstefano_zampini pcbddc->ksp_R = kspR; 21849326c5c6Sstefano_zampini pcbddc->coarse_ksp = kspC; 21859326c5c6Sstefano_zampini PetscFunctionReturn(0); 21869326c5c6Sstefano_zampini } 21879326c5c6Sstefano_zampini 21889326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc) 21899326c5c6Sstefano_zampini { 21909326c5c6Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 21919326c5c6Sstefano_zampini 21929326c5c6Sstefano_zampini PetscFunctionBegin; 21939566063dSJacob Faibussowitsch PetscCall(PCReset_BDDC(pc)); 21949566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_D)); 21959566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_R)); 21969566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->coarse_ksp)); 21979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL)); 21989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL)); 21999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL)); 22009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL)); 22019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL)); 220232fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",NULL)); 220332fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",NULL)); 22049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL)); 22059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL)); 22069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL)); 22079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL)); 22089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL)); 22099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL)); 22109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL)); 22119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL)); 22129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL)); 22139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL)); 22149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL)); 22159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL)); 22169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL)); 22179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL)); 22189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL)); 22199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL)); 22209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL)); 22219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL)); 22229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL)); 22239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL)); 22249566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2225da1bb401SStefano Zampini PetscFunctionReturn(0); 2226da1bb401SStefano Zampini } 22271e6b0712SBarry Smith 2228ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) 2229ab8c8b98SStefano Zampini { 2230ab8c8b98SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2231ab8c8b98SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 2232ab8c8b98SStefano Zampini 2233ab8c8b98SStefano Zampini PetscFunctionBegin; 22349566063dSJacob Faibussowitsch PetscCall(PetscFree(mat_graph->coords)); 22359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc*dim,&mat_graph->coords)); 22369566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->coords,coords,nloc*dim)); 2237ab8c8b98SStefano Zampini mat_graph->cnloc = nloc; 2238ab8c8b98SStefano Zampini mat_graph->cdim = dim; 2239ab8c8b98SStefano Zampini mat_graph->cloc = PETSC_FALSE; 22404f819b78SStefano Zampini /* flg setup */ 22414f819b78SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 22424f819b78SStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 2243ab8c8b98SStefano Zampini PetscFunctionReturn(0); 2244ab8c8b98SStefano Zampini } 2245ab8c8b98SStefano Zampini 2246a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change) 2247a06fd7f2SStefano Zampini { 2248a06fd7f2SStefano Zampini PetscFunctionBegin; 2249a06fd7f2SStefano Zampini *change = PETSC_TRUE; 2250a06fd7f2SStefano Zampini PetscFunctionReturn(0); 2251a06fd7f2SStefano Zampini } 2252a06fd7f2SStefano Zampini 22533425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 22543425bc38SStefano Zampini { 2255674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 2256266e20e9SStefano Zampini Vec work; 22573425bc38SStefano Zampini PC_IS* pcis; 22583425bc38SStefano Zampini PC_BDDC* pcbddc; 22590c7d97c5SJed Brown 22603425bc38SStefano Zampini PetscFunctionBegin; 22619566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 22623425bc38SStefano Zampini pcis = (PC_IS*)mat_ctx->pc->data; 22633425bc38SStefano Zampini pcbddc = (PC_BDDC*)mat_ctx->pc->data; 22643425bc38SStefano Zampini 22659566063dSJacob Faibussowitsch PetscCall(VecSet(fetidp_flux_rhs,0.0)); 2266229984c5Sstefano_zampini /* copy rhs since we may change it during PCPreSolve_BDDC */ 2267229984c5Sstefano_zampini if (!pcbddc->original_rhs) { 22689566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs)); 2269229984c5Sstefano_zampini } 22706cc1294bSstefano_zampini if (mat_ctx->rhs_flip) { 22719566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip)); 22726cc1294bSstefano_zampini } else { 22739566063dSJacob Faibussowitsch PetscCall(VecCopy(standard_rhs,pcbddc->original_rhs)); 22746cc1294bSstefano_zampini } 2275af140850Sstefano_zampini if (mat_ctx->g2g_p) { 2276229984c5Sstefano_zampini /* interface pressure rhs */ 22779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE)); 22789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE)); 22799566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD)); 22809566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD)); 22816cc1294bSstefano_zampini if (!mat_ctx->rhs_flip) { 22829566063dSJacob Faibussowitsch PetscCall(VecScale(fetidp_flux_rhs,-1.)); 2283229984c5Sstefano_zampini } 22846cc1294bSstefano_zampini } 2285c08af4c6SStefano Zampini /* 2286c08af4c6SStefano Zampini change of basis for physical rhs if needed 2287c08af4c6SStefano Zampini It also changes the rhs in case of dirichlet boundaries 2288c08af4c6SStefano Zampini */ 22899566063dSJacob Faibussowitsch PetscCall(PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL)); 2290fc17d649SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 22919566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change)); 22923738a8e6SStefano Zampini work = pcbddc->work_change; 2293fc17d649SStefano Zampini } else { 22943738a8e6SStefano Zampini work = pcbddc->original_rhs; 2295fc17d649SStefano Zampini } 22963425bc38SStefano Zampini /* store vectors for computation of fetidp final solution */ 22979566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD)); 22989566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD)); 2299fb223d50SStefano Zampini /* scale rhs since it should be unassembled */ 2300fb223d50SStefano Zampini /* TODO use counter scaling? (also below) */ 23019566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 23029566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 2303674ae819SStefano Zampini /* Apply partition of unity */ 23049566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B)); 23059566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 23068eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 23073425bc38SStefano Zampini /* compute partially subassembled Schur complement right-hand side */ 23089566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 23099566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D)); 23109566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 2311c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 23129566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B)); 23139566063dSJacob Faibussowitsch PetscCall(VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B)); 23149566063dSJacob Faibussowitsch PetscCall(VecSet(work,0.0)); 23159566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE)); 23169566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE)); 23179566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 23189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 23199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 23209566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B)); 23213425bc38SStefano Zampini } 23223425bc38SStefano Zampini /* BDDC rhs */ 23239566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B)); 2324*1baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D)); 23253425bc38SStefano Zampini /* apply BDDC */ 23269566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 23279566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE)); 23289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 2329229984c5Sstefano_zampini 23303425bc38SStefano Zampini /* Application of B_delta and assembling of rhs for fetidp fluxes */ 23319566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local)); 23329566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 23339566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 2334229984c5Sstefano_zampini /* Add contribution to interface pressures */ 2335229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 23369566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP)); 2337*1baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP)); 23389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 23399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 2340229984c5Sstefano_zampini } 23413425bc38SStefano Zampini PetscFunctionReturn(0); 23423425bc38SStefano Zampini } 23431e6b0712SBarry Smith 23443425bc38SStefano Zampini /*@ 23450f202f7eSStefano Zampini PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side 23463425bc38SStefano Zampini 23473425bc38SStefano Zampini Collective 23483425bc38SStefano Zampini 23493425bc38SStefano Zampini Input Parameters: 23500f202f7eSStefano Zampini + fetidp_mat - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators 23510f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system 23523425bc38SStefano Zampini 23533425bc38SStefano Zampini Output Parameters: 23540f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 23553425bc38SStefano Zampini 23563425bc38SStefano Zampini Level: developer 23573425bc38SStefano Zampini 23583425bc38SStefano Zampini Notes: 23593425bc38SStefano Zampini 236016b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()` 23613425bc38SStefano Zampini @*/ 23623425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 23633425bc38SStefano Zampini { 2364674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 23653425bc38SStefano Zampini 23663425bc38SStefano Zampini PetscFunctionBegin; 2367266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1); 2368266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2); 2369266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3); 23709566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 2371cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs)); 23723425bc38SStefano Zampini PetscFunctionReturn(0); 23733425bc38SStefano Zampini } 23741e6b0712SBarry Smith 23753425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 23763425bc38SStefano Zampini { 2377674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 23783425bc38SStefano Zampini PC_IS* pcis; 23793425bc38SStefano Zampini PC_BDDC* pcbddc; 2380229984c5Sstefano_zampini Vec work; 23813425bc38SStefano Zampini 23823425bc38SStefano Zampini PetscFunctionBegin; 23839566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 23843425bc38SStefano Zampini pcis = (PC_IS*)mat_ctx->pc->data; 23853425bc38SStefano Zampini pcbddc = (PC_BDDC*)mat_ctx->pc->data; 23863425bc38SStefano Zampini 23873425bc38SStefano Zampini /* apply B_delta^T */ 23889566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B,0.)); 23899566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE)); 23909566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE)); 23919566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B)); 2392229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 23939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE)); 23949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE)); 23959566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B)); 2396229984c5Sstefano_zampini } 2397229984c5Sstefano_zampini 23983425bc38SStefano Zampini /* compute rhs for BDDC application */ 23999566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B)); 24008eeda7d8SStefano Zampini if (pcbddc->switch_static) { 24019566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D)); 2402229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 24039566063dSJacob Faibussowitsch PetscCall(VecScale(mat_ctx->vP,-1.)); 24049566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D)); 24053425bc38SStefano Zampini } 2406229984c5Sstefano_zampini } 2407229984c5Sstefano_zampini 24083425bc38SStefano Zampini /* apply BDDC */ 24099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 24109566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE)); 2411229984c5Sstefano_zampini 2412229984c5Sstefano_zampini /* put values into global vector */ 2413af140850Sstefano_zampini if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change; 2414af140850Sstefano_zampini else work = standard_sol; 24159566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE)); 24169566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE)); 24178eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 24183425bc38SStefano Zampini /* compute values into the interior if solved for the partially subassembled Schur complement */ 24199566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D)); 24209566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D)); 24219566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 24229566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D)); 24239566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 2424c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 24253425bc38SStefano Zampini } 2426229984c5Sstefano_zampini 24279566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE)); 24289566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE)); 2429266e20e9SStefano Zampini /* add p0 solution to final solution */ 24309566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE)); 2431*1baa6e33SBarry Smith if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol)); 24329566063dSJacob Faibussowitsch PetscCall(PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol)); 2433af140850Sstefano_zampini if (mat_ctx->g2g_p) { 24349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE)); 24359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE)); 2436229984c5Sstefano_zampini } 24373425bc38SStefano Zampini PetscFunctionReturn(0); 24383425bc38SStefano Zampini } 24391e6b0712SBarry Smith 24405a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) 24415a1e936bSStefano Zampini { 24425a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24435a1e936bSStefano Zampini PetscBool isascii; 24445a1e936bSStefano Zampini 24455a1e936bSStefano Zampini PetscFunctionBegin; 24469566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 24479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 24485a1e936bSStefano Zampini if (isascii) { 24499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n")); 24505a1e936bSStefano Zampini } 24519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 24529566063dSJacob Faibussowitsch PetscCall(PCView(bddcipc_ctx->bddc,viewer)); 24539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 24545a1e936bSStefano Zampini PetscFunctionReturn(0); 24555a1e936bSStefano Zampini } 24565a1e936bSStefano Zampini 24575a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc) 24585a1e936bSStefano Zampini { 24595a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24605a1e936bSStefano Zampini PetscBool isbddc; 24615a1e936bSStefano Zampini Vec vv; 24625a1e936bSStefano Zampini IS is; 24635a1e936bSStefano Zampini PC_IS *pcis; 24645a1e936bSStefano Zampini 24655a1e936bSStefano Zampini PetscFunctionBegin; 24669566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 24679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc)); 246828b400f6SJacob Faibussowitsch PetscCheck(isbddc,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name); 24699566063dSJacob Faibussowitsch PetscCall(PCSetUp(bddcipc_ctx->bddc)); 24705a1e936bSStefano Zampini 24715a1e936bSStefano Zampini /* create interface scatter */ 24725a1e936bSStefano Zampini pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 24739566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 24749566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat,&vv,NULL)); 24759566063dSJacob Faibussowitsch PetscCall(ISRenumber(pcis->is_B_global,NULL,NULL,&is)); 24769566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l)); 24779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 24789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vv)); 24795a1e936bSStefano Zampini PetscFunctionReturn(0); 24805a1e936bSStefano Zampini } 24815a1e936bSStefano Zampini 24825a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) 24835a1e936bSStefano Zampini { 24845a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24855a1e936bSStefano Zampini PC_IS *pcis; 24865a1e936bSStefano Zampini VecScatter tmps; 24875a1e936bSStefano Zampini 24885a1e936bSStefano Zampini PetscFunctionBegin; 24899566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 24905a1e936bSStefano Zampini pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 24915a1e936bSStefano Zampini tmps = pcis->global_to_B; 24925a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 24939566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B)); 24949566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE)); 24959566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x)); 24965a1e936bSStefano Zampini pcis->global_to_B = tmps; 24975a1e936bSStefano Zampini PetscFunctionReturn(0); 24985a1e936bSStefano Zampini } 24995a1e936bSStefano Zampini 25005a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) 25015a1e936bSStefano Zampini { 25025a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 25035a1e936bSStefano Zampini PC_IS *pcis; 25045a1e936bSStefano Zampini VecScatter tmps; 25055a1e936bSStefano Zampini 25065a1e936bSStefano Zampini PetscFunctionBegin; 25079566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 25085a1e936bSStefano Zampini pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 25095a1e936bSStefano Zampini tmps = pcis->global_to_B; 25105a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 25119566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B)); 25129566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE)); 25139566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x)); 25145a1e936bSStefano Zampini pcis->global_to_B = tmps; 25155a1e936bSStefano Zampini PetscFunctionReturn(0); 25165a1e936bSStefano Zampini } 25175a1e936bSStefano Zampini 25185a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc) 25195a1e936bSStefano Zampini { 25205a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 25215a1e936bSStefano Zampini 25225a1e936bSStefano Zampini PetscFunctionBegin; 25239566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 25249566063dSJacob Faibussowitsch PetscCall(PCDestroy(&bddcipc_ctx->bddc)); 25259566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 25269566063dSJacob Faibussowitsch PetscCall(PetscFree(bddcipc_ctx)); 25275a1e936bSStefano Zampini PetscFunctionReturn(0); 25285a1e936bSStefano Zampini } 25295a1e936bSStefano Zampini 25303425bc38SStefano Zampini /*@ 25310f202f7eSStefano Zampini PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 25323425bc38SStefano Zampini 25333425bc38SStefano Zampini Collective 25343425bc38SStefano Zampini 25353425bc38SStefano Zampini Input Parameters: 25360f202f7eSStefano Zampini + fetidp_mat - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators 25370f202f7eSStefano Zampini - fetidp_flux_sol - the solution of the FETI-DP linear system 25383425bc38SStefano Zampini 25393425bc38SStefano Zampini Output Parameters: 25400f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain 25413425bc38SStefano Zampini 25423425bc38SStefano Zampini Level: developer 25433425bc38SStefano Zampini 25443425bc38SStefano Zampini Notes: 25453425bc38SStefano Zampini 254616b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()` 25473425bc38SStefano Zampini @*/ 25483425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 25493425bc38SStefano Zampini { 2550674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 25513425bc38SStefano Zampini 25523425bc38SStefano Zampini PetscFunctionBegin; 2553266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1); 2554266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2); 2555266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3); 25569566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 2557cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol)); 25583425bc38SStefano Zampini PetscFunctionReturn(0); 25593425bc38SStefano Zampini } 25601e6b0712SBarry Smith 2561547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc) 25623425bc38SStefano Zampini { 2563674ae819SStefano Zampini 2564674ae819SStefano Zampini FETIDPMat_ctx fetidpmat_ctx; 25653425bc38SStefano Zampini Mat newmat; 2566674ae819SStefano Zampini FETIDPPC_ctx fetidppc_ctx; 25673425bc38SStefano Zampini PC newpc; 2568ce94432eSBarry Smith MPI_Comm comm; 25693425bc38SStefano Zampini 25703425bc38SStefano Zampini PetscFunctionBegin; 25719566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc,&comm)); 257215579a77SStefano Zampini /* FETI-DP matrix */ 25739566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx)); 25741720468bSStefano Zampini fetidpmat_ctx->fully_redundant = fully_redundant; 25759566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx)); 25769566063dSJacob Faibussowitsch PetscCall(MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat)); 25779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G")); 25789566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult)); 25799566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose)); 25809566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat)); 258115579a77SStefano Zampini /* propagate MatOptions */ 258215579a77SStefano Zampini { 258315579a77SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data; 258415579a77SStefano Zampini PetscBool issym; 258515579a77SStefano Zampini 25869566063dSJacob Faibussowitsch PetscCall(MatGetOption(pc->mat,MAT_SYMMETRIC,&issym)); 258715579a77SStefano Zampini if (issym || pcbddc->symmetric_primal) { 25889566063dSJacob Faibussowitsch PetscCall(MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE)); 258915579a77SStefano Zampini } 259015579a77SStefano Zampini } 25919566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(newmat,prefix)); 25929566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(newmat,"fetidp_")); 25939566063dSJacob Faibussowitsch PetscCall(MatSetUp(newmat)); 259415579a77SStefano Zampini /* FETI-DP preconditioner */ 25959566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx)); 25969566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx)); 25979566063dSJacob Faibussowitsch PetscCall(PCCreate(comm,&newpc)); 25989566063dSJacob Faibussowitsch PetscCall(PCSetOperators(newpc,newmat,newmat)); 25999566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(newpc,prefix)); 26009566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(newpc,"fetidp_")); 26019566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(newpc,pc->erroriffailure)); 260215579a77SStefano Zampini if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */ 26039566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc,PCSHELL)); 26049566063dSJacob Faibussowitsch PetscCall(PCShellSetName(newpc,"FETI-DP multipliers")); 26059566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(newpc,fetidppc_ctx)); 26069566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(newpc,FETIDPPCApply)); 26079566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose)); 26089566063dSJacob Faibussowitsch PetscCall(PCShellSetView(newpc,FETIDPPCView)); 26099566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC)); 26105a1e936bSStefano Zampini } else { /* saddle-point FETI-DP */ 26115a1e936bSStefano Zampini Mat M; 26125a1e936bSStefano Zampini PetscInt psize; 26135a1e936bSStefano Zampini PetscBool fake = PETSC_FALSE, isfieldsplit; 2614e1214c54Sstefano_zampini 26159566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view")); 26169566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view")); 26179566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M)); 26189566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc,PCFIELDSPLIT)); 26199566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange)); 26209566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure)); 26219566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR)); 26229566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG)); 26239566063dSJacob Faibussowitsch PetscCall(ISGetSize(fetidpmat_ctx->pressure,&psize)); 26245a1e936bSStefano Zampini if (psize != M->rmap->N) { 26255a1e936bSStefano Zampini Mat M2; 26265a1e936bSStefano Zampini PetscInt lpsize; 26275a1e936bSStefano Zampini 26285a1e936bSStefano Zampini fake = PETSC_TRUE; 26299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize)); 26309566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&M2)); 26319566063dSJacob Faibussowitsch PetscCall(MatSetType(M2,MATAIJ)); 26329566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M2,lpsize,lpsize,psize,psize)); 26339566063dSJacob Faibussowitsch PetscCall(MatSetUp(M2)); 26349566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY)); 26359566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY)); 26369566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2)); 26379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M2)); 26385a1e936bSStefano Zampini } else { 26399566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M)); 26405a1e936bSStefano Zampini } 26419566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurScale(newpc,1.0)); 264215579a77SStefano Zampini 264315579a77SStefano Zampini /* we need to setfromoptions and setup here to access the blocks */ 26449566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(newpc)); 26459566063dSJacob Faibussowitsch PetscCall(PCSetUp(newpc)); 2646e1214c54Sstefano_zampini 26475a1e936bSStefano Zampini /* user may have changed the type (e.g. -fetidp_pc_type none) */ 26489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit)); 26495a1e936bSStefano Zampini if (isfieldsplit) { 26505a1e936bSStefano Zampini KSP *ksps; 26515a1e936bSStefano Zampini PC ppc,lagpc; 26525a1e936bSStefano Zampini PetscInt nn; 2653064a4176SStefano Zampini PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE; 26545a1e936bSStefano Zampini 2655e1214c54Sstefano_zampini /* set the solver for the (0,0) block */ 26569566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps)); 26575a1e936bSStefano Zampini if (!nn) { /* not of type PC_COMPOSITE_SCHUR */ 26589566063dSJacob Faibussowitsch PetscCall(PCFieldSplitGetSubKSP(newpc,&nn,&ksps)); 26595a1e936bSStefano Zampini if (!fake) { /* pass pmat to the pressure solver */ 26605a1e936bSStefano Zampini Mat F; 26615a1e936bSStefano Zampini 26629566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[1],&F,NULL)); 26639566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksps[1],F,M)); 26645a1e936bSStefano Zampini } 26655a1e936bSStefano Zampini } else { 26665a1e936bSStefano Zampini PetscBool issym; 26675a1e936bSStefano Zampini Mat S; 26685a1e936bSStefano Zampini 26699566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetS(newpc,&S)); 26705a1e936bSStefano Zampini 26719566063dSJacob Faibussowitsch PetscCall(MatGetOption(newmat,MAT_SYMMETRIC,&issym)); 2672*1baa6e33SBarry Smith if (issym) PetscCall(MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE)); 26735a1e936bSStefano Zampini } 26749566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[0],&lagpc)); 26759566063dSJacob Faibussowitsch PetscCall(PCSetType(lagpc,PCSHELL)); 26769566063dSJacob Faibussowitsch PetscCall(PCShellSetName(lagpc,"FETI-DP multipliers")); 26779566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(lagpc,fetidppc_ctx)); 26789566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(lagpc,FETIDPPCApply)); 26799566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose)); 26809566063dSJacob Faibussowitsch PetscCall(PCShellSetView(lagpc,FETIDPPCView)); 26819566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC)); 26825a1e936bSStefano Zampini 26835a1e936bSStefano Zampini /* Olof's idea: interface Schur complement preconditioner for the mass matrix */ 26849566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[1],&ppc)); 26855a1e936bSStefano Zampini if (fake) { 26865a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 2687ff11fd76SStefano Zampini PetscContainer c; 26885a1e936bSStefano Zampini 26895a1e936bSStefano Zampini matisok = PETSC_TRUE; 26905a1e936bSStefano Zampini 26915a1e936bSStefano Zampini /* create inner BDDC solver */ 26929566063dSJacob Faibussowitsch PetscCall(PetscNew(&bddcipc_ctx)); 26939566063dSJacob Faibussowitsch PetscCall(PCCreate(comm,&bddcipc_ctx->bddc)); 26949566063dSJacob Faibussowitsch PetscCall(PCSetType(bddcipc_ctx->bddc,PCBDDC)); 26959566063dSJacob Faibussowitsch PetscCall(PCSetOperators(bddcipc_ctx->bddc,M,M)); 26969566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c)); 26979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis)); 2698ff11fd76SStefano Zampini if (c && ismatis) { 2699ff11fd76SStefano Zampini Mat lM; 2700ff11fd76SStefano Zampini PetscInt *csr,n; 2701ff11fd76SStefano Zampini 27029566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(M,&lM)); 27039566063dSJacob Faibussowitsch PetscCall(MatGetSize(lM,&n,NULL)); 27049566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c,(void**)&csr)); 27059566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES)); 27069566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(M,&lM)); 2707ff11fd76SStefano Zampini } 27089566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix)); 27099566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure)); 27109566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(bddcipc_ctx->bddc)); 27115a1e936bSStefano Zampini 27125a1e936bSStefano Zampini /* wrap the interface application */ 27139566063dSJacob Faibussowitsch PetscCall(PCSetType(ppc,PCSHELL)); 27149566063dSJacob Faibussowitsch PetscCall(PCShellSetName(ppc,"FETI-DP pressure")); 27159566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(ppc,bddcipc_ctx)); 27169566063dSJacob Faibussowitsch PetscCall(PCShellSetSetUp(ppc,PCSetUp_BDDCIPC)); 27179566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(ppc,PCApply_BDDCIPC)); 27189566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC)); 27199566063dSJacob Faibussowitsch PetscCall(PCShellSetView(ppc,PCView_BDDCIPC)); 27209566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(ppc,PCDestroy_BDDCIPC)); 27215a1e936bSStefano Zampini } 27225a1e936bSStefano Zampini 27235a1e936bSStefano Zampini /* determine if we need to assemble M to construct a preconditioner */ 27245a1e936bSStefano Zampini if (!matisok) { 27259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis)); 27269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"")); 27275a1e936bSStefano Zampini if (ismatis && !matisok) { 27289566063dSJacob Faibussowitsch PetscCall(MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M)); 27295a1e936bSStefano Zampini } 27305a1e936bSStefano Zampini } 2731064a4176SStefano Zampini 2732064a4176SStefano Zampini /* run the subproblems to check convergence */ 27339566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL)); 2734064a4176SStefano Zampini if (check) { 2735064a4176SStefano Zampini PetscInt i; 2736064a4176SStefano Zampini 2737064a4176SStefano Zampini for (i=0;i<nn;i++) { 2738064a4176SStefano Zampini KSP kspC; 2739064a4176SStefano Zampini PC pc; 2740064a4176SStefano Zampini Mat F,pF; 2741064a4176SStefano Zampini Vec x,y; 2742064a4176SStefano Zampini PetscBool isschur,prec = PETSC_TRUE; 2743064a4176SStefano Zampini 27449566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC)); 27459566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix)); 27469566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(kspC,"check_")); 27479566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[i],&F,&pF)); 27489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur)); 2749064a4176SStefano Zampini if (isschur) { 2750064a4176SStefano Zampini KSP kspS,kspS2; 2751064a4176SStefano Zampini Mat A00,pA00,A10,A01,A11; 2752064a4176SStefano Zampini char prefix[256]; 2753064a4176SStefano Zampini 27549566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F,&kspS)); 27559566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11)); 27569566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F)); 27579566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F,&kspS2)); 27589566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix)); 27599566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspS2,prefix)); 27609566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2,&pc)); 27619566063dSJacob Faibussowitsch PetscCall(PCSetType(pc,PCKSP)); 27629566063dSJacob Faibussowitsch PetscCall(PCKSPSetKSP(pc,kspS)); 27639566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspS2)); 27649566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2,&pc)); 27659566063dSJacob Faibussowitsch PetscCall(PCSetUseAmat(pc,PETSC_TRUE)); 2766064a4176SStefano Zampini } else { 27679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)F)); 2768064a4176SStefano Zampini } 27699566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspC)); 27709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL)); 2771064a4176SStefano Zampini if (prec) { 27729566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[i],&pc)); 27739566063dSJacob Faibussowitsch PetscCall(KSPSetPC(kspC,pc)); 2774064a4176SStefano Zampini } 27759566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(kspC,F,pF)); 27769566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(F,&x,&y)); 27779566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x,NULL)); 27789566063dSJacob Faibussowitsch PetscCall(MatMult(F,x,y)); 27799566063dSJacob Faibussowitsch PetscCall(KSPSolve(kspC,y,x)); 27809566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(kspC,pc,x)); 27819566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&kspC)); 27829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&F)); 27839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 27849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 2785064a4176SStefano Zampini } 2786064a4176SStefano Zampini } 27879566063dSJacob Faibussowitsch PetscCall(PetscFree(ksps)); 2788e1214c54Sstefano_zampini } 27895a1e936bSStefano Zampini } 27903425bc38SStefano Zampini /* return pointers for objects created */ 27913425bc38SStefano Zampini *fetidp_mat = newmat; 27923425bc38SStefano Zampini *fetidp_pc = newpc; 27933425bc38SStefano Zampini PetscFunctionReturn(0); 27943425bc38SStefano Zampini } 27951e6b0712SBarry Smith 279694ef8ddeSSatish Balay /*@C 27970f202f7eSStefano Zampini PCBDDCCreateFETIDPOperators - Create FETI-DP operators 27983425bc38SStefano Zampini 27993425bc38SStefano Zampini Collective 28003425bc38SStefano Zampini 28013425bc38SStefano Zampini Input Parameters: 28021720468bSStefano Zampini + pc - the BDDC preconditioning context (setup should have been called before) 2803547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers 2804547c9a8eSstefano_zampini - prefix - optional options database prefix for the objects to be created (can be NULL) 280528509bceSStefano Zampini 280628509bceSStefano Zampini Output Parameters: 28070f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object 28080f202f7eSStefano Zampini - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 280928509bceSStefano Zampini 28103425bc38SStefano Zampini Level: developer 28113425bc38SStefano Zampini 28123425bc38SStefano Zampini Notes: 28130f202f7eSStefano Zampini Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose 28143425bc38SStefano Zampini 281516b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()` 28163425bc38SStefano Zampini @*/ 2817547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) 28183425bc38SStefano Zampini { 28193425bc38SStefano Zampini PetscFunctionBegin; 28203425bc38SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 28213425bc38SStefano Zampini if (pc->setupcalled) { 2822cac4c232SBarry Smith PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc)); 28236080607fSStefano Zampini } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first"); 28243425bc38SStefano Zampini PetscFunctionReturn(0); 28253425bc38SStefano Zampini } 28260c7d97c5SJed Brown /* -------------------------------------------------------------------------- */ 2827da1bb401SStefano Zampini /*MC 2828da1bb401SStefano Zampini PCBDDC - Balancing Domain Decomposition by Constraints. 28290c7d97c5SJed Brown 2830be4a8d98Sprj- An implementation of the BDDC preconditioner based on the bibliography found below. 283128509bceSStefano Zampini 283228509bceSStefano Zampini The matrix to be preconditioned (Pmat) must be of type MATIS. 283328509bceSStefano Zampini 28340f202f7eSStefano Zampini Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 283528509bceSStefano Zampini 283628509bceSStefano Zampini It also works with unsymmetric and indefinite problems. 283728509bceSStefano Zampini 2838b6fdb6dfSStefano Zampini Unlike 'conventional' interface preconditioners, PCBDDC iterates over all degrees of freedom, not just those on the interface. This allows the use of approximate solvers on the subdomains. 2839b6fdb6dfSStefano Zampini 2840c7017625SStefano Zampini Approximate local solvers are automatically adapted (see [1]) if the user has attached a nullspace object to the subdomain matrices, and informed BDDC of using approximate solvers (via the command line). 284128509bceSStefano Zampini 28420f202f7eSStefano Zampini Boundary nodes are split in vertices, edges and faces classes using information from the local to global mapping of dofs and the local connectivity graph of nodes. The latter can be customized by using PCBDDCSetLocalAdjacencyGraph() 284330368db7SStefano Zampini Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts. 284428509bceSStefano Zampini 28450f202f7eSStefano Zampini Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD. 284628509bceSStefano Zampini 28470f202f7eSStefano Zampini Change of basis is performed similarly to [2] when requested. When more than one constraint is present on a single connected component (i.e. an edge or a face), a robust method based on local QR factorizations is used. 28480f202f7eSStefano Zampini User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat() 284928509bceSStefano Zampini 28500f202f7eSStefano Zampini The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object. 285128509bceSStefano Zampini 2852df4d28bfSStefano Zampini Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present. Future versions of the code will also consider using PASTIX. 285328509bceSStefano Zampini 28540f202f7eSStefano Zampini An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using PCBDDCCreateFETIDPOperators(). A stand-alone class for the FETI-DP method will be provided in the next releases. 28550f202f7eSStefano Zampini 2856d314f959SVaclav Hapla Options Database Keys (some of them, run with -help for a complete list): 28570f202f7eSStefano Zampini 2858a2b725a8SWilliam Gropp + -pc_bddc_use_vertices <true> - use or not vertices in primal space 28590f202f7eSStefano Zampini . -pc_bddc_use_edges <true> - use or not edges in primal space 28600f202f7eSStefano Zampini . -pc_bddc_use_faces <false> - use or not faces in primal space 28610f202f7eSStefano Zampini . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 28620f202f7eSStefano Zampini . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 28630f202f7eSStefano Zampini . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 28640f202f7eSStefano Zampini . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 286528509bceSStefano Zampini . -pc_bddc_levels <0> - maximum number of levels for multilevel 28660f202f7eSStefano 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) 28675459c157SBarry 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) 28680f202f7eSStefano Zampini . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 286971f2caa7Sprj- . -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) 2870bd2a564bSStefano 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) 287128509bceSStefano Zampini - -pc_bddc_check_level <0> - set verbosity level of debugging output 287228509bceSStefano Zampini 287328509bceSStefano Zampini Options for Dirichlet, Neumann or coarse solver can be set with 287428509bceSStefano Zampini .vb 287528509bceSStefano Zampini -pc_bddc_dirichlet_ 287628509bceSStefano Zampini -pc_bddc_neumann_ 287728509bceSStefano Zampini -pc_bddc_coarse_ 287828509bceSStefano Zampini .ve 2879f9ff08acSPierre Jolivet e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU. 288028509bceSStefano Zampini 28810f202f7eSStefano Zampini When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as 288228509bceSStefano Zampini .vb 2883312be037SStefano Zampini -pc_bddc_dirichlet_lN_ 2884312be037SStefano Zampini -pc_bddc_neumann_lN_ 2885312be037SStefano Zampini -pc_bddc_coarse_lN_ 288628509bceSStefano Zampini .ve 28870f202f7eSStefano Zampini Note that level number ranges from the finest (0) to the coarsest (N). 28880f202f7eSStefano Zampini In order to specify options for the BDDC operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l to the option, e.g. 28890f202f7eSStefano Zampini .vb 28900f202f7eSStefano Zampini -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 28910f202f7eSStefano Zampini .ve 28920f202f7eSStefano 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 2893da1bb401SStefano Zampini 2894be4a8d98Sprj- References: 2895606c0280SSatish Balay + * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007 2896606c0280SSatish Balay . * - A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", Communications on Pure and Applied Mathematics Volume 59, Issue 11, pages 1523--1572, November 2006 2897606c0280SSatish Balay . * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008 2898606c0280SSatish Balay - * - C. Pechstein and C. R. Dohrmann. "Modern domain decomposition methods BDDC, deluxe scaling, and an algebraic approach", Seminar talk, Linz, December 2013, http://people.ricam.oeaw.ac.at/c.pechstein/pechstein-bddc2013.pdf 2899be4a8d98Sprj- 2900da1bb401SStefano Zampini Level: intermediate 2901da1bb401SStefano Zampini 2902e94cfbe0SPatrick Sanan Developer Notes: 2903da1bb401SStefano Zampini 2904da1bb401SStefano Zampini Contributed by Stefano Zampini 2905da1bb401SStefano Zampini 2906db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS` 2907da1bb401SStefano Zampini M*/ 2908b2573a8aSBarry Smith 29098cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 2910da1bb401SStefano Zampini { 2911da1bb401SStefano Zampini PC_BDDC *pcbddc; 2912da1bb401SStefano Zampini 2913da1bb401SStefano Zampini PetscFunctionBegin; 29149566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&pcbddc)); 29153ec1f749SStefano Zampini pc->data = pcbddc; 2916da1bb401SStefano Zampini 2917da1bb401SStefano Zampini /* create PCIS data structure */ 29189566063dSJacob Faibussowitsch PetscCall(PCISCreate(pc)); 2919da1bb401SStefano Zampini 29209326c5c6Sstefano_zampini /* create local graph structure */ 29219566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph)); 29229326c5c6Sstefano_zampini 29239326c5c6Sstefano_zampini /* BDDC nonzero defaults */ 29246d9e27e4SStefano Zampini pcbddc->use_nnsp = PETSC_TRUE; 292508a5cf49SStefano Zampini pcbddc->use_local_adj = PETSC_TRUE; 292647d04d0dSStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 292747d04d0dSStefano Zampini pcbddc->use_edges = PETSC_TRUE; 29283301b35fSStefano Zampini pcbddc->symmetric_primal = PETSC_TRUE; 292914f95afaSStefano Zampini pcbddc->vertex_size = 1; 2930c703fcc7SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 293168457ee5SStefano Zampini pcbddc->coarse_size = -1; 293285c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 293347d04d0dSStefano Zampini pcbddc->coarsening_ratio = 8; 293457de7509SStefano Zampini pcbddc->coarse_eqs_per_proc = 1; 293527b6a85dSStefano Zampini pcbddc->benign_compute_correction = PETSC_TRUE; 29361e0482f5SStefano Zampini pcbddc->nedfield = -1; 29371e0482f5SStefano Zampini pcbddc->nedglobal = PETSC_TRUE; 2938be12c134Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 2939b96c3477SStefano Zampini pcbddc->sub_schurs_layers = -1; 2940bd2a564bSStefano Zampini pcbddc->adaptive_threshold[0] = 0.0; 2941bd2a564bSStefano Zampini pcbddc->adaptive_threshold[1] = 0.0; 2942b7eb3628SStefano Zampini 2943da1bb401SStefano Zampini /* function pointers */ 2944da1bb401SStefano Zampini pc->ops->apply = PCApply_BDDC; 294593bd9ae7SStefano Zampini pc->ops->applytranspose = PCApplyTranspose_BDDC; 2946da1bb401SStefano Zampini pc->ops->setup = PCSetUp_BDDC; 2947da1bb401SStefano Zampini pc->ops->destroy = PCDestroy_BDDC; 2948da1bb401SStefano Zampini pc->ops->setfromoptions = PCSetFromOptions_BDDC; 29496b78500eSPatrick Sanan pc->ops->view = PCView_BDDC; 29500a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 29510a545947SLisandro Dalcin pc->ops->applysymmetricleft = NULL; 29520a545947SLisandro Dalcin pc->ops->applysymmetricright = NULL; 2953534831adSStefano Zampini pc->ops->presolve = PCPreSolve_BDDC; 2954534831adSStefano Zampini pc->ops->postsolve = PCPostSolve_BDDC; 29559326c5c6Sstefano_zampini pc->ops->reset = PCReset_BDDC; 2956da1bb401SStefano Zampini 2957da1bb401SStefano Zampini /* composing function */ 29589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC)); 29599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC)); 29609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC)); 29619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC)); 29629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC)); 29639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC)); 29649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC)); 29659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC)); 29669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC)); 29679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC)); 29689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC)); 29699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC)); 29709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC)); 29719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC)); 29729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC)); 29739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC)); 29749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC)); 29759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC)); 29769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC)); 29779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC)); 29789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC)); 29799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC)); 29809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC)); 29819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC)); 29829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC)); 29839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC)); 29849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC)); 2985da1bb401SStefano Zampini PetscFunctionReturn(0); 2986da1bb401SStefano Zampini } 298743371fb9SStefano Zampini 298843371fb9SStefano Zampini /*@C 298943371fb9SStefano Zampini PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called 29908a690491SBarry Smith from PCInitializePackage(). 299143371fb9SStefano Zampini 299243371fb9SStefano Zampini Level: developer 299343371fb9SStefano Zampini 2994db781477SPatrick Sanan .seealso: `PetscInitialize()` 299543371fb9SStefano Zampini @*/ 299643371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void) 299743371fb9SStefano Zampini { 299843371fb9SStefano Zampini int i; 299943371fb9SStefano Zampini 300043371fb9SStefano Zampini PetscFunctionBegin; 300143371fb9SStefano Zampini if (PCBDDCPackageInitialized) PetscFunctionReturn(0); 300243371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_TRUE; 30039566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage)); 300443371fb9SStefano Zampini 300543371fb9SStefano Zampini /* general events */ 30069566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0])); 30079566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0])); 30089566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0])); 30099566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0])); 30109566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0])); 30119566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0])); 30129566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0])); 30139566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0])); 30149566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0])); 30159566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0])); 30169566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0])); 30179566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0])); 30189566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1])); 30199566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2])); 302043371fb9SStefano Zampini for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) { 302143371fb9SStefano Zampini char ename[32]; 302243371fb9SStefano Zampini 30239566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i)); 30249566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i])); 30259566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i)); 30269566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i])); 30279566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i)); 30289566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i])); 30299566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i)); 30309566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i])); 30319566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i)); 30329566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i])); 30339566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i)); 30349566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i])); 30359566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i)); 30369566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i])); 30379566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i)); 30389566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i])); 30399566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i)); 30409566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i])); 30419566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i)); 30429566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i])); 30439566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i)); 30449566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i])); 30459566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i)); 30469566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0])); 30479566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i)); 30489566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1])); 30499566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i)); 30509566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2])); 305143371fb9SStefano Zampini } 305243371fb9SStefano Zampini PetscFunctionReturn(0); 305343371fb9SStefano Zampini } 305443371fb9SStefano Zampini 305543371fb9SStefano Zampini /*@C 305643371fb9SStefano Zampini PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is 305743371fb9SStefano Zampini called from PetscFinalize() automatically. 305843371fb9SStefano Zampini 305943371fb9SStefano Zampini Level: developer 306043371fb9SStefano Zampini 3061db781477SPatrick Sanan .seealso: `PetscFinalize()` 306243371fb9SStefano Zampini @*/ 306343371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void) 306443371fb9SStefano Zampini { 306543371fb9SStefano Zampini PetscFunctionBegin; 306643371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_FALSE; 306743371fb9SStefano Zampini PetscFunctionReturn(0); 306843371fb9SStefano Zampini } 3069