153cdbc3dSStefano Zampini /* TODOLIST 2eb97c9d2SStefano Zampini 3eb97c9d2SStefano Zampini Solvers 4a0d3c3abSStefano Zampini - Add support for cholesky for coarse solver (similar to local solvers) 5eb97c9d2SStefano Zampini - Propagate ksp prefixes for solvers to mat objects? 6eb97c9d2SStefano Zampini 7eb97c9d2SStefano Zampini User interface 80f202f7eSStefano Zampini - ** DM attached to pc? 9eb97c9d2SStefano Zampini 10eb97c9d2SStefano Zampini Debugging output 11b9b85e73SStefano Zampini - * Better management of verbosity levels of debugging output 12eb97c9d2SStefano Zampini 13eb97c9d2SStefano Zampini Extra 14b9b85e73SStefano Zampini - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)? 15eb97c9d2SStefano Zampini - BDDC with MG framework? 16eb97c9d2SStefano Zampini 17eb97c9d2SStefano Zampini MATIS related operations contained in BDDC code 18eb97c9d2SStefano Zampini - Provide general case for subassembling 19eb97c9d2SStefano Zampini 2053cdbc3dSStefano Zampini */ 210c7d97c5SJed Brown 22ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 23ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h> 243b03a366Sstefano_zampini #include <petscblaslapack.h> 25674ae819SStefano Zampini 2643371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE; 2743371fb9SStefano Zampini 28f3d41395Sstefano_zampini static PetscBool cited = PETSC_FALSE; 29f3d41395Sstefano_zampini static const char citation[] = 30f3d41395Sstefano_zampini "@article{ZampiniPCBDDC,\n" 31f3d41395Sstefano_zampini "author = {Stefano Zampini},\n" 32f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n" 33f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n" 34f3d41395Sstefano_zampini "volume = {38},\n" 35f3d41395Sstefano_zampini "number = {5},\n" 36f3d41395Sstefano_zampini "pages = {S282-S306},\n" 37f3d41395Sstefano_zampini "year = {2016},\n" 38f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n" 39f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n" 40f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n" 41f3d41395Sstefano_zampini "}\n"; 42f3d41395Sstefano_zampini 4343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS]; 4443371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS]; 4543371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS]; 4643371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS]; 478ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS]; 488ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS]; 4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS]; 5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS]; 5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS]; 5243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS]; 5343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS]; 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; 669566063dSJacob Faibussowitsch PetscCall(PetscOptionsHead(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)); 1309566063dSJacob Faibussowitsch PetscCall(PetscOptionsTail()); 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 } 1559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use verbose output: %D\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) { 1649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Graph max count: %D\n",pcbddc->graphmaxcount)); 165aefa1729SStefano Zampini } 1669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Corner selection: %d (selected %d)\n",pcbddc->corner_selection,pcbddc->corner_selected)); 1679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use vertices: %d (vertex size %D)\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])); 1809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Multilevel max levels: %D\n",pcbddc->max_levels)); 1819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Multilevel coarsening ratio: %D\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)); 1879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Number of dofs' layers for the computation of principal minors: %D\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]) { 1909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Adaptive constraint selection thresholds (active %d, userdefined %d): %g,%g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0],pcbddc->adaptive_threshold[1])); 191bd2a564bSStefano Zampini } else { 1929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Adaptive constraint selection threshold (active %d, userdefined %d): %g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0])); 193bd2a564bSStefano Zampini } 1949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Min constraints / connected component: %D\n",pcbddc->adaptive_nmin)); 1959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Max constraints / connected component: %D\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)); 1989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red)); 1999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Coarse eqs per proc (significant at the coarsest level): %D\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 } 2359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level)); 2369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Global dofs sizes: all %D interface %D coarse %D\n",pc->pmat->rmap->N,(PetscInt)PetscRealPart(interface_size),pcbddc->coarse_size)); 2379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2)); 2389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Active processes : %D\n",(PetscInt)gsum[0])); 2399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Total subdomains : %D\n",(PetscInt)gsum[5])); 240345ecf6cSStefano Zampini if (pcbddc->benign_have_null) { 2419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Benign subs : %D\n",(PetscInt)totbenign)); 242345ecf6cSStefano Zampini } 2439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Dofs type :\tMIN\tMAX\tMEAN\n")); 2449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Interior dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]))); 2459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Interface dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[2],(PetscInt)gmax[2],(PetscInt)(gsum[2]/gsum[0]))); 2469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Primal dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[3],(PetscInt)gmax[3],(PetscInt)(gsum[3]/gsum[0]))); 2479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Local dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[4],(PetscInt)gmax[4],(PetscInt)(gsum[4]/gsum[0]))); 2489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Local subs :\t%D\t%D\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 329495a2a07SStefano Zampini .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); 3419566063dSJacob Faibussowitsch PetscCall(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 380a198735bSStefano Zampini .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"); 3949566063dSJacob Faibussowitsch PetscCall(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 } 409b9b85e73SStefano Zampini /*@ 410906d46d4SStefano Zampini PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 411b9b85e73SStefano Zampini 412b9b85e73SStefano Zampini Collective on PC 413b9b85e73SStefano Zampini 414b9b85e73SStefano Zampini Input Parameters: 415b9b85e73SStefano Zampini + pc - the preconditioning context 4161dd7afcfSStefano Zampini . change - the change of basis matrix 4171dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs 418b9b85e73SStefano Zampini 419b9b85e73SStefano Zampini Level: intermediate 420b9b85e73SStefano Zampini 421b9b85e73SStefano Zampini Notes: 422b9b85e73SStefano Zampini 423b9b85e73SStefano Zampini .seealso: PCBDDC 424b9b85e73SStefano Zampini @*/ 4251dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior) 426b9b85e73SStefano Zampini { 427b9b85e73SStefano Zampini PetscFunctionBegin; 428b9b85e73SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 429b9b85e73SStefano Zampini PetscValidHeaderSpecific(change,MAT_CLASSID,2); 430906d46d4SStefano Zampini PetscCheckSameComm(pc,1,change,2); 431906d46d4SStefano Zampini if (pc->mat) { 432906d46d4SStefano Zampini PetscInt rows_c,cols_c,rows,cols; 4339566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat,&rows,&cols)); 4349566063dSJacob Faibussowitsch PetscCall(MatGetSize(change,&rows_c,&cols_c)); 435*7827d75bSBarry Smith PetscCheck(rows_c == rows,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %D != %D",rows_c,rows); 436*7827d75bSBarry Smith PetscCheck(cols_c == cols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %D != %D",cols_c,cols); 4379566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat,&rows,&cols)); 4389566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(change,&rows_c,&cols_c)); 439*7827d75bSBarry Smith PetscCheck(rows_c == rows,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %D != %D",rows_c,rows); 440*7827d75bSBarry Smith PetscCheck(cols_c == cols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %D != %D",cols_c,cols); 441906d46d4SStefano Zampini } 4429566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior))); 443b9b85e73SStefano Zampini PetscFunctionReturn(0); 444b9b85e73SStefano Zampini } 4452d505d7fSStefano Zampini 44630368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices) 44730368db7SStefano Zampini { 44830368db7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 44956282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 45030368db7SStefano Zampini 45130368db7SStefano Zampini PetscFunctionBegin; 4529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 45356282151SStefano Zampini if (pcbddc->user_primal_vertices) { 4549566063dSJacob Faibussowitsch PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal)); 45556282151SStefano Zampini } 4569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 4579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 45830368db7SStefano Zampini pcbddc->user_primal_vertices = PrimalVertices; 45956282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 46030368db7SStefano Zampini PetscFunctionReturn(0); 46130368db7SStefano Zampini } 462ab8c8b98SStefano Zampini 46330368db7SStefano Zampini /*@ 46430368db7SStefano Zampini PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC 46530368db7SStefano Zampini 46630368db7SStefano Zampini Collective 46730368db7SStefano Zampini 46830368db7SStefano Zampini Input Parameters: 46930368db7SStefano Zampini + pc - the preconditioning context 47030368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty) 47130368db7SStefano Zampini 47230368db7SStefano Zampini Level: intermediate 47330368db7SStefano Zampini 47430368db7SStefano Zampini Notes: 47530368db7SStefano Zampini Any process can list any global node 47630368db7SStefano Zampini 4773100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS() 47830368db7SStefano Zampini @*/ 47930368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices) 48030368db7SStefano Zampini { 48130368db7SStefano Zampini PetscFunctionBegin; 48230368db7SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 48330368db7SStefano Zampini PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 48430368db7SStefano Zampini PetscCheckSameComm(pc,1,PrimalVertices,2); 4859566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices))); 48630368db7SStefano Zampini PetscFunctionReturn(0); 48730368db7SStefano Zampini } 4882d505d7fSStefano Zampini 4893100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is) 4903100ebe3SStefano Zampini { 4913100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 4923100ebe3SStefano Zampini 4933100ebe3SStefano Zampini PetscFunctionBegin; 4943100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices; 4953100ebe3SStefano Zampini PetscFunctionReturn(0); 4963100ebe3SStefano Zampini } 4973100ebe3SStefano Zampini 4983100ebe3SStefano Zampini /*@ 4993100ebe3SStefano Zampini PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS() 5003100ebe3SStefano Zampini 5013100ebe3SStefano Zampini Collective 5023100ebe3SStefano Zampini 5033100ebe3SStefano Zampini Input Parameters: 5043100ebe3SStefano Zampini . pc - the preconditioning context 5053100ebe3SStefano Zampini 5063100ebe3SStefano Zampini Output Parameters: 5073100ebe3SStefano Zampini . is - index set of primal vertices in global numbering (NULL if not set) 5083100ebe3SStefano Zampini 5093100ebe3SStefano Zampini Level: intermediate 5103100ebe3SStefano Zampini 5113100ebe3SStefano Zampini Notes: 5123100ebe3SStefano Zampini 5133100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS() 5143100ebe3SStefano Zampini @*/ 5153100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) 5163100ebe3SStefano Zampini { 5173100ebe3SStefano Zampini PetscFunctionBegin; 5183100ebe3SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5193100ebe3SStefano Zampini PetscValidPointer(is,2); 5209566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is))); 5213100ebe3SStefano Zampini PetscFunctionReturn(0); 5223100ebe3SStefano Zampini } 5233100ebe3SStefano Zampini 524674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 525674ae819SStefano Zampini { 526674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 52756282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 5281e6b0712SBarry Smith 529674ae819SStefano Zampini PetscFunctionBegin; 5309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 53156282151SStefano Zampini if (pcbddc->user_primal_vertices_local) { 5329566063dSJacob Faibussowitsch PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal)); 53356282151SStefano Zampini } 5349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 5359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 53630368db7SStefano Zampini pcbddc->user_primal_vertices_local = PrimalVertices; 53756282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 538674ae819SStefano Zampini PetscFunctionReturn(0); 539674ae819SStefano Zampini } 5403100ebe3SStefano Zampini 541674ae819SStefano Zampini /*@ 54228509bceSStefano Zampini PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC 543674ae819SStefano Zampini 54417eb1463SStefano Zampini Collective 545674ae819SStefano Zampini 546674ae819SStefano Zampini Input Parameters: 547674ae819SStefano Zampini + pc - the preconditioning context 54817eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty) 549674ae819SStefano Zampini 550674ae819SStefano Zampini Level: intermediate 551674ae819SStefano Zampini 552674ae819SStefano Zampini Notes: 553674ae819SStefano Zampini 5543100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCGetPrimalVerticesLocalIS() 555674ae819SStefano Zampini @*/ 556674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 557674ae819SStefano Zampini { 558674ae819SStefano Zampini PetscFunctionBegin; 559674ae819SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 560674ae819SStefano Zampini PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 56117eb1463SStefano Zampini PetscCheckSameComm(pc,1,PrimalVertices,2); 5629566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices))); 563674ae819SStefano Zampini PetscFunctionReturn(0); 564674ae819SStefano Zampini } 5652d505d7fSStefano Zampini 5663100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) 5673100ebe3SStefano Zampini { 5683100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 5693100ebe3SStefano Zampini 5703100ebe3SStefano Zampini PetscFunctionBegin; 5713100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices_local; 5723100ebe3SStefano Zampini PetscFunctionReturn(0); 5733100ebe3SStefano Zampini } 5743100ebe3SStefano Zampini 5753100ebe3SStefano Zampini /*@ 5763100ebe3SStefano Zampini PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS() 5773100ebe3SStefano Zampini 5783100ebe3SStefano Zampini Collective 5793100ebe3SStefano Zampini 5803100ebe3SStefano Zampini Input Parameters: 5813100ebe3SStefano Zampini . pc - the preconditioning context 5823100ebe3SStefano Zampini 5833100ebe3SStefano Zampini Output Parameters: 5843100ebe3SStefano Zampini . is - index set of primal vertices in local numbering (NULL if not set) 5853100ebe3SStefano Zampini 5863100ebe3SStefano Zampini Level: intermediate 5873100ebe3SStefano Zampini 5883100ebe3SStefano Zampini Notes: 5893100ebe3SStefano Zampini 5903100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS() 5913100ebe3SStefano Zampini @*/ 5923100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) 5933100ebe3SStefano Zampini { 5943100ebe3SStefano Zampini PetscFunctionBegin; 5953100ebe3SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 5963100ebe3SStefano Zampini PetscValidPointer(is,2); 5979566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is))); 5983100ebe3SStefano Zampini PetscFunctionReturn(0); 5993100ebe3SStefano Zampini } 6003100ebe3SStefano Zampini 6014fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k) 6024fad6a16SStefano Zampini { 6034fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 6044fad6a16SStefano Zampini 6054fad6a16SStefano Zampini PetscFunctionBegin; 6064fad6a16SStefano Zampini pcbddc->coarsening_ratio = k; 6074fad6a16SStefano Zampini PetscFunctionReturn(0); 6084fad6a16SStefano Zampini } 6091e6b0712SBarry Smith 6104fad6a16SStefano Zampini /*@ 61128509bceSStefano Zampini PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel 6124fad6a16SStefano Zampini 6134fad6a16SStefano Zampini Logically collective on PC 6144fad6a16SStefano Zampini 6154fad6a16SStefano Zampini Input Parameters: 6164fad6a16SStefano Zampini + pc - the preconditioning context 61728509bceSStefano Zampini - k - coarsening ratio (H/h at the coarser level) 6184fad6a16SStefano Zampini 6190f202f7eSStefano Zampini Options Database Keys: 62067b8a455SSatish Balay . -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening 6214fad6a16SStefano Zampini 6224fad6a16SStefano Zampini Level: intermediate 6234fad6a16SStefano Zampini 6244fad6a16SStefano Zampini Notes: 6250f202f7eSStefano Zampini Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level 6264fad6a16SStefano Zampini 6270f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels() 6284fad6a16SStefano Zampini @*/ 6294fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k) 6304fad6a16SStefano Zampini { 6314fad6a16SStefano Zampini PetscFunctionBegin; 6324fad6a16SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 6332b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc,k,2); 6349566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k))); 6354fad6a16SStefano Zampini PetscFunctionReturn(0); 6364fad6a16SStefano Zampini } 6372b510759SStefano Zampini 638b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 639b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg) 640b8ffe317SStefano Zampini { 641b8ffe317SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 642b8ffe317SStefano Zampini 643b8ffe317SStefano Zampini PetscFunctionBegin; 64485c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = flg; 645b8ffe317SStefano Zampini PetscFunctionReturn(0); 646b8ffe317SStefano Zampini } 647b8ffe317SStefano Zampini 648b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg) 6492b510759SStefano Zampini { 6502b510759SStefano Zampini PetscFunctionBegin; 6512b510759SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 652b8ffe317SStefano Zampini PetscValidLogicalCollectiveBool(pc,flg,2); 6539566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg))); 6542b510759SStefano Zampini PetscFunctionReturn(0); 6552b510759SStefano Zampini } 6561e6b0712SBarry Smith 6572b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level) 6584fad6a16SStefano Zampini { 6594fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 6604fad6a16SStefano Zampini 6614fad6a16SStefano Zampini PetscFunctionBegin; 6622b510759SStefano Zampini pcbddc->current_level = level; 6634fad6a16SStefano Zampini PetscFunctionReturn(0); 6644fad6a16SStefano Zampini } 6651e6b0712SBarry Smith 666b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level) 667b8ffe317SStefano Zampini { 668b8ffe317SStefano Zampini PetscFunctionBegin; 669b8ffe317SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 670b8ffe317SStefano Zampini PetscValidLogicalCollectiveInt(pc,level,2); 6719566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level))); 672b8ffe317SStefano Zampini PetscFunctionReturn(0); 673b8ffe317SStefano Zampini } 674b8ffe317SStefano Zampini 6752b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels) 6762b510759SStefano Zampini { 6772b510759SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 6782b510759SStefano Zampini 6792b510759SStefano Zampini PetscFunctionBegin; 680*7827d75bSBarry 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); 6812b510759SStefano Zampini pcbddc->max_levels = levels; 6822b510759SStefano Zampini PetscFunctionReturn(0); 6832b510759SStefano Zampini } 6842b510759SStefano Zampini 6854fad6a16SStefano Zampini /*@ 68637ebbdf7SStefano Zampini PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC 6874fad6a16SStefano Zampini 6884fad6a16SStefano Zampini Logically collective on PC 6894fad6a16SStefano Zampini 6904fad6a16SStefano Zampini Input Parameters: 6914fad6a16SStefano Zampini + pc - the preconditioning context 69237ebbdf7SStefano Zampini - levels - the maximum number of levels 6934fad6a16SStefano Zampini 6940f202f7eSStefano Zampini Options Database Keys: 69567b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel 6964fad6a16SStefano Zampini 6974fad6a16SStefano Zampini Level: intermediate 6984fad6a16SStefano Zampini 6994fad6a16SStefano Zampini Notes: 70037ebbdf7SStefano Zampini The default value is 0, that gives the classical two-levels BDDC 7014fad6a16SStefano Zampini 7020f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio() 7034fad6a16SStefano Zampini @*/ 7042b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels) 7054fad6a16SStefano Zampini { 7064fad6a16SStefano Zampini PetscFunctionBegin; 7074fad6a16SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 7082b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc,levels,2); 7099566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels))); 7104fad6a16SStefano Zampini PetscFunctionReturn(0); 7114fad6a16SStefano Zampini } 7121e6b0712SBarry Smith 7133b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries) 7143b03a366Sstefano_zampini { 7153b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 71656282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7173b03a366Sstefano_zampini 7183b03a366Sstefano_zampini PetscFunctionBegin; 7199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 72056282151SStefano Zampini if (pcbddc->DirichletBoundaries) { 7219566063dSJacob Faibussowitsch PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal)); 72256282151SStefano Zampini } 723a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 72636e030ebSStefano Zampini pcbddc->DirichletBoundaries = DirichletBoundaries; 72756282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7283b03a366Sstefano_zampini PetscFunctionReturn(0); 7293b03a366Sstefano_zampini } 7301e6b0712SBarry Smith 7313b03a366Sstefano_zampini /*@ 73228509bceSStefano Zampini PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem. 7333b03a366Sstefano_zampini 734785d1243SStefano Zampini Collective 7353b03a366Sstefano_zampini 7363b03a366Sstefano_zampini Input Parameters: 7373b03a366Sstefano_zampini + pc - the preconditioning context 738785d1243SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries 7393b03a366Sstefano_zampini 7403b03a366Sstefano_zampini Level: intermediate 7413b03a366Sstefano_zampini 7420f202f7eSStefano Zampini Notes: 7430f202f7eSStefano Zampini Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node 7443b03a366Sstefano_zampini 7450f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns() 7463b03a366Sstefano_zampini @*/ 7473b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries) 7483b03a366Sstefano_zampini { 7493b03a366Sstefano_zampini PetscFunctionBegin; 7503b03a366Sstefano_zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 751674ae819SStefano Zampini PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 752785d1243SStefano Zampini PetscCheckSameComm(pc,1,DirichletBoundaries,2); 7539566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries))); 7543b03a366Sstefano_zampini PetscFunctionReturn(0); 7553b03a366Sstefano_zampini } 7561e6b0712SBarry Smith 75782ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries) 7583b03a366Sstefano_zampini { 7593b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 76056282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7613b03a366Sstefano_zampini 7623b03a366Sstefano_zampini PetscFunctionBegin; 7639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 76456282151SStefano Zampini if (pcbddc->DirichletBoundariesLocal) { 7659566063dSJacob Faibussowitsch PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal)); 76656282151SStefano Zampini } 767a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 770785d1243SStefano Zampini pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 77156282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7723b03a366Sstefano_zampini PetscFunctionReturn(0); 7733b03a366Sstefano_zampini } 7743b03a366Sstefano_zampini 7753b03a366Sstefano_zampini /*@ 77682ba6b80SStefano Zampini PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering. 7773b03a366Sstefano_zampini 778785d1243SStefano Zampini Collective 7793b03a366Sstefano_zampini 7803b03a366Sstefano_zampini Input Parameters: 7813b03a366Sstefano_zampini + pc - the preconditioning context 78282ba6b80SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering) 7833b03a366Sstefano_zampini 7843b03a366Sstefano_zampini Level: intermediate 7853b03a366Sstefano_zampini 7863b03a366Sstefano_zampini Notes: 7873b03a366Sstefano_zampini 7880f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns() 7893b03a366Sstefano_zampini @*/ 79082ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries) 7913b03a366Sstefano_zampini { 7923b03a366Sstefano_zampini PetscFunctionBegin; 7933b03a366Sstefano_zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 7943b03a366Sstefano_zampini PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 79582ba6b80SStefano Zampini PetscCheckSameComm(pc,1,DirichletBoundaries,2); 7969566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries))); 7973b03a366Sstefano_zampini PetscFunctionReturn(0); 7983b03a366Sstefano_zampini } 7993b03a366Sstefano_zampini 80053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries) 8010c7d97c5SJed Brown { 8020c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 80356282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 8040c7d97c5SJed Brown 8050c7d97c5SJed Brown PetscFunctionBegin; 8069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 80756282151SStefano Zampini if (pcbddc->NeumannBoundaries) { 8089566063dSJacob Faibussowitsch PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal)); 80956282151SStefano Zampini } 810a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 8119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 8129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 81336e030ebSStefano Zampini pcbddc->NeumannBoundaries = NeumannBoundaries; 81456282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 8150c7d97c5SJed Brown PetscFunctionReturn(0); 8160c7d97c5SJed Brown } 8171e6b0712SBarry Smith 81857527edcSJed Brown /*@ 81928509bceSStefano Zampini PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem. 82057527edcSJed Brown 821785d1243SStefano Zampini Collective 82257527edcSJed Brown 82357527edcSJed Brown Input Parameters: 82457527edcSJed Brown + pc - the preconditioning context 825785d1243SStefano Zampini - NeumannBoundaries - parallel IS defining the Neumann boundaries 82657527edcSJed Brown 82757527edcSJed Brown Level: intermediate 82857527edcSJed Brown 8290f202f7eSStefano Zampini Notes: 8300f202f7eSStefano Zampini Any process can list any global node 83157527edcSJed Brown 8320f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal() 83357527edcSJed Brown @*/ 83453cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries) 8350c7d97c5SJed Brown { 8360c7d97c5SJed Brown PetscFunctionBegin; 8370c7d97c5SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 838674ae819SStefano Zampini PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 839785d1243SStefano Zampini PetscCheckSameComm(pc,1,NeumannBoundaries,2); 8409566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries))); 84153cdbc3dSStefano Zampini PetscFunctionReturn(0); 84253cdbc3dSStefano Zampini } 8431e6b0712SBarry Smith 84482ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries) 8450c7d97c5SJed Brown { 8460c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 84756282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 8480c7d97c5SJed Brown 8490c7d97c5SJed Brown PetscFunctionBegin; 8509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 85156282151SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 8529566063dSJacob Faibussowitsch PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal)); 85356282151SStefano Zampini } 854a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 8559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 8569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 857785d1243SStefano Zampini pcbddc->NeumannBoundariesLocal = NeumannBoundaries; 85856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 8590c7d97c5SJed Brown PetscFunctionReturn(0); 8600c7d97c5SJed Brown } 8610c7d97c5SJed Brown 8620c7d97c5SJed Brown /*@ 86382ba6b80SStefano Zampini PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering. 8640c7d97c5SJed Brown 865785d1243SStefano Zampini Collective 8660c7d97c5SJed Brown 8670c7d97c5SJed Brown Input Parameters: 8680c7d97c5SJed Brown + pc - the preconditioning context 86982ba6b80SStefano Zampini - NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering) 8700c7d97c5SJed Brown 8710c7d97c5SJed Brown Level: intermediate 8720c7d97c5SJed Brown 8730c7d97c5SJed Brown Notes: 8740c7d97c5SJed Brown 8750f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries() 8760c7d97c5SJed Brown @*/ 87782ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries) 8780c7d97c5SJed Brown { 8790c7d97c5SJed Brown PetscFunctionBegin; 8800c7d97c5SJed Brown PetscValidHeaderSpecific(pc,PC_CLASSID,1); 8810c7d97c5SJed Brown PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 88282ba6b80SStefano Zampini PetscCheckSameComm(pc,1,NeumannBoundaries,2); 8839566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries))); 88453cdbc3dSStefano Zampini PetscFunctionReturn(0); 88553cdbc3dSStefano Zampini } 88653cdbc3dSStefano Zampini 887da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries) 888da1bb401SStefano Zampini { 889da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 890da1bb401SStefano Zampini 891da1bb401SStefano Zampini PetscFunctionBegin; 892da1bb401SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundaries; 893da1bb401SStefano Zampini PetscFunctionReturn(0); 894da1bb401SStefano Zampini } 8951e6b0712SBarry Smith 896da1bb401SStefano Zampini /*@ 897785d1243SStefano Zampini PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries 898da1bb401SStefano Zampini 899785d1243SStefano Zampini Collective 900785d1243SStefano Zampini 901785d1243SStefano Zampini Input Parameters: 902785d1243SStefano Zampini . pc - the preconditioning context 903785d1243SStefano Zampini 904785d1243SStefano Zampini Output Parameters: 905785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries 906785d1243SStefano Zampini 907785d1243SStefano Zampini Level: intermediate 908785d1243SStefano Zampini 9090f202f7eSStefano Zampini Notes: 9100f202f7eSStefano Zampini The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries 911785d1243SStefano Zampini 912785d1243SStefano Zampini .seealso: PCBDDC 913785d1243SStefano Zampini @*/ 914785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries) 915785d1243SStefano Zampini { 916785d1243SStefano Zampini PetscFunctionBegin; 917785d1243SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 9189566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries))); 919785d1243SStefano Zampini PetscFunctionReturn(0); 920785d1243SStefano Zampini } 921785d1243SStefano Zampini 922785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries) 923785d1243SStefano Zampini { 924785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 925785d1243SStefano Zampini 926785d1243SStefano Zampini PetscFunctionBegin; 927785d1243SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 928785d1243SStefano Zampini PetscFunctionReturn(0); 929785d1243SStefano Zampini } 930785d1243SStefano Zampini 931da1bb401SStefano Zampini /*@ 93282ba6b80SStefano Zampini PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering) 933da1bb401SStefano Zampini 934785d1243SStefano Zampini Collective 935da1bb401SStefano Zampini 936da1bb401SStefano Zampini Input Parameters: 93728509bceSStefano Zampini . pc - the preconditioning context 938da1bb401SStefano Zampini 939da1bb401SStefano Zampini Output Parameters: 94028509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 941da1bb401SStefano Zampini 942da1bb401SStefano Zampini Level: intermediate 943da1bb401SStefano Zampini 944da1bb401SStefano Zampini Notes: 9450f202f7eSStefano 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). 9460f202f7eSStefano Zampini In the latter case, the IS will be available after PCSetUp. 947da1bb401SStefano Zampini 948da1bb401SStefano Zampini .seealso: PCBDDC 949da1bb401SStefano Zampini @*/ 95082ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries) 951da1bb401SStefano Zampini { 952da1bb401SStefano Zampini PetscFunctionBegin; 953da1bb401SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 9549566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries))); 955da1bb401SStefano Zampini PetscFunctionReturn(0); 956da1bb401SStefano Zampini } 9571e6b0712SBarry Smith 95853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries) 95953cdbc3dSStefano Zampini { 96053cdbc3dSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 96153cdbc3dSStefano Zampini 96253cdbc3dSStefano Zampini PetscFunctionBegin; 96353cdbc3dSStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundaries; 96453cdbc3dSStefano Zampini PetscFunctionReturn(0); 96553cdbc3dSStefano Zampini } 9661e6b0712SBarry Smith 96753cdbc3dSStefano Zampini /*@ 968785d1243SStefano Zampini PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries 96953cdbc3dSStefano Zampini 970785d1243SStefano Zampini Collective 971785d1243SStefano Zampini 972785d1243SStefano Zampini Input Parameters: 973785d1243SStefano Zampini . pc - the preconditioning context 974785d1243SStefano Zampini 975785d1243SStefano Zampini Output Parameters: 976785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries 977785d1243SStefano Zampini 978785d1243SStefano Zampini Level: intermediate 979785d1243SStefano Zampini 9800f202f7eSStefano Zampini Notes: 9810f202f7eSStefano Zampini The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries 982785d1243SStefano Zampini 983785d1243SStefano Zampini .seealso: PCBDDC 984785d1243SStefano Zampini @*/ 985785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries) 986785d1243SStefano Zampini { 987785d1243SStefano Zampini PetscFunctionBegin; 988785d1243SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 9899566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries))); 990785d1243SStefano Zampini PetscFunctionReturn(0); 991785d1243SStefano Zampini } 992785d1243SStefano Zampini 993785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries) 994785d1243SStefano Zampini { 995785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 996785d1243SStefano Zampini 997785d1243SStefano Zampini PetscFunctionBegin; 998785d1243SStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 999785d1243SStefano Zampini PetscFunctionReturn(0); 1000785d1243SStefano Zampini } 1001785d1243SStefano Zampini 100253cdbc3dSStefano Zampini /*@ 100382ba6b80SStefano Zampini PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering) 100453cdbc3dSStefano Zampini 1005785d1243SStefano Zampini Collective 100653cdbc3dSStefano Zampini 100753cdbc3dSStefano Zampini Input Parameters: 100828509bceSStefano Zampini . pc - the preconditioning context 100953cdbc3dSStefano Zampini 101053cdbc3dSStefano Zampini Output Parameters: 101128509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 101253cdbc3dSStefano Zampini 101353cdbc3dSStefano Zampini Level: intermediate 101453cdbc3dSStefano Zampini 101553cdbc3dSStefano Zampini Notes: 10160f202f7eSStefano 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). 10170f202f7eSStefano Zampini In the latter case, the IS will be available after PCSetUp. 101853cdbc3dSStefano Zampini 101953cdbc3dSStefano Zampini .seealso: PCBDDC 102053cdbc3dSStefano Zampini @*/ 102182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries) 102253cdbc3dSStefano Zampini { 102353cdbc3dSStefano Zampini PetscFunctionBegin; 102453cdbc3dSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 10259566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries))); 10260c7d97c5SJed Brown PetscFunctionReturn(0); 10270c7d97c5SJed Brown } 10281e6b0712SBarry Smith 10291a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 103036e030ebSStefano Zampini { 103136e030ebSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1032da1bb401SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 103356282151SStefano Zampini PetscBool same_data = PETSC_FALSE; 103436e030ebSStefano Zampini 103536e030ebSStefano Zampini PetscFunctionBegin; 10368687889aSStefano Zampini if (!nvtxs) { 103704194a47SStefano Zampini if (copymode == PETSC_OWN_POINTER) { 10389566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 10399566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 104004194a47SStefano Zampini } 10419566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 10428687889aSStefano Zampini PetscFunctionReturn(0); 10438687889aSStefano Zampini } 104466da6bd7Sstefano_zampini if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */ 104556282151SStefano Zampini if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE; 104656282151SStefano Zampini if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) { 10479566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data)); 10482d505d7fSStefano Zampini if (same_data) { 10499566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data)); 10502d505d7fSStefano Zampini } 105156282151SStefano Zampini } 105256282151SStefano Zampini } 105356282151SStefano Zampini if (!same_data) { 1054674ae819SStefano Zampini /* free old CSR */ 10559566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 1056674ae819SStefano Zampini /* get CSR into graph structure */ 1057da1bb401SStefano Zampini if (copymode == PETSC_COPY_VALUES) { 10589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nvtxs+1,&mat_graph->xadj)); 10599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy)); 10609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1)); 10619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs])); 1062a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1063da1bb401SStefano Zampini } else if (copymode == PETSC_OWN_POINTER) { 10641a83f524SJed Brown mat_graph->xadj = (PetscInt*)xadj; 10651a83f524SJed Brown mat_graph->adjncy = (PetscInt*)adjncy; 1066a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1067a1dbd327SStefano Zampini } else if (copymode == PETSC_USE_POINTER) { 1068a1dbd327SStefano Zampini mat_graph->xadj = (PetscInt*)xadj; 1069a1dbd327SStefano Zampini mat_graph->adjncy = (PetscInt*)adjncy; 1070a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_FALSE; 107198921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode); 1072575ad6abSStefano Zampini mat_graph->nvtxs_csr = nvtxs; 107356282151SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 107456282151SStefano Zampini } 107536e030ebSStefano Zampini PetscFunctionReturn(0); 107636e030ebSStefano Zampini } 10771e6b0712SBarry Smith 107836e030ebSStefano Zampini /*@ 107954fffbccSStefano Zampini PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom. 108036e030ebSStefano Zampini 108136e030ebSStefano Zampini Not collective 108236e030ebSStefano Zampini 108336e030ebSStefano Zampini Input Parameters: 108454fffbccSStefano Zampini + pc - the preconditioning context. 108554fffbccSStefano Zampini . nvtxs - number of local vertices of the graph (i.e., the number of local dofs). 108654fffbccSStefano Zampini . xadj, adjncy - the connectivity of the dofs in CSR format. 108754fffbccSStefano Zampini - copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER. 108836e030ebSStefano Zampini 108936e030ebSStefano Zampini Level: intermediate 109036e030ebSStefano Zampini 109195452b02SPatrick Sanan Notes: 109295452b02SPatrick Sanan A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative. 109336e030ebSStefano Zampini 109428509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode 109536e030ebSStefano Zampini @*/ 10961a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 109736e030ebSStefano Zampini { 10980a545947SLisandro Dalcin void (*f)(void) = NULL; 109936e030ebSStefano Zampini 110036e030ebSStefano Zampini PetscFunctionBegin; 110136e030ebSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 11028687889aSStefano Zampini if (nvtxs) { 1103674ae819SStefano Zampini PetscValidIntPointer(xadj,3); 11041633d1f0SStefano Zampini if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4); 11058687889aSStefano Zampini } 11069566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode))); 1107575ad6abSStefano Zampini /* free arrays if PCBDDC is not the PC type */ 11089566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f)); 1109575ad6abSStefano Zampini if (!f && copymode == PETSC_OWN_POINTER) { 11109566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 11119566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 1112da1bb401SStefano Zampini } 111336e030ebSStefano Zampini PetscFunctionReturn(0); 111436e030ebSStefano Zampini } 11151e6b0712SBarry Smith 111663602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 111763602bcaSStefano Zampini { 111863602bcaSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 111963602bcaSStefano Zampini PetscInt i; 112056282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 112163602bcaSStefano Zampini 112263602bcaSStefano Zampini PetscFunctionBegin; 112356282151SStefano Zampini if (pcbddc->n_ISForDofsLocal == n_is) { 112456282151SStefano Zampini for (i=0;i<n_is;i++) { 112556282151SStefano Zampini PetscBool isequalt; 11269566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt)); 112756282151SStefano Zampini if (!isequalt) break; 112856282151SStefano Zampini } 112956282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 113056282151SStefano Zampini } 113156282151SStefano Zampini for (i=0;i<n_is;i++) { 11329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 113356282151SStefano Zampini } 113463602bcaSStefano Zampini /* Destroy ISes if they were already set */ 113563602bcaSStefano Zampini for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 11369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 113763602bcaSStefano Zampini } 11389566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 1139a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 114063602bcaSStefano Zampini for (i=0;i<pcbddc->n_ISForDofs;i++) { 11419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 114263602bcaSStefano Zampini } 11439566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 114463602bcaSStefano Zampini pcbddc->n_ISForDofs = 0; 114563602bcaSStefano Zampini /* allocate space then set */ 1146d02579f5SStefano Zampini if (n_is) { 11479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofsLocal)); 1148d02579f5SStefano Zampini } 114963602bcaSStefano Zampini for (i=0;i<n_is;i++) { 115063602bcaSStefano Zampini pcbddc->ISForDofsLocal[i] = ISForDofs[i]; 115163602bcaSStefano Zampini } 115263602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = n_is; 115363602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 115456282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 115563602bcaSStefano Zampini PetscFunctionReturn(0); 115663602bcaSStefano Zampini } 115763602bcaSStefano Zampini 115863602bcaSStefano Zampini /*@ 115963602bcaSStefano Zampini PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix 116063602bcaSStefano Zampini 116163602bcaSStefano Zampini Collective 116263602bcaSStefano Zampini 116363602bcaSStefano Zampini Input Parameters: 116463602bcaSStefano Zampini + pc - the preconditioning context 11650f202f7eSStefano Zampini . n_is - number of index sets defining the fields 11660f202f7eSStefano Zampini - ISForDofs - array of IS describing the fields in local ordering 116763602bcaSStefano Zampini 116863602bcaSStefano Zampini Level: intermediate 116963602bcaSStefano Zampini 11700f202f7eSStefano Zampini Notes: 11710f202f7eSStefano Zampini n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 117263602bcaSStefano Zampini 117363602bcaSStefano Zampini .seealso: PCBDDC 117463602bcaSStefano Zampini @*/ 117563602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[]) 117663602bcaSStefano Zampini { 117763602bcaSStefano Zampini PetscInt i; 117863602bcaSStefano Zampini 117963602bcaSStefano Zampini PetscFunctionBegin; 118063602bcaSStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 118163602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc,n_is,2); 118263602bcaSStefano Zampini for (i=0;i<n_is;i++) { 118363602bcaSStefano Zampini PetscCheckSameComm(pc,1,ISForDofs[i],3); 118463602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 118563602bcaSStefano Zampini } 11869566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs))); 118763602bcaSStefano Zampini PetscFunctionReturn(0); 118863602bcaSStefano Zampini } 118963602bcaSStefano Zampini 11909c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 11919c0446d6SStefano Zampini { 11929c0446d6SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 11939c0446d6SStefano Zampini PetscInt i; 119456282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 11959c0446d6SStefano Zampini 11969c0446d6SStefano Zampini PetscFunctionBegin; 119756282151SStefano Zampini if (pcbddc->n_ISForDofs == n_is) { 119856282151SStefano Zampini for (i=0;i<n_is;i++) { 119956282151SStefano Zampini PetscBool isequalt; 12009566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt)); 120156282151SStefano Zampini if (!isequalt) break; 120256282151SStefano Zampini } 120356282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 120456282151SStefano Zampini } 120556282151SStefano Zampini for (i=0;i<n_is;i++) { 12069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 120756282151SStefano Zampini } 1208da1bb401SStefano Zampini /* Destroy ISes if they were already set */ 12099c0446d6SStefano Zampini for (i=0;i<pcbddc->n_ISForDofs;i++) { 12109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 12119c0446d6SStefano Zampini } 12129566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 1213a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 121463602bcaSStefano Zampini for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 12159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 121663602bcaSStefano Zampini } 12179566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 121863602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = 0; 1219da1bb401SStefano Zampini /* allocate space then set */ 1220d02579f5SStefano Zampini if (n_is) { 12219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofs)); 1222d02579f5SStefano Zampini } 12239c0446d6SStefano Zampini for (i=0;i<n_is;i++) { 1224da1bb401SStefano Zampini pcbddc->ISForDofs[i] = ISForDofs[i]; 12259c0446d6SStefano Zampini } 12269c0446d6SStefano Zampini pcbddc->n_ISForDofs = n_is; 122763602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 122856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 12299c0446d6SStefano Zampini PetscFunctionReturn(0); 12309c0446d6SStefano Zampini } 12311e6b0712SBarry Smith 12329c0446d6SStefano Zampini /*@ 123363602bcaSStefano Zampini PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix 12349c0446d6SStefano Zampini 123563602bcaSStefano Zampini Collective 12369c0446d6SStefano Zampini 12379c0446d6SStefano Zampini Input Parameters: 12389c0446d6SStefano Zampini + pc - the preconditioning context 12390f202f7eSStefano Zampini . n_is - number of index sets defining the fields 12400f202f7eSStefano Zampini - ISForDofs - array of IS describing the fields in global ordering 12419c0446d6SStefano Zampini 12429c0446d6SStefano Zampini Level: intermediate 12439c0446d6SStefano Zampini 12440f202f7eSStefano Zampini Notes: 12450f202f7eSStefano Zampini Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 12469c0446d6SStefano Zampini 12479c0446d6SStefano Zampini .seealso: PCBDDC 12489c0446d6SStefano Zampini @*/ 12499c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[]) 12509c0446d6SStefano Zampini { 12512b510759SStefano Zampini PetscInt i; 12529c0446d6SStefano Zampini 12539c0446d6SStefano Zampini PetscFunctionBegin; 12549c0446d6SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 125563602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc,n_is,2); 12562b510759SStefano Zampini for (i=0;i<n_is;i++) { 125763602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 1258a011d5a7Sstefano_zampini PetscCheckSameComm(pc,1,ISForDofs[i],3); 12592b510759SStefano Zampini } 12609566063dSJacob Faibussowitsch PetscCall(PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs))); 12619c0446d6SStefano Zampini PetscFunctionReturn(0); 12629c0446d6SStefano Zampini } 1263906d46d4SStefano Zampini 1264534831adSStefano Zampini /* 1265534831adSStefano Zampini PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 1266534831adSStefano Zampini guess if a transformation of basis approach has been selected. 12679c0446d6SStefano Zampini 1268534831adSStefano Zampini Input Parameter: 1269966d8056SPierre Jolivet + pc - the preconditioner context 1270534831adSStefano Zampini 1271534831adSStefano Zampini Application Interface Routine: PCPreSolve() 1272534831adSStefano Zampini 1273534831adSStefano Zampini Notes: 1274534831adSStefano Zampini The interface routine PCPreSolve() is not usually called directly by 1275534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1276534831adSStefano Zampini */ 1277534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1278534831adSStefano Zampini { 1279534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1280534831adSStefano Zampini PC_IS *pcis = (PC_IS*)(pc->data); 12813972b0daSStefano Zampini Vec used_vec; 12824df7a6bfSStefano Zampini PetscBool iscg = PETSC_FALSE, save_rhs = PETSC_TRUE, benign_correction_computed; 1283534831adSStefano Zampini 1284534831adSStefano Zampini PetscFunctionBegin; 12851f4df5f7SStefano Zampini /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */ 128685c4d303SStefano Zampini if (ksp) { 12874df7a6bfSStefano Zampini PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr; 12884df7a6bfSStefano Zampini 12899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg)); 12909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg)); 12919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg)); 12929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg)); 12939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr)); 12944df7a6bfSStefano Zampini iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr); 12953bf6e316SStefano Zampini if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) { 12969566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE)); 129785c4d303SStefano Zampini } 129885c4d303SStefano Zampini } 12993bf6e316SStefano Zampini if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) { 13009566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE)); 1301fc17d649SStefano Zampini } 13021f4df5f7SStefano Zampini 130385c4d303SStefano Zampini /* Creates parallel work vectors used in presolve */ 130462a6ff1dSStefano Zampini if (!pcbddc->original_rhs) { 13059566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs)); 130662a6ff1dSStefano Zampini } 130762a6ff1dSStefano Zampini if (!pcbddc->temp_solution) { 13089566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution)); 130962a6ff1dSStefano Zampini } 13108d00608fSStefano Zampini 131127b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_FALSE; 13123972b0daSStefano Zampini if (x) { 13139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)x)); 13143972b0daSStefano Zampini used_vec = x; 13158d00608fSStefano Zampini } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 13169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution)); 13173972b0daSStefano Zampini used_vec = pcbddc->temp_solution; 13189566063dSJacob Faibussowitsch PetscCall(VecSet(used_vec,0.0)); 131927b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 13209566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs,pcbddc->original_rhs)); 1321266e20e9SStefano Zampini save_rhs = PETSC_FALSE; 1322266e20e9SStefano Zampini pcbddc->eliminate_dirdofs = PETSC_TRUE; 13233972b0daSStefano Zampini } 13248efcfb23SStefano Zampini 13258efcfb23SStefano Zampini /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 13263972b0daSStefano Zampini if (ksp) { 1327a0cb1b98SStefano Zampini /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 13289566063dSJacob Faibussowitsch PetscCall(KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero)); 13298efcfb23SStefano Zampini if (!pcbddc->ksp_guess_nonzero) { 13309566063dSJacob Faibussowitsch PetscCall(VecSet(used_vec,0.0)); 13313972b0daSStefano Zampini } 13323972b0daSStefano Zampini } 13333308cffdSStefano Zampini 13348d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 13353972b0daSStefano Zampini /* Take into account zeroed rows -> change rhs and store solution removed */ 133670c64980SStefano Zampini if (rhs && pcbddc->eliminate_dirdofs) { 13373975b054SStefano Zampini IS dirIS = NULL; 13383975b054SStefano Zampini 1339a07ea27aSStefano Zampini /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 13409566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS)); 13413975b054SStefano Zampini if (dirIS) { 1342906d46d4SStefano Zampini Mat_IS *matis = (Mat_IS*)pc->pmat->data; 1343785d1243SStefano Zampini PetscInt dirsize,i,*is_indices; 13442b095fd8SStefano Zampini PetscScalar *array_x; 13452b095fd8SStefano Zampini const PetscScalar *array_diagonal; 1346785d1243SStefano Zampini 13479566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(pc->pmat,pcis->vec1_global)); 13489566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global)); 13499566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD)); 13509566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD)); 13519566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 13529566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD)); 13539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS,&dirsize)); 13549566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N,&array_x)); 13559566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->vec2_N,&array_diagonal)); 13569566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS,(const PetscInt**)&is_indices)); 13572fa5cd67SKarl Rupp for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 13589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS,(const PetscInt**)&is_indices)); 13599566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->vec2_N,&array_diagonal)); 13609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N,&array_x)); 13619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE)); 13629566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE)); 13638d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 13649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 13658efcfb23SStefano Zampini } 1366a07ea27aSStefano Zampini } 1367b76ba322SStefano Zampini 13688efcfb23SStefano Zampini /* remove the computed solution or the initial guess from the rhs */ 13698d00608fSStefano Zampini if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) { 137027b6a85dSStefano Zampini /* save the original rhs */ 137127b6a85dSStefano Zampini if (save_rhs) { 13729566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs,pcbddc->original_rhs)); 137327b6a85dSStefano Zampini save_rhs = PETSC_FALSE; 13748d00608fSStefano Zampini } 13758d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 13769566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec,-1.0)); 13779566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs)); 13789566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec,-1.0)); 13799566063dSJacob Faibussowitsch PetscCall(VecCopy(used_vec,pcbddc->temp_solution)); 138027b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 13817acc28cbSStefano Zampini if (ksp) { 13829566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_FALSE)); 13837acc28cbSStefano Zampini } 13843308cffdSStefano Zampini } 13859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&used_vec)); 1386b76ba322SStefano Zampini 1387fc17d649SStefano Zampini /* compute initial vector in benign space if needed 138827b6a85dSStefano Zampini and remove non-benign solution from the rhs */ 138927b6a85dSStefano Zampini benign_correction_computed = PETSC_FALSE; 139008af2428SStefano Zampini if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) { 13911f4df5f7SStefano Zampini /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1) 13921f4df5f7SStefano Zampini Recursively apply BDDC in the multilevel case */ 13930369aaf7SStefano Zampini if (!pcbddc->benign_vec) { 13949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(rhs,&pcbddc->benign_vec)); 13950369aaf7SStefano Zampini } 1396c69e9cc1SStefano Zampini /* keep applying coarse solver unless we no longer have benign subdomains */ 1397c69e9cc1SStefano Zampini pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE; 139827b6a85dSStefano Zampini if (!pcbddc->benign_skip_correction) { 13999566063dSJacob Faibussowitsch PetscCall(PCApply_BDDC(pc,rhs,pcbddc->benign_vec)); 14003bca92a6SStefano Zampini benign_correction_computed = PETSC_TRUE; 14011f4df5f7SStefano Zampini if (pcbddc->temp_solution_used) { 14029566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec)); 14031f4df5f7SStefano Zampini } 14049566063dSJacob Faibussowitsch PetscCall(VecScale(pcbddc->benign_vec,-1.0)); 140527b6a85dSStefano Zampini /* store the original rhs if not done earlier */ 140627b6a85dSStefano Zampini if (save_rhs) { 14079566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs,pcbddc->original_rhs)); 140892e3dcfbSStefano Zampini } 140927b6a85dSStefano Zampini if (pcbddc->rhs_change) { 14109566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs)); 141127b6a85dSStefano Zampini } else { 14129566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs)); 141327b6a85dSStefano Zampini } 14140369aaf7SStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 141527b6a85dSStefano Zampini } 141627b6a85dSStefano Zampini pcbddc->benign_apply_coarse_only = PETSC_FALSE; 14174df7a6bfSStefano Zampini } else { 14189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 14190369aaf7SStefano Zampini } 14202d4c4fecSStefano Zampini 14212d4c4fecSStefano Zampini /* dbg output */ 1422a198735bSStefano Zampini if (pcbddc->dbg_flag && benign_correction_computed) { 14231f4df5f7SStefano Zampini Vec v; 1424c69e9cc1SStefano Zampini 14259566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&v)); 1426c69e9cc1SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 14279566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v)); 1428c69e9cc1SStefano Zampini } else { 14299566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs,v)); 1430c69e9cc1SStefano Zampini } 14319566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE)); 14329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level)); 14339566063dSJacob Faibussowitsch PetscCall(PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer)); 14349566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 14359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 14361f4df5f7SStefano Zampini } 14370369aaf7SStefano Zampini 14380369aaf7SStefano Zampini /* set initial guess if using PCG */ 14398ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 14400369aaf7SStefano Zampini if (x && pcbddc->use_exact_dirichlet_trick) { 14419566063dSJacob Faibussowitsch PetscCall(VecSet(x,0.0)); 14421dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 144327b6a85dSStefano Zampini if (benign_correction_computed) { /* we have already saved the changed rhs */ 14449566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 14451dd7afcfSStefano Zampini } else { 14469566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global)); 14471dd7afcfSStefano Zampini } 14489566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14499566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14501dd7afcfSStefano Zampini } else { 14519566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14529566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 14531dd7afcfSStefano Zampini } 14549566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 14559566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D)); 14569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 14579566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 14581dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 14599566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global,0.)); 14609566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE)); 14619566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE)); 14629566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x)); 14631dd7afcfSStefano Zampini } else { 14649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE)); 14659566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE)); 14661dd7afcfSStefano Zampini } 14670369aaf7SStefano Zampini if (ksp) { 14689566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_TRUE)); 14690369aaf7SStefano Zampini } 14708ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_TRUE; 1471266e20e9SStefano Zampini } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) { 14729566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 14730369aaf7SStefano Zampini } 1474534831adSStefano Zampini PetscFunctionReturn(0); 1475534831adSStefano Zampini } 1476906d46d4SStefano Zampini 1477534831adSStefano Zampini /* 1478534831adSStefano Zampini PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1479534831adSStefano Zampini approach has been selected. Also, restores rhs to its original state. 1480534831adSStefano Zampini 1481534831adSStefano Zampini Input Parameter: 1482966d8056SPierre Jolivet + pc - the preconditioner context 1483534831adSStefano Zampini 1484534831adSStefano Zampini Application Interface Routine: PCPostSolve() 1485534831adSStefano Zampini 1486534831adSStefano Zampini Notes: 1487534831adSStefano Zampini The interface routine PCPostSolve() is not usually called directly by 1488534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1489534831adSStefano Zampini */ 1490534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1491534831adSStefano Zampini { 1492534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1493534831adSStefano Zampini 1494534831adSStefano Zampini PetscFunctionBegin; 14953972b0daSStefano Zampini /* add solution removed in presolve */ 14966bcfc461SStefano Zampini if (x && pcbddc->rhs_change) { 149727b6a85dSStefano Zampini if (pcbddc->temp_solution_used) { 14989566063dSJacob Faibussowitsch PetscCall(VecAXPY(x,1.0,pcbddc->temp_solution)); 1499af140850Sstefano_zampini } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) { 15009566063dSJacob Faibussowitsch PetscCall(VecAXPY(x,-1.0,pcbddc->benign_vec)); 15013425bc38SStefano Zampini } 1502af140850Sstefano_zampini /* restore to original state (not for FETI-DP) */ 1503af140850Sstefano_zampini if (ksp) pcbddc->temp_solution_used = PETSC_FALSE; 150427b6a85dSStefano Zampini } 150527b6a85dSStefano Zampini 1506266e20e9SStefano Zampini /* restore rhs to its original state (not needed for FETI-DP) */ 15078d00608fSStefano Zampini if (rhs && pcbddc->rhs_change) { 15089566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs,pcbddc->original_rhs)); 15098d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 1510af140850Sstefano_zampini } 15118efcfb23SStefano Zampini /* restore ksp guess state */ 15128efcfb23SStefano Zampini if (ksp) { 15139566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero)); 15148ae0ca82SStefano Zampini /* reset flag for exact dirichlet trick */ 15158ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 1516af140850Sstefano_zampini } 1517534831adSStefano Zampini PetscFunctionReturn(0); 1518534831adSStefano Zampini } 1519af140850Sstefano_zampini 15200c7d97c5SJed Brown /* 15210c7d97c5SJed Brown PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 15220c7d97c5SJed Brown by setting data structures and options. 15230c7d97c5SJed Brown 15240c7d97c5SJed Brown Input Parameter: 152553cdbc3dSStefano Zampini + pc - the preconditioner context 15260c7d97c5SJed Brown 15270c7d97c5SJed Brown Application Interface Routine: PCSetUp() 15280c7d97c5SJed Brown 15290c7d97c5SJed Brown Notes: 15300c7d97c5SJed Brown The interface routine PCSetUp() is not usually called directly by 15310c7d97c5SJed Brown the user, but instead is called by PCApply() if necessary. 15320c7d97c5SJed Brown */ 153353cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc) 15340c7d97c5SJed Brown { 15350c7d97c5SJed Brown PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 1536c703fcc7SStefano Zampini PCBDDCSubSchurs sub_schurs; 15375e8657edSStefano Zampini Mat_IS* matis; 153808122e43SStefano Zampini MatNullSpace nearnullspace; 153935509ce9Sstefano_zampini Mat lA; 154035509ce9Sstefano_zampini IS lP,zerodiag = NULL; 154191e8d312SStefano Zampini PetscInt nrows,ncols; 154286bfa4cfSStefano Zampini PetscMPIInt size; 1543c703fcc7SStefano Zampini PetscBool computesubschurs; 15448de1fae6SStefano Zampini PetscBool computeconstraintsmatrix; 15453b03f7bbSStefano Zampini PetscBool new_nearnullspace_provided,ismatis,rl; 15460c7d97c5SJed Brown 15470c7d97c5SJed Brown PetscFunctionBegin; 15489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis)); 154928b400f6SJacob Faibussowitsch PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS"); 15509566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat,&nrows,&ncols)); 1551*7827d75bSBarry Smith PetscCheck(nrows == ncols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix"); 15529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size)); 155386bfa4cfSStefano Zampini 15545e8657edSStefano Zampini matis = (Mat_IS*)pc->pmat->data; 1555f4ddd8eeSStefano Zampini /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 15563b03a366Sstefano_zampini /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 155771582508SStefano Zampini Also, BDDC builds its own KSP for the Dirichlet problem */ 15583b03f7bbSStefano Zampini rl = pcbddc->recompute_topography; 15593b03f7bbSStefano Zampini if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE; 15609566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc))); 1561c83e1ba7SStefano Zampini if (pcbddc->recompute_topography) { 1562c83e1ba7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 1563c83e1ba7SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1564c83e1ba7SStefano Zampini } else { 15658de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_FALSE; 1566c83e1ba7SStefano Zampini } 1567b087196eSStefano Zampini 1568b087196eSStefano Zampini /* check parameters' compatibility */ 1569b7ab4a40SStefano Zampini if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE; 1570bd2a564bSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0); 157186bfa4cfSStefano Zampini pcbddc->use_deluxe_scaling = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1); 157286bfa4cfSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_selection && size > 1); 1573bf3a8328SStefano Zampini pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined); 1574862806e4SStefano Zampini if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1575862806e4SStefano Zampini 15765a95e1ceSStefano Zampini computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 157716909a7fSStefano Zampini 157871582508SStefano Zampini /* activate all connected components if the netflux has been requested */ 1579bb05f991SStefano Zampini if (pcbddc->compute_nonetflux) { 1580bb05f991SStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 1581bb05f991SStefano Zampini pcbddc->use_edges = PETSC_TRUE; 1582bb05f991SStefano Zampini pcbddc->use_faces = PETSC_TRUE; 1583bb05f991SStefano Zampini } 1584bb05f991SStefano Zampini 1585f4ddd8eeSStefano Zampini /* Get stdout for dbg */ 158670cf5478SStefano Zampini if (pcbddc->dbg_flag) { 158770cf5478SStefano Zampini if (!pcbddc->dbg_viewer) { 158858a03d70SStefano Zampini pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 1589f4ddd8eeSStefano Zampini } 15909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 15919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level)); 1592f4ddd8eeSStefano Zampini } 1593f4ddd8eeSStefano Zampini 1594c703fcc7SStefano Zampini /* process topology information */ 15959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0)); 159671582508SStefano Zampini if (pcbddc->recompute_topography) { 15979566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalTopologyInfo(pc)); 1598c703fcc7SStefano Zampini if (pcbddc->discretegradient) { 15999566063dSJacob Faibussowitsch PetscCall(PCBDDCNedelecSupport(pc)); 1600a13144ffSStefano Zampini } 1601c703fcc7SStefano Zampini } 16024f819b78SStefano Zampini if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE; 1603a13144ffSStefano Zampini 1604c703fcc7SStefano Zampini /* change basis if requested by the user */ 16055e8657edSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 16065e8657edSStefano Zampini /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 16075e8657edSStefano Zampini pcbddc->use_change_of_basis = PETSC_FALSE; 16089566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix)); 16095e8657edSStefano Zampini } else { 16109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 16119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 16125e8657edSStefano Zampini pcbddc->local_mat = matis->A; 1613d16cbb6bSStefano Zampini } 1614d16cbb6bSStefano Zampini 16154f1b2e48SStefano Zampini /* 1616c703fcc7SStefano Zampini Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick 16174f1b2e48SStefano Zampini This should come earlier then PCISSetUp for extracting the correct subdomain matrices 16184f1b2e48SStefano Zampini */ 16199566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc,PETSC_TRUE)); 1620d16cbb6bSStefano Zampini if (pcbddc->benign_saddle_point) { 16219f47a83aSStefano Zampini PC_IS* pcis = (PC_IS*)pc->data; 16229f47a83aSStefano Zampini 162305b28244SStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE; 16243b03f7bbSStefano Zampini /* detect local saddle point and change the basis in pcbddc->local_mat */ 16259566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag)); 1626a3df083aSStefano Zampini /* pop B0 mat from local mat */ 16279566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE)); 16281dd7afcfSStefano Zampini /* give pcis a hint to not reuse submatrices during PCISCreate */ 16291dd7afcfSStefano Zampini if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) { 16301dd7afcfSStefano Zampini if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) { 16311dd7afcfSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 16321dd7afcfSStefano Zampini } else { 1633a3df083aSStefano Zampini pcis->reusesubmatrices = PETSC_TRUE; 16341dd7afcfSStefano Zampini } 1635a3df083aSStefano Zampini } else { 16369f47a83aSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 1637674ae819SStefano Zampini } 1638a3df083aSStefano Zampini } 163927b6a85dSStefano Zampini 16408037d520SStefano Zampini /* propagate relevant information */ 164106a4e24aSStefano Zampini if (matis->A->symmetric_set) { 16429566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric)); 164306a4e24aSStefano Zampini } 164406a4e24aSStefano Zampini if (matis->A->spd_set) { 16459566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd)); 164606a4e24aSStefano Zampini } 1647e496cd5dSStefano Zampini 16485e8657edSStefano Zampini /* Set up all the "iterative substructuring" common block without computing solvers */ 16495e8657edSStefano Zampini { 16505e8657edSStefano Zampini Mat temp_mat; 16515e8657edSStefano Zampini 16525e8657edSStefano Zampini temp_mat = matis->A; 16535e8657edSStefano Zampini matis->A = pcbddc->local_mat; 16549566063dSJacob Faibussowitsch PetscCall(PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE)); 16555e8657edSStefano Zampini pcbddc->local_mat = matis->A; 16565e8657edSStefano Zampini matis->A = temp_mat; 16575e8657edSStefano Zampini } 1658684f6988SStefano Zampini 165981d14e9dSStefano Zampini /* Analyze interface */ 166064ac59b8SStefano Zampini if (!pcbddc->graphanalyzed) { 16619566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 16628de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1663345ecf6cSStefano Zampini if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) { 16644247aa23Sstefano_zampini SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling"); 1665345ecf6cSStefano Zampini } 1666a198735bSStefano Zampini if (pcbddc->compute_nonetflux) { 1667669cc0f4SStefano Zampini MatNullSpace nnfnnsp; 1668669cc0f4SStefano Zampini 166928b400f6SJacob Faibussowitsch PetscCheck(pcbddc->divudotp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator"); 16709566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp)); 167171582508SStefano Zampini /* TODO what if a nearnullspace is already attached? */ 16728037d520SStefano Zampini if (nnfnnsp) { 16739566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(pc->pmat,nnfnnsp)); 16749566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nnfnnsp)); 1675669cc0f4SStefano Zampini } 1676674ae819SStefano Zampini } 16778037d520SStefano Zampini } 16789566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0)); 1679fb8d54d4SStefano Zampini 16805408967cSStefano Zampini /* check existence of a divergence free extension, i.e. 16815408967cSStefano Zampini b(v_I,p_0) = 0 for all v_I (raise error if not). 16825408967cSStefano Zampini Also, check that PCBDDCBenignGetOrSetP0 works */ 1683ff1f7e73Sstefano_zampini if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) { 16849566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignCheck(pc,zerodiag)); 168509f581a4SStefano Zampini } 16869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 168706f24817SStefano Zampini 1688b96c3477SStefano Zampini /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 1689c703fcc7SStefano Zampini if (computesubschurs && pcbddc->recompute_topography) { 16909566063dSJacob Faibussowitsch PetscCall(PCBDDCInitSubSchurs(pc)); 1691b1b3d7a2SStefano Zampini } 16929d54b7f4SStefano Zampini /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/ 16939d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) { 16949566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingSetUp(pc)); 16959d54b7f4SStefano Zampini } 1696c703fcc7SStefano Zampini 1697c703fcc7SStefano Zampini /* finish setup solvers and do adaptive selection of constraints */ 1698b334f244SStefano Zampini sub_schurs = pcbddc->sub_schurs; 1699b334f244SStefano Zampini if (sub_schurs && sub_schurs->schur_explicit) { 17002070dbb6SStefano Zampini if (computesubschurs) { 17019566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpSubSchurs(pc)); 17022070dbb6SStefano Zampini } 17039566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE)); 1704d5574798SStefano Zampini } else { 17059566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE)); 17062070dbb6SStefano Zampini if (computesubschurs) { 17079566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpSubSchurs(pc)); 1708d5574798SStefano Zampini } 17092070dbb6SStefano Zampini } 171008122e43SStefano Zampini if (pcbddc->adaptive_selection) { 17119566063dSJacob Faibussowitsch PetscCall(PCBDDCAdaptiveSelection(pc)); 17128de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1713b7eb3628SStefano Zampini } 1714684f6988SStefano Zampini 1715f4ddd8eeSStefano Zampini /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1716fb8d54d4SStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 17179566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat,&nearnullspace)); 1718f4ddd8eeSStefano Zampini if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1719f4ddd8eeSStefano Zampini if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1720f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1721f4ddd8eeSStefano Zampini } else { 1722f4ddd8eeSStefano Zampini /* determine if the two nullspaces are different (should be lightweight) */ 1723f4ddd8eeSStefano Zampini if (nearnullspace != pcbddc->onearnullspace) { 1724f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1725165b64e2SStefano Zampini } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1726f4ddd8eeSStefano Zampini PetscInt i; 1727165b64e2SStefano Zampini const Vec *nearnullvecs; 1728165b64e2SStefano Zampini PetscObjectState state; 1729165b64e2SStefano Zampini PetscInt nnsp_size; 17309566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs)); 1731f4ddd8eeSStefano Zampini for (i=0;i<nnsp_size;i++) { 17329566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i],&state)); 1733165b64e2SStefano Zampini if (pcbddc->onearnullvecs_state[i] != state) { 1734f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1735f4ddd8eeSStefano Zampini break; 1736f4ddd8eeSStefano Zampini } 1737f4ddd8eeSStefano Zampini } 1738f4ddd8eeSStefano Zampini } 1739f4ddd8eeSStefano Zampini } 1740f4ddd8eeSStefano Zampini } else { 1741f4ddd8eeSStefano Zampini if (!nearnullspace) { /* both nearnullspaces are null */ 1742f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 1743f4ddd8eeSStefano Zampini } else { /* nearnullspace attached later */ 1744f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1745f4ddd8eeSStefano Zampini } 1746f4ddd8eeSStefano Zampini } 1747f4ddd8eeSStefano Zampini 1748f4ddd8eeSStefano Zampini /* Setup constraints and related work vectors */ 1749727cdba6SStefano Zampini /* reset primal space flags */ 17509566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0)); 1751f4ddd8eeSStefano Zampini pcbddc->new_primal_space = PETSC_FALSE; 1752727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_FALSE; 17538de1fae6SStefano Zampini if (computeconstraintsmatrix || new_nearnullspace_provided) { 1754727cdba6SStefano Zampini /* It also sets the primal space flags */ 17559566063dSJacob Faibussowitsch PetscCall(PCBDDCConstraintsSetUp(pc)); 17569543d0ffSStefano Zampini } 1757e7b262bdSStefano Zampini /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 17589566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalWorkVectors(pc)); 17595e8657edSStefano Zampini 17605e8657edSStefano Zampini if (pcbddc->use_change_of_basis) { 17615e8657edSStefano Zampini PC_IS *pcis = (PC_IS*)(pc->data); 17625e8657edSStefano Zampini 17639566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix)); 17644f1b2e48SStefano Zampini if (pcbddc->benign_change) { 17659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 1766c263805aSStefano Zampini /* pop B0 from pcbddc->local_mat */ 17679566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE)); 1768c263805aSStefano Zampini } 17695e8657edSStefano Zampini /* get submatrices */ 17709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 17719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 17729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BB)); 17739566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB)); 17749566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB)); 17759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI)); 17763975b054SStefano Zampini /* set flag in pcis to not reuse submatrices during PCISCreate */ 17773975b054SStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 17789c6a02ceSStefano Zampini } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) { 17799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 17809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 17815e8657edSStefano Zampini pcbddc->local_mat = matis->A; 17825e8657edSStefano Zampini } 178335509ce9Sstefano_zampini 178435509ce9Sstefano_zampini /* interface pressure block row for B_C */ 17859566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP)); 17869566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA)); 178735509ce9Sstefano_zampini if (lA && lP) { 178835509ce9Sstefano_zampini PC_IS* pcis = (PC_IS*)pc->data; 178935509ce9Sstefano_zampini Mat B_BI,B_BB,Bt_BI,Bt_BB; 179035509ce9Sstefano_zampini PetscBool issym; 17919566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(lA,PETSC_SMALL,&issym)); 17926cc1294bSstefano_zampini if (issym) { 17939566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI)); 17949566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB)); 17959566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BI,&Bt_BI)); 17969566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BB,&Bt_BB)); 179735509ce9Sstefano_zampini } else { 17989566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI)); 17999566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB)); 18009566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI)); 18019566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB)); 180235509ce9Sstefano_zampini } 18039566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI)); 18049566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB)); 18059566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI)); 18069566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB)); 18079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BI)); 18089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BB)); 18099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BI)); 18109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BB)); 181135509ce9Sstefano_zampini } 18129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0)); 181335509ce9Sstefano_zampini 1814b96c3477SStefano Zampini /* SetUp coarse and local Neumann solvers */ 18159566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpSolvers(pc)); 1816b96c3477SStefano Zampini /* SetUp Scaling operator */ 18179d54b7f4SStefano Zampini if (pcbddc->use_deluxe_scaling) { 18189566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingSetUp(pc)); 18190c7d97c5SJed Brown } 1820c703fcc7SStefano Zampini 18211dd7afcfSStefano Zampini /* mark topography as done */ 182256282151SStefano Zampini pcbddc->recompute_topography = PETSC_FALSE; 18230369aaf7SStefano Zampini 18241dd7afcfSStefano Zampini /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */ 18259566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc,PETSC_FALSE)); 18261dd7afcfSStefano Zampini 182758a03d70SStefano Zampini if (pcbddc->dbg_flag) { 18289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level)); 18299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 18302b510759SStefano Zampini } 18310c7d97c5SJed Brown PetscFunctionReturn(0); 18320c7d97c5SJed Brown } 18330c7d97c5SJed Brown 18340c7d97c5SJed Brown /* 183550efa1b5SStefano Zampini PCApply_BDDC - Applies the BDDC operator to a vector. 18360c7d97c5SJed Brown 18370c7d97c5SJed Brown Input Parameters: 18380f202f7eSStefano Zampini + pc - the preconditioner context 18390f202f7eSStefano Zampini - r - input vector (global) 18400c7d97c5SJed Brown 18410c7d97c5SJed Brown Output Parameter: 18420c7d97c5SJed Brown . z - output vector (global) 18430c7d97c5SJed Brown 18440c7d97c5SJed Brown Application Interface Routine: PCApply() 18450c7d97c5SJed Brown */ 184653cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 18470c7d97c5SJed Brown { 18480c7d97c5SJed Brown PC_IS *pcis = (PC_IS*)(pc->data); 18490c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1850b3338236SStefano Zampini Mat lA = NULL; 1851b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 18523b03a366Sstefano_zampini const PetscScalar one = 1.0; 18533b03a366Sstefano_zampini const PetscScalar m_one = -1.0; 18542617d88aSStefano Zampini const PetscScalar zero = 0.0; 18550c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN 18560c7d97c5SJed Brown NN interface preconditioner changed to BDDC 1857b097fa66SStefano Zampini Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 18580c7d97c5SJed Brown 18590c7d97c5SJed Brown PetscFunctionBegin; 18609566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation,&cited)); 1861b3338236SStefano Zampini if (pcbddc->switch_static) { 18629566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA)); 1863b3338236SStefano Zampini } 1864b3338236SStefano Zampini 18651dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 18661dd7afcfSStefano Zampini Vec swap; 186727b6a85dSStefano Zampini 18689566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change)); 18691dd7afcfSStefano Zampini swap = pcbddc->work_change; 18701dd7afcfSStefano Zampini pcbddc->work_change = r; 18711dd7afcfSStefano Zampini r = swap; 18721dd7afcfSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 18739cc2a9b1Sstefano_zampini if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 18749566063dSJacob Faibussowitsch PetscCall(VecCopy(r,pcis->vec1_global)); 18759566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 18761dd7afcfSStefano Zampini } 18771dd7afcfSStefano Zampini } 187827b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 18799566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE)); 1880efc2fbd9SStefano Zampini } 1881bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 18829566063dSJacob Faibussowitsch PetscCall(VecCopy(r,z)); 18830c7d97c5SJed Brown /* First Dirichlet solve */ 18849566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 18859566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 18860c7d97c5SJed Brown /* 18870c7d97c5SJed Brown Assembling right hand side for BDDC operator 1888b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1889674ae819SStefano Zampini - pcis->vec1_B the interface part of the global vector z 18900c7d97c5SJed Brown */ 1891b097fa66SStefano Zampini if (n_D) { 18929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 18939566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D)); 18949566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 18959566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 18969566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D,m_one)); 189716909a7fSStefano Zampini if (pcbddc->switch_static) { 18989566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N,0.)); 18999566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 19009566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 190116909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19029566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N)); 190316909a7fSStefano Zampini } else { 19049566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 19059566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec2_N,pcis->vec1_N)); 19069566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 190716909a7fSStefano Zampini } 19089566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 19099566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 19109566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 19119566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 191216909a7fSStefano Zampini } else { 19139566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B)); 191416909a7fSStefano Zampini } 1915b097fa66SStefano Zampini } else { 19169566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B,zero)); 1917b097fa66SStefano Zampini } 19189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 19199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 19209566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B)); 1921b76ba322SStefano Zampini } else { 19224fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 19239566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B)); 1924b76ba322SStefano Zampini } 19254fee134fSStefano Zampini } 1926bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 192728b400f6SJacob Faibussowitsch PetscCheck(pcbddc->switch_static,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static"); 19289566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 19299566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 1930bc960bbfSJed Brown } 1931b76ba322SStefano Zampini 19322617d88aSStefano Zampini /* Apply interface preconditioner 19332617d88aSStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 19349566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE)); 19352617d88aSStefano Zampini 1936674ae819SStefano Zampini /* Apply transpose of partition of unity operator */ 19379566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z)); 1938bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 19399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE)); 1941bc960bbfSJed Brown PetscFunctionReturn(0); 1942bc960bbfSJed Brown } 19433b03a366Sstefano_zampini /* Second Dirichlet solve and assembling of output */ 19449566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 19459566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 1946b097fa66SStefano Zampini if (n_B) { 194716909a7fSStefano Zampini if (pcbddc->switch_static) { 19489566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 19499566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 19509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 19519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 195216909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19539566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N)); 195416909a7fSStefano Zampini } else { 19559566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 19569566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec2_N,pcis->vec1_N)); 19579566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 195816909a7fSStefano Zampini } 19599566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD)); 19609566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD)); 196116909a7fSStefano Zampini } else { 19629566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D)); 196316909a7fSStefano Zampini } 196416909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 196516909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19669566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec1_D,pcis->vec3_D)); 196716909a7fSStefano Zampini } else { 19689566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N)); 19699566063dSJacob Faibussowitsch PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N)); 19709566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D)); 197116909a7fSStefano Zampini } 1972b097fa66SStefano Zampini } 19739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 19749566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D)); 19759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 19769566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D)); 1977efc2fbd9SStefano Zampini 19788ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1979b097fa66SStefano Zampini if (pcbddc->switch_static) { 19809566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D)); 1981b097fa66SStefano Zampini } else { 19829566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D)); 1983b097fa66SStefano Zampini } 19849566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19859566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 1986b097fa66SStefano Zampini } else { 1987b097fa66SStefano Zampini if (pcbddc->switch_static) { 19889566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D)); 1989b097fa66SStefano Zampini } else { 19909566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D,m_one)); 1991b097fa66SStefano Zampini } 19929566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 19939566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 1994b097fa66SStefano Zampini } 199527b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 19961dd7afcfSStefano Zampini if (pcbddc->benign_apply_coarse_only) { 19979566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 19981dd7afcfSStefano Zampini } 19999566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE)); 2000efc2fbd9SStefano Zampini } 20011f4df5f7SStefano Zampini 20021dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 2003f913dca9SStefano Zampini pcbddc->work_change = r; 20049566063dSJacob Faibussowitsch PetscCall(VecCopy(z,pcbddc->work_change)); 20059566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z)); 20061dd7afcfSStefano Zampini } 20070c7d97c5SJed Brown PetscFunctionReturn(0); 20080c7d97c5SJed Brown } 200950efa1b5SStefano Zampini 201050efa1b5SStefano Zampini /* 201150efa1b5SStefano Zampini PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 201250efa1b5SStefano Zampini 201350efa1b5SStefano Zampini Input Parameters: 20140f202f7eSStefano Zampini + pc - the preconditioner context 20150f202f7eSStefano Zampini - r - input vector (global) 201650efa1b5SStefano Zampini 201750efa1b5SStefano Zampini Output Parameter: 201850efa1b5SStefano Zampini . z - output vector (global) 201950efa1b5SStefano Zampini 202050efa1b5SStefano Zampini Application Interface Routine: PCApplyTranspose() 202150efa1b5SStefano Zampini */ 202250efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z) 202350efa1b5SStefano Zampini { 202450efa1b5SStefano Zampini PC_IS *pcis = (PC_IS*)(pc->data); 202550efa1b5SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 2026b3338236SStefano Zampini Mat lA = NULL; 2027b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 202850efa1b5SStefano Zampini const PetscScalar one = 1.0; 202950efa1b5SStefano Zampini const PetscScalar m_one = -1.0; 203050efa1b5SStefano Zampini const PetscScalar zero = 0.0; 203150efa1b5SStefano Zampini 203250efa1b5SStefano Zampini PetscFunctionBegin; 20339566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation,&cited)); 2034b3338236SStefano Zampini if (pcbddc->switch_static) { 20359566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA)); 2036b3338236SStefano Zampini } 20371dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 20381dd7afcfSStefano Zampini Vec swap; 203927b6a85dSStefano Zampini 20409566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change)); 20411dd7afcfSStefano Zampini swap = pcbddc->work_change; 20421dd7afcfSStefano Zampini pcbddc->work_change = r; 20431dd7afcfSStefano Zampini r = swap; 204427b6a85dSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 20458ae0ca82SStefano Zampini if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) { 20469566063dSJacob Faibussowitsch PetscCall(VecCopy(r,pcis->vec1_global)); 20479566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 20481dd7afcfSStefano Zampini } 204927b6a85dSStefano Zampini } 205027b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 20519566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE)); 2052537c1cdfSStefano Zampini } 20538ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 20549566063dSJacob Faibussowitsch PetscCall(VecCopy(r,z)); 205550efa1b5SStefano Zampini /* First Dirichlet solve */ 20569566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 20579566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD)); 205850efa1b5SStefano Zampini /* 205950efa1b5SStefano Zampini Assembling right hand side for BDDC operator 2060b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 206150efa1b5SStefano Zampini - pcis->vec1_B the interface part of the global vector z 206250efa1b5SStefano Zampini */ 2063b097fa66SStefano Zampini if (n_D) { 20649566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 20659566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D)); 20669566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 20679566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D)); 20689566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D,m_one)); 206916909a7fSStefano Zampini if (pcbddc->switch_static) { 20709566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N,0.)); 20719566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 20729566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 207316909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 20749566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N)); 207516909a7fSStefano Zampini } else { 20769566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 20779566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N)); 20789566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 207916909a7fSStefano Zampini } 20809566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 20819566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD)); 20829566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 20839566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 208416909a7fSStefano Zampini } else { 20859566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B)); 208616909a7fSStefano Zampini } 2087b097fa66SStefano Zampini } else { 20889566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B,zero)); 2089b097fa66SStefano Zampini } 20909566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 20919566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE)); 20929566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B)); 209350efa1b5SStefano Zampini } else { 20949566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B)); 209550efa1b5SStefano Zampini } 209650efa1b5SStefano Zampini 209750efa1b5SStefano Zampini /* Apply interface preconditioner 209850efa1b5SStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 20999566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE)); 210050efa1b5SStefano Zampini 210150efa1b5SStefano Zampini /* Apply transpose of partition of unity operator */ 21029566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z)); 210350efa1b5SStefano Zampini 210450efa1b5SStefano Zampini /* Second Dirichlet solve and assembling of output */ 21059566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 21069566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD)); 2107b097fa66SStefano Zampini if (n_B) { 210816909a7fSStefano Zampini if (pcbddc->switch_static) { 21099566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 21109566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 21119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 21129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE)); 211316909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 21149566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N)); 211516909a7fSStefano Zampini } else { 21169566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 21179566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N)); 21189566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N)); 211916909a7fSStefano Zampini } 21209566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD)); 21219566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD)); 212216909a7fSStefano Zampini } else { 21239566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D)); 212416909a7fSStefano Zampini } 212516909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 212616909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 21279566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D)); 212816909a7fSStefano Zampini } else { 21299566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N)); 21309566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N)); 21319566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D)); 213216909a7fSStefano Zampini } 2133b097fa66SStefano Zampini } 21349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 21359566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D)); 21369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0)); 21379566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D)); 21388ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 2139b097fa66SStefano Zampini if (pcbddc->switch_static) { 21409566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D)); 2141b097fa66SStefano Zampini } else { 21429566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D)); 2143b097fa66SStefano Zampini } 21449566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 21459566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE)); 2146b097fa66SStefano Zampini } else { 2147b097fa66SStefano Zampini if (pcbddc->switch_static) { 21489566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D)); 2149b097fa66SStefano Zampini } else { 21509566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D,m_one)); 2151b097fa66SStefano Zampini } 21529566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 21539566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE)); 2154b097fa66SStefano Zampini } 215527b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 21569566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE)); 2157537c1cdfSStefano Zampini } 21581dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 2159f913dca9SStefano Zampini pcbddc->work_change = r; 21609566063dSJacob Faibussowitsch PetscCall(VecCopy(z,pcbddc->work_change)); 21619566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z)); 21621dd7afcfSStefano Zampini } 216350efa1b5SStefano Zampini PetscFunctionReturn(0); 216450efa1b5SStefano Zampini } 2165674ae819SStefano Zampini 21669326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc) 2167da1bb401SStefano Zampini { 2168da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 21699326c5c6Sstefano_zampini PC_IS *pcis = (PC_IS*)pc->data; 21709326c5c6Sstefano_zampini KSP kspD,kspR,kspC; 2171da1bb401SStefano Zampini 2172da1bb401SStefano Zampini PetscFunctionBegin; 2173674ae819SStefano Zampini /* free BDDC custom data */ 21749566063dSJacob Faibussowitsch PetscCall(PCBDDCResetCustomization(pc)); 2175674ae819SStefano Zampini /* destroy objects related to topography */ 21769566063dSJacob Faibussowitsch PetscCall(PCBDDCResetTopography(pc)); 217734a97f8cSStefano Zampini /* destroy objects for scaling operator */ 21789566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingDestroy(pc)); 2179674ae819SStefano Zampini /* free solvers stuff */ 21809566063dSJacob Faibussowitsch PetscCall(PCBDDCResetSolvers(pc)); 218162a6ff1dSStefano Zampini /* free global vectors needed in presolve */ 21829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->temp_solution)); 21839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->original_rhs)); 21841dd7afcfSStefano Zampini /* free data created by PCIS */ 21859566063dSJacob Faibussowitsch PetscCall(PCISDestroy(pc)); 21869326c5c6Sstefano_zampini 21879326c5c6Sstefano_zampini /* restore defaults */ 21889326c5c6Sstefano_zampini kspD = pcbddc->ksp_D; 21899326c5c6Sstefano_zampini kspR = pcbddc->ksp_R; 21909326c5c6Sstefano_zampini kspC = pcbddc->coarse_ksp; 21919566063dSJacob Faibussowitsch PetscCall(PetscMemzero(pc->data,sizeof(*pcbddc))); 21929326c5c6Sstefano_zampini pcis->n_neigh = -1; 21939326c5c6Sstefano_zampini pcis->scaling_factor = 1.0; 21949326c5c6Sstefano_zampini pcis->reusesubmatrices = PETSC_TRUE; 21959326c5c6Sstefano_zampini pcbddc->use_local_adj = PETSC_TRUE; 21969326c5c6Sstefano_zampini pcbddc->use_vertices = PETSC_TRUE; 21979326c5c6Sstefano_zampini pcbddc->use_edges = PETSC_TRUE; 21989326c5c6Sstefano_zampini pcbddc->symmetric_primal = PETSC_TRUE; 21999326c5c6Sstefano_zampini pcbddc->vertex_size = 1; 22009326c5c6Sstefano_zampini pcbddc->recompute_topography = PETSC_TRUE; 22019326c5c6Sstefano_zampini pcbddc->coarse_size = -1; 22029326c5c6Sstefano_zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 22039326c5c6Sstefano_zampini pcbddc->coarsening_ratio = 8; 22049326c5c6Sstefano_zampini pcbddc->coarse_eqs_per_proc = 1; 22059326c5c6Sstefano_zampini pcbddc->benign_compute_correction = PETSC_TRUE; 22069326c5c6Sstefano_zampini pcbddc->nedfield = -1; 22079326c5c6Sstefano_zampini pcbddc->nedglobal = PETSC_TRUE; 22089326c5c6Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 22099326c5c6Sstefano_zampini pcbddc->sub_schurs_layers = -1; 22109326c5c6Sstefano_zampini pcbddc->ksp_D = kspD; 22119326c5c6Sstefano_zampini pcbddc->ksp_R = kspR; 22129326c5c6Sstefano_zampini pcbddc->coarse_ksp = kspC; 22139326c5c6Sstefano_zampini PetscFunctionReturn(0); 22149326c5c6Sstefano_zampini } 22159326c5c6Sstefano_zampini 22169326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc) 22179326c5c6Sstefano_zampini { 22189326c5c6Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 22199326c5c6Sstefano_zampini 22209326c5c6Sstefano_zampini PetscFunctionBegin; 22219566063dSJacob Faibussowitsch PetscCall(PCReset_BDDC(pc)); 22229566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_D)); 22239566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_R)); 22249566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->coarse_ksp)); 22259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL)); 22269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL)); 22279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL)); 22289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL)); 22299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL)); 22309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL)); 22319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL)); 22329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL)); 22339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL)); 22349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL)); 22359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL)); 22369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL)); 22379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL)); 22389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL)); 22399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL)); 22409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL)); 22419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL)); 22429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL)); 22439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL)); 22449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL)); 22459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL)); 22469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL)); 22479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL)); 22489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL)); 22499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL)); 22509566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2251da1bb401SStefano Zampini PetscFunctionReturn(0); 2252da1bb401SStefano Zampini } 22531e6b0712SBarry Smith 2254ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) 2255ab8c8b98SStefano Zampini { 2256ab8c8b98SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2257ab8c8b98SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 2258ab8c8b98SStefano Zampini 2259ab8c8b98SStefano Zampini PetscFunctionBegin; 22609566063dSJacob Faibussowitsch PetscCall(PetscFree(mat_graph->coords)); 22619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc*dim,&mat_graph->coords)); 22629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->coords,coords,nloc*dim)); 2263ab8c8b98SStefano Zampini mat_graph->cnloc = nloc; 2264ab8c8b98SStefano Zampini mat_graph->cdim = dim; 2265ab8c8b98SStefano Zampini mat_graph->cloc = PETSC_FALSE; 22664f819b78SStefano Zampini /* flg setup */ 22674f819b78SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 22684f819b78SStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 2269ab8c8b98SStefano Zampini PetscFunctionReturn(0); 2270ab8c8b98SStefano Zampini } 2271ab8c8b98SStefano Zampini 2272a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change) 2273a06fd7f2SStefano Zampini { 2274a06fd7f2SStefano Zampini PetscFunctionBegin; 2275a06fd7f2SStefano Zampini *change = PETSC_TRUE; 2276a06fd7f2SStefano Zampini PetscFunctionReturn(0); 2277a06fd7f2SStefano Zampini } 2278a06fd7f2SStefano Zampini 22793425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 22803425bc38SStefano Zampini { 2281674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 2282266e20e9SStefano Zampini Vec work; 22833425bc38SStefano Zampini PC_IS* pcis; 22843425bc38SStefano Zampini PC_BDDC* pcbddc; 22850c7d97c5SJed Brown 22863425bc38SStefano Zampini PetscFunctionBegin; 22879566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 22883425bc38SStefano Zampini pcis = (PC_IS*)mat_ctx->pc->data; 22893425bc38SStefano Zampini pcbddc = (PC_BDDC*)mat_ctx->pc->data; 22903425bc38SStefano Zampini 22919566063dSJacob Faibussowitsch PetscCall(VecSet(fetidp_flux_rhs,0.0)); 2292229984c5Sstefano_zampini /* copy rhs since we may change it during PCPreSolve_BDDC */ 2293229984c5Sstefano_zampini if (!pcbddc->original_rhs) { 22949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs)); 2295229984c5Sstefano_zampini } 22966cc1294bSstefano_zampini if (mat_ctx->rhs_flip) { 22979566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip)); 22986cc1294bSstefano_zampini } else { 22999566063dSJacob Faibussowitsch PetscCall(VecCopy(standard_rhs,pcbddc->original_rhs)); 23006cc1294bSstefano_zampini } 2301af140850Sstefano_zampini if (mat_ctx->g2g_p) { 2302229984c5Sstefano_zampini /* interface pressure rhs */ 23039566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE)); 23049566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE)); 23059566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD)); 23069566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD)); 23076cc1294bSstefano_zampini if (!mat_ctx->rhs_flip) { 23089566063dSJacob Faibussowitsch PetscCall(VecScale(fetidp_flux_rhs,-1.)); 2309229984c5Sstefano_zampini } 23106cc1294bSstefano_zampini } 2311c08af4c6SStefano Zampini /* 2312c08af4c6SStefano Zampini change of basis for physical rhs if needed 2313c08af4c6SStefano Zampini It also changes the rhs in case of dirichlet boundaries 2314c08af4c6SStefano Zampini */ 23159566063dSJacob Faibussowitsch PetscCall(PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL)); 2316fc17d649SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 23179566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change)); 23183738a8e6SStefano Zampini work = pcbddc->work_change; 2319fc17d649SStefano Zampini } else { 23203738a8e6SStefano Zampini work = pcbddc->original_rhs; 2321fc17d649SStefano Zampini } 23223425bc38SStefano Zampini /* store vectors for computation of fetidp final solution */ 23239566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD)); 23249566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD)); 2325fb223d50SStefano Zampini /* scale rhs since it should be unassembled */ 2326fb223d50SStefano Zampini /* TODO use counter scaling? (also below) */ 23279566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 23289566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 2329674ae819SStefano Zampini /* Apply partition of unity */ 23309566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B)); 23319566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 23328eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 23333425bc38SStefano Zampini /* compute partially subassembled Schur complement right-hand side */ 23349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 23359566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D)); 23369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 2337c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 23389566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B)); 23399566063dSJacob Faibussowitsch PetscCall(VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B)); 23409566063dSJacob Faibussowitsch PetscCall(VecSet(work,0.0)); 23419566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE)); 23429566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE)); 23439566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 23449566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 23459566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD)); 23469566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B)); 23473425bc38SStefano Zampini } 23483425bc38SStefano Zampini /* BDDC rhs */ 23499566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B)); 23508eeda7d8SStefano Zampini if (pcbddc->switch_static) { 23519566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D)); 23523425bc38SStefano Zampini } 23533425bc38SStefano Zampini /* apply BDDC */ 23549566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 23559566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE)); 23569566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 2357229984c5Sstefano_zampini 23583425bc38SStefano Zampini /* Application of B_delta and assembling of rhs for fetidp fluxes */ 23599566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local)); 23609566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 23619566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 2362229984c5Sstefano_zampini /* Add contribution to interface pressures */ 2363229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 23649566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP)); 2365229984c5Sstefano_zampini if (pcbddc->switch_static) { 23669566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP)); 2367229984c5Sstefano_zampini } 23689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 23699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD)); 2370229984c5Sstefano_zampini } 23713425bc38SStefano Zampini PetscFunctionReturn(0); 23723425bc38SStefano Zampini } 23731e6b0712SBarry Smith 23743425bc38SStefano Zampini /*@ 23750f202f7eSStefano Zampini PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side 23763425bc38SStefano Zampini 23773425bc38SStefano Zampini Collective 23783425bc38SStefano Zampini 23793425bc38SStefano Zampini Input Parameters: 23800f202f7eSStefano Zampini + fetidp_mat - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators 23810f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system 23823425bc38SStefano Zampini 23833425bc38SStefano Zampini Output Parameters: 23840f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 23853425bc38SStefano Zampini 23863425bc38SStefano Zampini Level: developer 23873425bc38SStefano Zampini 23883425bc38SStefano Zampini Notes: 23893425bc38SStefano Zampini 23900f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution 23913425bc38SStefano Zampini @*/ 23923425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 23933425bc38SStefano Zampini { 2394674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 23953425bc38SStefano Zampini 23963425bc38SStefano Zampini PetscFunctionBegin; 2397266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1); 2398266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2); 2399266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3); 24009566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 24019566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs))); 24023425bc38SStefano Zampini PetscFunctionReturn(0); 24033425bc38SStefano Zampini } 24041e6b0712SBarry Smith 24053425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 24063425bc38SStefano Zampini { 2407674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 24083425bc38SStefano Zampini PC_IS* pcis; 24093425bc38SStefano Zampini PC_BDDC* pcbddc; 2410229984c5Sstefano_zampini Vec work; 24113425bc38SStefano Zampini 24123425bc38SStefano Zampini PetscFunctionBegin; 24139566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 24143425bc38SStefano Zampini pcis = (PC_IS*)mat_ctx->pc->data; 24153425bc38SStefano Zampini pcbddc = (PC_BDDC*)mat_ctx->pc->data; 24163425bc38SStefano Zampini 24173425bc38SStefano Zampini /* apply B_delta^T */ 24189566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B,0.)); 24199566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE)); 24209566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE)); 24219566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B)); 2422229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 24239566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE)); 24249566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE)); 24259566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B)); 2426229984c5Sstefano_zampini } 2427229984c5Sstefano_zampini 24283425bc38SStefano Zampini /* compute rhs for BDDC application */ 24299566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B)); 24308eeda7d8SStefano Zampini if (pcbddc->switch_static) { 24319566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D)); 2432229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 24339566063dSJacob Faibussowitsch PetscCall(VecScale(mat_ctx->vP,-1.)); 24349566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D)); 24353425bc38SStefano Zampini } 2436229984c5Sstefano_zampini } 2437229984c5Sstefano_zampini 24383425bc38SStefano Zampini /* apply BDDC */ 24399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n)); 24409566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE)); 2441229984c5Sstefano_zampini 2442229984c5Sstefano_zampini /* put values into global vector */ 2443af140850Sstefano_zampini if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change; 2444af140850Sstefano_zampini else work = standard_sol; 24459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE)); 24469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE)); 24478eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 24483425bc38SStefano Zampini /* compute values into the interior if solved for the partially subassembled Schur complement */ 24499566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D)); 24509566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D)); 24519566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 24529566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D)); 24539566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0)); 2454c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 24553425bc38SStefano Zampini } 2456229984c5Sstefano_zampini 24579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE)); 24589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE)); 2459266e20e9SStefano Zampini /* add p0 solution to final solution */ 24609566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE)); 2461fc17d649SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 24629566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol)); 2463fc17d649SStefano Zampini } 24649566063dSJacob Faibussowitsch PetscCall(PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol)); 2465af140850Sstefano_zampini if (mat_ctx->g2g_p) { 24669566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE)); 24679566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE)); 2468229984c5Sstefano_zampini } 24693425bc38SStefano Zampini PetscFunctionReturn(0); 24703425bc38SStefano Zampini } 24711e6b0712SBarry Smith 24725a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) 24735a1e936bSStefano Zampini { 24745a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24755a1e936bSStefano Zampini PetscBool isascii; 24765a1e936bSStefano Zampini 24775a1e936bSStefano Zampini PetscFunctionBegin; 24789566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 24799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 24805a1e936bSStefano Zampini if (isascii) { 24819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n")); 24825a1e936bSStefano Zampini } 24839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 24849566063dSJacob Faibussowitsch PetscCall(PCView(bddcipc_ctx->bddc,viewer)); 24859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 24865a1e936bSStefano Zampini PetscFunctionReturn(0); 24875a1e936bSStefano Zampini } 24885a1e936bSStefano Zampini 24895a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc) 24905a1e936bSStefano Zampini { 24915a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24925a1e936bSStefano Zampini PetscBool isbddc; 24935a1e936bSStefano Zampini Vec vv; 24945a1e936bSStefano Zampini IS is; 24955a1e936bSStefano Zampini PC_IS *pcis; 24965a1e936bSStefano Zampini 24975a1e936bSStefano Zampini PetscFunctionBegin; 24989566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 24999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc)); 250028b400f6SJacob Faibussowitsch PetscCheck(isbddc,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name); 25019566063dSJacob Faibussowitsch PetscCall(PCSetUp(bddcipc_ctx->bddc)); 25025a1e936bSStefano Zampini 25035a1e936bSStefano Zampini /* create interface scatter */ 25045a1e936bSStefano Zampini pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 25059566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 25069566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat,&vv,NULL)); 25079566063dSJacob Faibussowitsch PetscCall(ISRenumber(pcis->is_B_global,NULL,NULL,&is)); 25089566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l)); 25099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 25109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vv)); 25115a1e936bSStefano Zampini PetscFunctionReturn(0); 25125a1e936bSStefano Zampini } 25135a1e936bSStefano Zampini 25145a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) 25155a1e936bSStefano Zampini { 25165a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 25175a1e936bSStefano Zampini PC_IS *pcis; 25185a1e936bSStefano Zampini VecScatter tmps; 25195a1e936bSStefano Zampini 25205a1e936bSStefano Zampini PetscFunctionBegin; 25219566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 25225a1e936bSStefano Zampini pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 25235a1e936bSStefano Zampini tmps = pcis->global_to_B; 25245a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 25259566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B)); 25269566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE)); 25279566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x)); 25285a1e936bSStefano Zampini pcis->global_to_B = tmps; 25295a1e936bSStefano Zampini PetscFunctionReturn(0); 25305a1e936bSStefano Zampini } 25315a1e936bSStefano Zampini 25325a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) 25335a1e936bSStefano Zampini { 25345a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 25355a1e936bSStefano Zampini PC_IS *pcis; 25365a1e936bSStefano Zampini VecScatter tmps; 25375a1e936bSStefano Zampini 25385a1e936bSStefano Zampini PetscFunctionBegin; 25399566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 25405a1e936bSStefano Zampini pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 25415a1e936bSStefano Zampini tmps = pcis->global_to_B; 25425a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 25439566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B)); 25449566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE)); 25459566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x)); 25465a1e936bSStefano Zampini pcis->global_to_B = tmps; 25475a1e936bSStefano Zampini PetscFunctionReturn(0); 25485a1e936bSStefano Zampini } 25495a1e936bSStefano Zampini 25505a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc) 25515a1e936bSStefano Zampini { 25525a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 25535a1e936bSStefano Zampini 25545a1e936bSStefano Zampini PetscFunctionBegin; 25559566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc,&bddcipc_ctx)); 25569566063dSJacob Faibussowitsch PetscCall(PCDestroy(&bddcipc_ctx->bddc)); 25579566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 25589566063dSJacob Faibussowitsch PetscCall(PetscFree(bddcipc_ctx)); 25595a1e936bSStefano Zampini PetscFunctionReturn(0); 25605a1e936bSStefano Zampini } 25615a1e936bSStefano Zampini 25623425bc38SStefano Zampini /*@ 25630f202f7eSStefano Zampini PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 25643425bc38SStefano Zampini 25653425bc38SStefano Zampini Collective 25663425bc38SStefano Zampini 25673425bc38SStefano Zampini Input Parameters: 25680f202f7eSStefano Zampini + fetidp_mat - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators 25690f202f7eSStefano Zampini - fetidp_flux_sol - the solution of the FETI-DP linear system 25703425bc38SStefano Zampini 25713425bc38SStefano Zampini Output Parameters: 25720f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain 25733425bc38SStefano Zampini 25743425bc38SStefano Zampini Level: developer 25753425bc38SStefano Zampini 25763425bc38SStefano Zampini Notes: 25773425bc38SStefano Zampini 25780f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS 25793425bc38SStefano Zampini @*/ 25803425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 25813425bc38SStefano Zampini { 2582674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 25833425bc38SStefano Zampini 25843425bc38SStefano Zampini PetscFunctionBegin; 2585266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1); 2586266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2); 2587266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3); 25889566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx)); 25899566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol))); 25903425bc38SStefano Zampini PetscFunctionReturn(0); 25913425bc38SStefano Zampini } 25921e6b0712SBarry Smith 2593547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc) 25943425bc38SStefano Zampini { 2595674ae819SStefano Zampini 2596674ae819SStefano Zampini FETIDPMat_ctx fetidpmat_ctx; 25973425bc38SStefano Zampini Mat newmat; 2598674ae819SStefano Zampini FETIDPPC_ctx fetidppc_ctx; 25993425bc38SStefano Zampini PC newpc; 2600ce94432eSBarry Smith MPI_Comm comm; 26013425bc38SStefano Zampini 26023425bc38SStefano Zampini PetscFunctionBegin; 26039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc,&comm)); 260415579a77SStefano Zampini /* FETI-DP matrix */ 26059566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx)); 26061720468bSStefano Zampini fetidpmat_ctx->fully_redundant = fully_redundant; 26079566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx)); 26089566063dSJacob Faibussowitsch PetscCall(MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat)); 26099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G")); 26109566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult)); 26119566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose)); 26129566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat)); 261315579a77SStefano Zampini /* propagate MatOptions */ 261415579a77SStefano Zampini { 261515579a77SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data; 261615579a77SStefano Zampini PetscBool issym; 261715579a77SStefano Zampini 26189566063dSJacob Faibussowitsch PetscCall(MatGetOption(pc->mat,MAT_SYMMETRIC,&issym)); 261915579a77SStefano Zampini if (issym || pcbddc->symmetric_primal) { 26209566063dSJacob Faibussowitsch PetscCall(MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE)); 262115579a77SStefano Zampini } 262215579a77SStefano Zampini } 26239566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(newmat,prefix)); 26249566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(newmat,"fetidp_")); 26259566063dSJacob Faibussowitsch PetscCall(MatSetUp(newmat)); 262615579a77SStefano Zampini /* FETI-DP preconditioner */ 26279566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx)); 26289566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx)); 26299566063dSJacob Faibussowitsch PetscCall(PCCreate(comm,&newpc)); 26309566063dSJacob Faibussowitsch PetscCall(PCSetOperators(newpc,newmat,newmat)); 26319566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(newpc,prefix)); 26329566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(newpc,"fetidp_")); 26339566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(newpc,pc->erroriffailure)); 263415579a77SStefano Zampini if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */ 26359566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc,PCSHELL)); 26369566063dSJacob Faibussowitsch PetscCall(PCShellSetName(newpc,"FETI-DP multipliers")); 26379566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(newpc,fetidppc_ctx)); 26389566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(newpc,FETIDPPCApply)); 26399566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose)); 26409566063dSJacob Faibussowitsch PetscCall(PCShellSetView(newpc,FETIDPPCView)); 26419566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC)); 26425a1e936bSStefano Zampini } else { /* saddle-point FETI-DP */ 26435a1e936bSStefano Zampini Mat M; 26445a1e936bSStefano Zampini PetscInt psize; 26455a1e936bSStefano Zampini PetscBool fake = PETSC_FALSE, isfieldsplit; 2646e1214c54Sstefano_zampini 26479566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view")); 26489566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view")); 26499566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M)); 26509566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc,PCFIELDSPLIT)); 26519566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange)); 26529566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure)); 26539566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR)); 26549566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG)); 26559566063dSJacob Faibussowitsch PetscCall(ISGetSize(fetidpmat_ctx->pressure,&psize)); 26565a1e936bSStefano Zampini if (psize != M->rmap->N) { 26575a1e936bSStefano Zampini Mat M2; 26585a1e936bSStefano Zampini PetscInt lpsize; 26595a1e936bSStefano Zampini 26605a1e936bSStefano Zampini fake = PETSC_TRUE; 26619566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize)); 26629566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&M2)); 26639566063dSJacob Faibussowitsch PetscCall(MatSetType(M2,MATAIJ)); 26649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M2,lpsize,lpsize,psize,psize)); 26659566063dSJacob Faibussowitsch PetscCall(MatSetUp(M2)); 26669566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY)); 26679566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY)); 26689566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2)); 26699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M2)); 26705a1e936bSStefano Zampini } else { 26719566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M)); 26725a1e936bSStefano Zampini } 26739566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurScale(newpc,1.0)); 267415579a77SStefano Zampini 267515579a77SStefano Zampini /* we need to setfromoptions and setup here to access the blocks */ 26769566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(newpc)); 26779566063dSJacob Faibussowitsch PetscCall(PCSetUp(newpc)); 2678e1214c54Sstefano_zampini 26795a1e936bSStefano Zampini /* user may have changed the type (e.g. -fetidp_pc_type none) */ 26809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit)); 26815a1e936bSStefano Zampini if (isfieldsplit) { 26825a1e936bSStefano Zampini KSP *ksps; 26835a1e936bSStefano Zampini PC ppc,lagpc; 26845a1e936bSStefano Zampini PetscInt nn; 2685064a4176SStefano Zampini PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE; 26865a1e936bSStefano Zampini 2687e1214c54Sstefano_zampini /* set the solver for the (0,0) block */ 26889566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps)); 26895a1e936bSStefano Zampini if (!nn) { /* not of type PC_COMPOSITE_SCHUR */ 26909566063dSJacob Faibussowitsch PetscCall(PCFieldSplitGetSubKSP(newpc,&nn,&ksps)); 26915a1e936bSStefano Zampini if (!fake) { /* pass pmat to the pressure solver */ 26925a1e936bSStefano Zampini Mat F; 26935a1e936bSStefano Zampini 26949566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[1],&F,NULL)); 26959566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksps[1],F,M)); 26965a1e936bSStefano Zampini } 26975a1e936bSStefano Zampini } else { 26985a1e936bSStefano Zampini PetscBool issym; 26995a1e936bSStefano Zampini Mat S; 27005a1e936bSStefano Zampini 27019566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetS(newpc,&S)); 27025a1e936bSStefano Zampini 27039566063dSJacob Faibussowitsch PetscCall(MatGetOption(newmat,MAT_SYMMETRIC,&issym)); 27045a1e936bSStefano Zampini if (issym) { 27059566063dSJacob Faibussowitsch PetscCall(MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE)); 27065a1e936bSStefano Zampini } 27075a1e936bSStefano Zampini } 27089566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[0],&lagpc)); 27099566063dSJacob Faibussowitsch PetscCall(PCSetType(lagpc,PCSHELL)); 27109566063dSJacob Faibussowitsch PetscCall(PCShellSetName(lagpc,"FETI-DP multipliers")); 27119566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(lagpc,fetidppc_ctx)); 27129566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(lagpc,FETIDPPCApply)); 27139566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose)); 27149566063dSJacob Faibussowitsch PetscCall(PCShellSetView(lagpc,FETIDPPCView)); 27159566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC)); 27165a1e936bSStefano Zampini 27175a1e936bSStefano Zampini /* Olof's idea: interface Schur complement preconditioner for the mass matrix */ 27189566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[1],&ppc)); 27195a1e936bSStefano Zampini if (fake) { 27205a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 2721ff11fd76SStefano Zampini PetscContainer c; 27225a1e936bSStefano Zampini 27235a1e936bSStefano Zampini matisok = PETSC_TRUE; 27245a1e936bSStefano Zampini 27255a1e936bSStefano Zampini /* create inner BDDC solver */ 27269566063dSJacob Faibussowitsch PetscCall(PetscNew(&bddcipc_ctx)); 27279566063dSJacob Faibussowitsch PetscCall(PCCreate(comm,&bddcipc_ctx->bddc)); 27289566063dSJacob Faibussowitsch PetscCall(PCSetType(bddcipc_ctx->bddc,PCBDDC)); 27299566063dSJacob Faibussowitsch PetscCall(PCSetOperators(bddcipc_ctx->bddc,M,M)); 27309566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c)); 27319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis)); 2732ff11fd76SStefano Zampini if (c && ismatis) { 2733ff11fd76SStefano Zampini Mat lM; 2734ff11fd76SStefano Zampini PetscInt *csr,n; 2735ff11fd76SStefano Zampini 27369566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(M,&lM)); 27379566063dSJacob Faibussowitsch PetscCall(MatGetSize(lM,&n,NULL)); 27389566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c,(void**)&csr)); 27399566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES)); 27409566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(M,&lM)); 2741ff11fd76SStefano Zampini } 27429566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix)); 27439566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure)); 27449566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(bddcipc_ctx->bddc)); 27455a1e936bSStefano Zampini 27465a1e936bSStefano Zampini /* wrap the interface application */ 27479566063dSJacob Faibussowitsch PetscCall(PCSetType(ppc,PCSHELL)); 27489566063dSJacob Faibussowitsch PetscCall(PCShellSetName(ppc,"FETI-DP pressure")); 27499566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(ppc,bddcipc_ctx)); 27509566063dSJacob Faibussowitsch PetscCall(PCShellSetSetUp(ppc,PCSetUp_BDDCIPC)); 27519566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(ppc,PCApply_BDDCIPC)); 27529566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC)); 27539566063dSJacob Faibussowitsch PetscCall(PCShellSetView(ppc,PCView_BDDCIPC)); 27549566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(ppc,PCDestroy_BDDCIPC)); 27555a1e936bSStefano Zampini } 27565a1e936bSStefano Zampini 27575a1e936bSStefano Zampini /* determine if we need to assemble M to construct a preconditioner */ 27585a1e936bSStefano Zampini if (!matisok) { 27599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis)); 27609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"")); 27615a1e936bSStefano Zampini if (ismatis && !matisok) { 27629566063dSJacob Faibussowitsch PetscCall(MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M)); 27635a1e936bSStefano Zampini } 27645a1e936bSStefano Zampini } 2765064a4176SStefano Zampini 2766064a4176SStefano Zampini /* run the subproblems to check convergence */ 27679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL)); 2768064a4176SStefano Zampini if (check) { 2769064a4176SStefano Zampini PetscInt i; 2770064a4176SStefano Zampini 2771064a4176SStefano Zampini for (i=0;i<nn;i++) { 2772064a4176SStefano Zampini KSP kspC; 2773064a4176SStefano Zampini PC pc; 2774064a4176SStefano Zampini Mat F,pF; 2775064a4176SStefano Zampini Vec x,y; 2776064a4176SStefano Zampini PetscBool isschur,prec = PETSC_TRUE; 2777064a4176SStefano Zampini 27789566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC)); 27799566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix)); 27809566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(kspC,"check_")); 27819566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[i],&F,&pF)); 27829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur)); 2783064a4176SStefano Zampini if (isschur) { 2784064a4176SStefano Zampini KSP kspS,kspS2; 2785064a4176SStefano Zampini Mat A00,pA00,A10,A01,A11; 2786064a4176SStefano Zampini char prefix[256]; 2787064a4176SStefano Zampini 27889566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F,&kspS)); 27899566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11)); 27909566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F)); 27919566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F,&kspS2)); 27929566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix)); 27939566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspS2,prefix)); 27949566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2,&pc)); 27959566063dSJacob Faibussowitsch PetscCall(PCSetType(pc,PCKSP)); 27969566063dSJacob Faibussowitsch PetscCall(PCKSPSetKSP(pc,kspS)); 27979566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspS2)); 27989566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2,&pc)); 27999566063dSJacob Faibussowitsch PetscCall(PCSetUseAmat(pc,PETSC_TRUE)); 2800064a4176SStefano Zampini } else { 28019566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)F)); 2802064a4176SStefano Zampini } 28039566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspC)); 28049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL)); 2805064a4176SStefano Zampini if (prec) { 28069566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[i],&pc)); 28079566063dSJacob Faibussowitsch PetscCall(KSPSetPC(kspC,pc)); 2808064a4176SStefano Zampini } 28099566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(kspC,F,pF)); 28109566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(F,&x,&y)); 28119566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x,NULL)); 28129566063dSJacob Faibussowitsch PetscCall(MatMult(F,x,y)); 28139566063dSJacob Faibussowitsch PetscCall(KSPSolve(kspC,y,x)); 28149566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(kspC,pc,x)); 28159566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&kspC)); 28169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&F)); 28179566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 28189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 2819064a4176SStefano Zampini } 2820064a4176SStefano Zampini } 28219566063dSJacob Faibussowitsch PetscCall(PetscFree(ksps)); 2822e1214c54Sstefano_zampini } 28235a1e936bSStefano Zampini } 28243425bc38SStefano Zampini /* return pointers for objects created */ 28253425bc38SStefano Zampini *fetidp_mat = newmat; 28263425bc38SStefano Zampini *fetidp_pc = newpc; 28273425bc38SStefano Zampini PetscFunctionReturn(0); 28283425bc38SStefano Zampini } 28291e6b0712SBarry Smith 283094ef8ddeSSatish Balay /*@C 28310f202f7eSStefano Zampini PCBDDCCreateFETIDPOperators - Create FETI-DP operators 28323425bc38SStefano Zampini 28333425bc38SStefano Zampini Collective 28343425bc38SStefano Zampini 28353425bc38SStefano Zampini Input Parameters: 28361720468bSStefano Zampini + pc - the BDDC preconditioning context (setup should have been called before) 2837547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers 2838547c9a8eSstefano_zampini - prefix - optional options database prefix for the objects to be created (can be NULL) 283928509bceSStefano Zampini 284028509bceSStefano Zampini Output Parameters: 28410f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object 28420f202f7eSStefano Zampini - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 284328509bceSStefano Zampini 28443425bc38SStefano Zampini Level: developer 28453425bc38SStefano Zampini 28463425bc38SStefano Zampini Notes: 28470f202f7eSStefano Zampini Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose 28483425bc38SStefano Zampini 28490f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution 28503425bc38SStefano Zampini @*/ 2851547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) 28523425bc38SStefano Zampini { 28533425bc38SStefano Zampini PetscFunctionBegin; 28543425bc38SStefano Zampini PetscValidHeaderSpecific(pc,PC_CLASSID,1); 28553425bc38SStefano Zampini if (pc->setupcalled) { 28569566063dSJacob Faibussowitsch PetscCall(PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc))); 28576080607fSStefano Zampini } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first"); 28583425bc38SStefano Zampini PetscFunctionReturn(0); 28593425bc38SStefano Zampini } 28600c7d97c5SJed Brown /* -------------------------------------------------------------------------- */ 2861da1bb401SStefano Zampini /*MC 2862da1bb401SStefano Zampini PCBDDC - Balancing Domain Decomposition by Constraints. 28630c7d97c5SJed Brown 2864be4a8d98Sprj- An implementation of the BDDC preconditioner based on the bibliography found below. 286528509bceSStefano Zampini 286628509bceSStefano Zampini The matrix to be preconditioned (Pmat) must be of type MATIS. 286728509bceSStefano Zampini 28680f202f7eSStefano Zampini Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 286928509bceSStefano Zampini 287028509bceSStefano Zampini It also works with unsymmetric and indefinite problems. 287128509bceSStefano Zampini 2872b6fdb6dfSStefano 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. 2873b6fdb6dfSStefano Zampini 2874c7017625SStefano 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). 287528509bceSStefano Zampini 28760f202f7eSStefano 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() 287730368db7SStefano Zampini Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts. 287828509bceSStefano Zampini 28790f202f7eSStefano Zampini Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD. 288028509bceSStefano Zampini 28810f202f7eSStefano 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. 28820f202f7eSStefano Zampini User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat() 288328509bceSStefano Zampini 28840f202f7eSStefano Zampini The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object. 288528509bceSStefano Zampini 2886df4d28bfSStefano 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. 288728509bceSStefano Zampini 28880f202f7eSStefano 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. 28890f202f7eSStefano Zampini 2890d314f959SVaclav Hapla Options Database Keys (some of them, run with -help for a complete list): 28910f202f7eSStefano Zampini 2892a2b725a8SWilliam Gropp + -pc_bddc_use_vertices <true> - use or not vertices in primal space 28930f202f7eSStefano Zampini . -pc_bddc_use_edges <true> - use or not edges in primal space 28940f202f7eSStefano Zampini . -pc_bddc_use_faces <false> - use or not faces in primal space 28950f202f7eSStefano Zampini . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 28960f202f7eSStefano Zampini . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 28970f202f7eSStefano Zampini . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 28980f202f7eSStefano Zampini . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 289928509bceSStefano Zampini . -pc_bddc_levels <0> - maximum number of levels for multilevel 29000f202f7eSStefano 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) 29015459c157SBarry 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) 29020f202f7eSStefano Zampini . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 290371f2caa7Sprj- . -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) 2904bd2a564bSStefano 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) 290528509bceSStefano Zampini - -pc_bddc_check_level <0> - set verbosity level of debugging output 290628509bceSStefano Zampini 290728509bceSStefano Zampini Options for Dirichlet, Neumann or coarse solver can be set with 290828509bceSStefano Zampini .vb 290928509bceSStefano Zampini -pc_bddc_dirichlet_ 291028509bceSStefano Zampini -pc_bddc_neumann_ 291128509bceSStefano Zampini -pc_bddc_coarse_ 291228509bceSStefano Zampini .ve 2913f9ff08acSPierre Jolivet e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU. 291428509bceSStefano Zampini 29150f202f7eSStefano Zampini When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as 291628509bceSStefano Zampini .vb 2917312be037SStefano Zampini -pc_bddc_dirichlet_lN_ 2918312be037SStefano Zampini -pc_bddc_neumann_lN_ 2919312be037SStefano Zampini -pc_bddc_coarse_lN_ 292028509bceSStefano Zampini .ve 29210f202f7eSStefano Zampini Note that level number ranges from the finest (0) to the coarsest (N). 29220f202f7eSStefano 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. 29230f202f7eSStefano Zampini .vb 29240f202f7eSStefano Zampini -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 29250f202f7eSStefano Zampini .ve 29260f202f7eSStefano 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 2927da1bb401SStefano Zampini 2928be4a8d98Sprj- References: 2929606c0280SSatish Balay + * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007 2930606c0280SSatish 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 2931606c0280SSatish Balay . * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008 2932606c0280SSatish 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 2933be4a8d98Sprj- 2934da1bb401SStefano Zampini Level: intermediate 2935da1bb401SStefano Zampini 2936e94cfbe0SPatrick Sanan Developer Notes: 2937da1bb401SStefano Zampini 2938da1bb401SStefano Zampini Contributed by Stefano Zampini 2939da1bb401SStefano Zampini 2940da1bb401SStefano Zampini .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 2941da1bb401SStefano Zampini M*/ 2942b2573a8aSBarry Smith 29438cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 2944da1bb401SStefano Zampini { 2945da1bb401SStefano Zampini PC_BDDC *pcbddc; 2946da1bb401SStefano Zampini 2947da1bb401SStefano Zampini PetscFunctionBegin; 29489566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&pcbddc)); 29493ec1f749SStefano Zampini pc->data = pcbddc; 2950da1bb401SStefano Zampini 2951da1bb401SStefano Zampini /* create PCIS data structure */ 29529566063dSJacob Faibussowitsch PetscCall(PCISCreate(pc)); 2953da1bb401SStefano Zampini 29549326c5c6Sstefano_zampini /* create local graph structure */ 29559566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph)); 29569326c5c6Sstefano_zampini 29579326c5c6Sstefano_zampini /* BDDC nonzero defaults */ 29586d9e27e4SStefano Zampini pcbddc->use_nnsp = PETSC_TRUE; 295908a5cf49SStefano Zampini pcbddc->use_local_adj = PETSC_TRUE; 296047d04d0dSStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 296147d04d0dSStefano Zampini pcbddc->use_edges = PETSC_TRUE; 29623301b35fSStefano Zampini pcbddc->symmetric_primal = PETSC_TRUE; 296314f95afaSStefano Zampini pcbddc->vertex_size = 1; 2964c703fcc7SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 296568457ee5SStefano Zampini pcbddc->coarse_size = -1; 296685c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 296747d04d0dSStefano Zampini pcbddc->coarsening_ratio = 8; 296857de7509SStefano Zampini pcbddc->coarse_eqs_per_proc = 1; 296927b6a85dSStefano Zampini pcbddc->benign_compute_correction = PETSC_TRUE; 29701e0482f5SStefano Zampini pcbddc->nedfield = -1; 29711e0482f5SStefano Zampini pcbddc->nedglobal = PETSC_TRUE; 2972be12c134Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 2973b96c3477SStefano Zampini pcbddc->sub_schurs_layers = -1; 2974bd2a564bSStefano Zampini pcbddc->adaptive_threshold[0] = 0.0; 2975bd2a564bSStefano Zampini pcbddc->adaptive_threshold[1] = 0.0; 2976b7eb3628SStefano Zampini 2977da1bb401SStefano Zampini /* function pointers */ 2978da1bb401SStefano Zampini pc->ops->apply = PCApply_BDDC; 297993bd9ae7SStefano Zampini pc->ops->applytranspose = PCApplyTranspose_BDDC; 2980da1bb401SStefano Zampini pc->ops->setup = PCSetUp_BDDC; 2981da1bb401SStefano Zampini pc->ops->destroy = PCDestroy_BDDC; 2982da1bb401SStefano Zampini pc->ops->setfromoptions = PCSetFromOptions_BDDC; 29836b78500eSPatrick Sanan pc->ops->view = PCView_BDDC; 29840a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 29850a545947SLisandro Dalcin pc->ops->applysymmetricleft = NULL; 29860a545947SLisandro Dalcin pc->ops->applysymmetricright = NULL; 2987534831adSStefano Zampini pc->ops->presolve = PCPreSolve_BDDC; 2988534831adSStefano Zampini pc->ops->postsolve = PCPostSolve_BDDC; 29899326c5c6Sstefano_zampini pc->ops->reset = PCReset_BDDC; 2990da1bb401SStefano Zampini 2991da1bb401SStefano Zampini /* composing function */ 29929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC)); 29939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC)); 29949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC)); 29959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC)); 29969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC)); 29979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC)); 29989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC)); 29999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC)); 30009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC)); 30019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC)); 30029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC)); 30039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC)); 30049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC)); 30059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC)); 30069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC)); 30079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC)); 30089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC)); 30099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC)); 30109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC)); 30119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC)); 30129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC)); 30139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC)); 30149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC)); 30159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC)); 30169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC)); 30179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC)); 30189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC)); 3019da1bb401SStefano Zampini PetscFunctionReturn(0); 3020da1bb401SStefano Zampini } 302143371fb9SStefano Zampini 302243371fb9SStefano Zampini /*@C 302343371fb9SStefano Zampini PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called 30248a690491SBarry Smith from PCInitializePackage(). 302543371fb9SStefano Zampini 302643371fb9SStefano Zampini Level: developer 302743371fb9SStefano Zampini 302843371fb9SStefano Zampini .seealso: PetscInitialize() 302943371fb9SStefano Zampini @*/ 303043371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void) 303143371fb9SStefano Zampini { 303243371fb9SStefano Zampini int i; 303343371fb9SStefano Zampini 303443371fb9SStefano Zampini PetscFunctionBegin; 303543371fb9SStefano Zampini if (PCBDDCPackageInitialized) PetscFunctionReturn(0); 303643371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_TRUE; 30379566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage)); 303843371fb9SStefano Zampini 303943371fb9SStefano Zampini /* general events */ 30409566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0])); 30419566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0])); 30429566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0])); 30439566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0])); 30449566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0])); 30459566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0])); 30469566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0])); 30479566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0])); 30489566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0])); 30499566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0])); 30509566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0])); 30519566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0])); 30529566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1])); 30539566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2])); 305443371fb9SStefano Zampini for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) { 305543371fb9SStefano Zampini char ename[32]; 305643371fb9SStefano Zampini 30579566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i)); 30589566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i])); 30599566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i)); 30609566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i])); 30619566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i)); 30629566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i])); 30639566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i)); 30649566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i])); 30659566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i)); 30669566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i])); 30679566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i)); 30689566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i])); 30699566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i)); 30709566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i])); 30719566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i)); 30729566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i])); 30739566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i)); 30749566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i])); 30759566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i)); 30769566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i])); 30779566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i)); 30789566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i])); 30799566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i)); 30809566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0])); 30819566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i)); 30829566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1])); 30839566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i)); 30849566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2])); 308543371fb9SStefano Zampini } 308643371fb9SStefano Zampini PetscFunctionReturn(0); 308743371fb9SStefano Zampini } 308843371fb9SStefano Zampini 308943371fb9SStefano Zampini /*@C 309043371fb9SStefano Zampini PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is 309143371fb9SStefano Zampini called from PetscFinalize() automatically. 309243371fb9SStefano Zampini 309343371fb9SStefano Zampini Level: developer 309443371fb9SStefano Zampini 309543371fb9SStefano Zampini .seealso: PetscFinalize() 309643371fb9SStefano Zampini @*/ 309743371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void) 309843371fb9SStefano Zampini { 309943371fb9SStefano Zampini PetscFunctionBegin; 310043371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_FALSE; 310143371fb9SStefano Zampini PetscFunctionReturn(0); 310243371fb9SStefano Zampini } 3103