1 /* TODOLIST 2 3 Solvers 4 - Add support for cholesky for coarse solver (similar to local solvers) 5 - Propagate ksp prefixes for solvers to mat objects? 6 7 User interface 8 - ** DM attached to pc? 9 10 Debugging output 11 - * Better management of verbosity levels of debugging output 12 13 Extra 14 - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)? 15 - BDDC with MG framework? 16 17 MATIS related operations contained in BDDC code 18 - Provide general case for subassembling 19 20 */ 21 22 #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 23 #include <../src/ksp/pc/impls/bddc/bddcprivate.h> 24 #include <petscblaslapack.h> 25 26 static PetscBool PCBDDCPackageInitialized = PETSC_FALSE; 27 28 static PetscBool cited = PETSC_FALSE; 29 static const char citation[] = 30 "@article{ZampiniPCBDDC,\n" 31 "author = {Stefano Zampini},\n" 32 "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n" 33 "journal = {SIAM Journal on Scientific Computing},\n" 34 "volume = {38},\n" 35 "number = {5},\n" 36 "pages = {S282-S306},\n" 37 "year = {2016},\n" 38 "doi = {10.1137/15M1025785},\n" 39 "URL = {http://dx.doi.org/10.1137/15M1025785},\n" 40 "eprint = {http://dx.doi.org/10.1137/15M1025785}\n" 41 "}\n"; 42 43 PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS]; 44 PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS]; 45 PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS]; 46 PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS]; 47 PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS]; 48 PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS]; 49 PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS]; 50 PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS]; 51 PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS]; 52 PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS]; 53 PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS]; 54 PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3]; 55 56 const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET","LUMP","PCBDDCInterfaceExtType","PC_BDDC_INTERFACE_EXT_",NULL}; 57 58 PetscErrorCode PCApply_BDDC(PC,Vec,Vec); 59 60 PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc) 61 { 62 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 63 PetscInt nt,i; 64 PetscErrorCode ierr; 65 66 PetscFunctionBegin; 67 ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr); 68 /* Verbose debugging */ 69 ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr); 70 /* Approximate solvers */ 71 ierr = 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);CHKERRQ(ierr); 72 if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) { 73 ierr = PetscOptionsBool("-pc_bddc_dirichlet_approximate","Inform PCBDDC that we are using approximate Dirichlet solvers","none",pcbddc->NullSpace_corr[0],&pcbddc->NullSpace_corr[0],NULL);CHKERRQ(ierr); 74 ierr = PetscOptionsBool("-pc_bddc_dirichlet_approximate_scale","Inform PCBDDC that we need to scale the Dirichlet solve","none",pcbddc->NullSpace_corr[1],&pcbddc->NullSpace_corr[1],NULL);CHKERRQ(ierr); 75 } else { 76 /* This flag is needed/implied by lumping */ 77 pcbddc->switch_static = PETSC_TRUE; 78 } 79 ierr = PetscOptionsBool("-pc_bddc_neumann_approximate","Inform PCBDDC that we are using approximate Neumann solvers","none",pcbddc->NullSpace_corr[2],&pcbddc->NullSpace_corr[2],NULL);CHKERRQ(ierr); 80 ierr = PetscOptionsBool("-pc_bddc_neumann_approximate_scale","Inform PCBDDC that we need to scale the Neumann solve","none",pcbddc->NullSpace_corr[3],&pcbddc->NullSpace_corr[3],NULL);CHKERRQ(ierr); 81 /* Primal space customization */ 82 ierr = PetscOptionsBool("-pc_bddc_use_local_mat_graph","Use or not adjacency graph of local mat for interface analysis","none",pcbddc->use_local_adj,&pcbddc->use_local_adj,NULL);CHKERRQ(ierr); 83 ierr = PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL);CHKERRQ(ierr); 84 ierr = PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL);CHKERRQ(ierr); 85 ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr); 86 ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr); 87 ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr); 88 ierr = PetscOptionsInt("-pc_bddc_vertex_size","Connected components smaller or equal to vertex size will be considered as primal vertices","none",pcbddc->vertex_size,&pcbddc->vertex_size,NULL);CHKERRQ(ierr); 89 ierr = PetscOptionsBool("-pc_bddc_use_nnsp","Use near null space attached to the matrix to compute constraints","none",pcbddc->use_nnsp,&pcbddc->use_nnsp,NULL);CHKERRQ(ierr); 90 ierr = 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);CHKERRQ(ierr); 91 ierr = PetscOptionsBool("-pc_bddc_use_qr_single","Use QR factorization for single constraints on cc (QR is always used when multiple constraints are present)","none",pcbddc->use_qr_single,&pcbddc->use_qr_single,NULL);CHKERRQ(ierr); 92 /* Change of basis */ 93 ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use or not internal change of basis on local edge nodes","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr); 94 ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use or not internal change of basis on local face nodes","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr); 95 if (!pcbddc->use_change_of_basis) { 96 pcbddc->use_change_on_faces = PETSC_FALSE; 97 } 98 /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 99 ierr = PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL);CHKERRQ(ierr); 100 ierr = 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);CHKERRQ(ierr); 101 i = pcbddc->coarsening_ratio; 102 ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL);CHKERRQ(ierr); 103 ierr = PCBDDCSetCoarseningRatio(pc,i);CHKERRQ(ierr); 104 i = pcbddc->max_levels; 105 ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL);CHKERRQ(ierr); 106 ierr = PCBDDCSetLevels(pc,i);CHKERRQ(ierr); 107 ierr = 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);CHKERRQ(ierr); 108 ierr = PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL);CHKERRQ(ierr); 109 ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr); 110 ierr = PetscOptionsBool("-pc_bddc_schur_rebuild","Whether or not the interface graph for Schur principal minors has to be rebuilt (i.e. define the interface without any adjacency)","none",pcbddc->sub_schurs_rebuild,&pcbddc->sub_schurs_rebuild,NULL);CHKERRQ(ierr); 111 ierr = PetscOptionsInt("-pc_bddc_schur_layers","Number of dofs' layers for the computation of principal minors (i.e. -1 uses all dofs)","none",pcbddc->sub_schurs_layers,&pcbddc->sub_schurs_layers,NULL);CHKERRQ(ierr); 112 ierr = PetscOptionsBool("-pc_bddc_schur_use_useradj","Whether or not the CSR graph specified by the user should be used for computing successive layers (default is to use adj of local mat)","none",pcbddc->sub_schurs_use_useradj,&pcbddc->sub_schurs_use_useradj,NULL);CHKERRQ(ierr); 113 ierr = PetscOptionsBool("-pc_bddc_schur_exact","Whether or not to use the exact Schur complement instead of the reduced one (which excludes size 1 cc)","none",pcbddc->sub_schurs_exact_schur,&pcbddc->sub_schurs_exact_schur,NULL);CHKERRQ(ierr); 114 ierr = PetscOptionsBool("-pc_bddc_deluxe_zerorows","Zero rows and columns of deluxe operators associated with primal dofs","none",pcbddc->deluxe_zerorows,&pcbddc->deluxe_zerorows,NULL);CHKERRQ(ierr); 115 ierr = PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL);CHKERRQ(ierr); 116 ierr = PetscOptionsBool("-pc_bddc_adaptive_userdefined","Use user-defined constraints (should be attached via MatSetNearNullSpace to pmat) in addition to those adaptively generated","none",pcbddc->adaptive_userdefined,&pcbddc->adaptive_userdefined,NULL);CHKERRQ(ierr); 117 nt = 2; 118 ierr = PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL);CHKERRQ(ierr); 119 if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0]; 120 ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr); 121 ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr); 122 ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr); 123 ierr = PetscOptionsInt("-pc_bddc_coarse_adj","Number of processors where to map the coarse adjacency list","none",pcbddc->coarse_adj_red,&pcbddc->coarse_adj_red,NULL);CHKERRQ(ierr); 124 ierr = PetscOptionsBool("-pc_bddc_benign_trick","Apply the benign subspace trick to saddle point problems with discontinuous pressures","none",pcbddc->benign_saddle_point,&pcbddc->benign_saddle_point,NULL);CHKERRQ(ierr); 125 ierr = PetscOptionsBool("-pc_bddc_benign_change","Compute the pressure change of basis explicitly","none",pcbddc->benign_change_explicit,&pcbddc->benign_change_explicit,NULL);CHKERRQ(ierr); 126 ierr = PetscOptionsBool("-pc_bddc_benign_compute_correction","Compute the benign correction during PreSolve","none",pcbddc->benign_compute_correction,&pcbddc->benign_compute_correction,NULL);CHKERRQ(ierr); 127 ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr); 128 ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr); 129 ierr = 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);CHKERRQ(ierr); 130 ierr = PetscOptionsBool("-pc_bddc_eliminate_dirichlet","Whether or not we want to eliminate dirichlet dofs during presolve","none",pcbddc->eliminate_dirdofs,&pcbddc->eliminate_dirdofs,NULL);CHKERRQ(ierr); 131 ierr = PetscOptionsTail();CHKERRQ(ierr); 132 PetscFunctionReturn(0); 133 } 134 135 static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer) 136 { 137 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 138 PC_IS *pcis = (PC_IS*)pc->data; 139 PetscErrorCode ierr; 140 PetscBool isascii; 141 PetscSubcomm subcomm; 142 PetscViewer subviewer; 143 144 PetscFunctionBegin; 145 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 146 /* ASCII viewer */ 147 if (isascii) { 148 PetscMPIInt color,rank,size; 149 PetscInt64 loc[7],gsum[6],gmax[6],gmin[6],totbenign; 150 PetscScalar interface_size; 151 PetscReal ratio1=0.,ratio2=0.; 152 Vec counter; 153 154 if (!pc->setupcalled) { 155 ierr = PetscViewerASCIIPrintf(viewer," Partial information available: preconditioner has not been setup yet\n");CHKERRQ(ierr); 156 } 157 ierr = PetscViewerASCIIPrintf(viewer," Use verbose output: %D\n",pcbddc->dbg_flag);CHKERRQ(ierr); 158 ierr = PetscViewerASCIIPrintf(viewer," Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr); 159 ierr = PetscViewerASCIIPrintf(viewer," Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr); 160 if (pcbddc->mat_graph->twodim) { 161 ierr = PetscViewerASCIIPrintf(viewer," Connectivity graph topological dimension: 2\n");CHKERRQ(ierr); 162 } else { 163 ierr = PetscViewerASCIIPrintf(viewer," Connectivity graph topological dimension: 3\n");CHKERRQ(ierr); 164 } 165 if (pcbddc->graphmaxcount != PETSC_MAX_INT) { 166 ierr = PetscViewerASCIIPrintf(viewer," Graph max count: %D\n",pcbddc->graphmaxcount);CHKERRQ(ierr); 167 } 168 ierr = PetscViewerASCIIPrintf(viewer," Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr); 169 ierr = PetscViewerASCIIPrintf(viewer," Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr); 170 ierr = PetscViewerASCIIPrintf(viewer," Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr); 171 ierr = PetscViewerASCIIPrintf(viewer," Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr); 172 ierr = PetscViewerASCIIPrintf(viewer," Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr); 173 ierr = PetscViewerASCIIPrintf(viewer," Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr); 174 ierr = PetscViewerASCIIPrintf(viewer," Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr); 175 ierr = PetscViewerASCIIPrintf(viewer," User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr); 176 ierr = PetscViewerASCIIPrintf(viewer," Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr); 177 ierr = PetscViewerASCIIPrintf(viewer," Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr); 178 ierr = PetscViewerASCIIPrintf(viewer," Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr); 179 ierr = PetscViewerASCIIPrintf(viewer," Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr); 180 ierr = PetscViewerASCIIPrintf(viewer," Interface extension: %s\n",PCBDDCInterfaceExtTypes[pcbddc->interface_extension]);CHKERRQ(ierr); 181 ierr = PetscViewerASCIIPrintf(viewer," Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr); 182 ierr = PetscViewerASCIIPrintf(viewer," Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr); 183 ierr = PetscViewerASCIIPrintf(viewer," Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr); 184 ierr = PetscViewerASCIIPrintf(viewer," Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr); 185 ierr = PetscViewerASCIIPrintf(viewer," Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr); 186 ierr = PetscViewerASCIIPrintf(viewer," Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr); 187 ierr = PetscViewerASCIIPrintf(viewer," Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr); 188 ierr = PetscViewerASCIIPrintf(viewer," Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr); 189 ierr = PetscViewerASCIIPrintf(viewer," Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr); 190 if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) { 191 ierr = 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]);CHKERRQ(ierr); 192 } else { 193 ierr = PetscViewerASCIIPrintf(viewer," Adaptive constraint selection threshold (active %d, userdefined %d): %g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0]);CHKERRQ(ierr); 194 } 195 ierr = PetscViewerASCIIPrintf(viewer," Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr); 196 ierr = PetscViewerASCIIPrintf(viewer," Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr); 197 ierr = PetscViewerASCIIPrintf(viewer," Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr); 198 ierr = PetscViewerASCIIPrintf(viewer," Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr); 199 ierr = PetscViewerASCIIPrintf(viewer," Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr); 200 ierr = PetscViewerASCIIPrintf(viewer," Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr); 201 ierr = PetscViewerASCIIPrintf(viewer," Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr); 202 ierr = PetscViewerASCIIPrintf(viewer," Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr); 203 ierr = PetscViewerASCIIPrintf(viewer," Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr); 204 ierr = PetscViewerASCIIPrintf(viewer," Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr); 205 if (!pc->setupcalled) PetscFunctionReturn(0); 206 207 /* compute interface size */ 208 ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr); 209 ierr = MatCreateVecs(pc->pmat,&counter,NULL);CHKERRQ(ierr); 210 ierr = VecSet(counter,0.0);CHKERRQ(ierr); 211 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 212 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 213 ierr = VecSum(counter,&interface_size);CHKERRQ(ierr); 214 ierr = VecDestroy(&counter);CHKERRQ(ierr); 215 216 /* compute some statistics on the domain decomposition */ 217 gsum[0] = 1; 218 gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0; 219 loc[0] = !!pcis->n; 220 loc[1] = pcis->n - pcis->n_B; 221 loc[2] = pcis->n_B; 222 loc[3] = pcbddc->local_primal_size; 223 loc[4] = pcis->n; 224 loc[5] = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0); 225 loc[6] = pcbddc->benign_n; 226 ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr); 227 if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1; 228 ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr); 229 if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT; 230 ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr); 231 ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr); 232 if (pcbddc->coarse_size) { 233 ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size); 234 ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size; 235 } 236 ierr = PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr); 237 ierr = PetscViewerASCIIPrintf(viewer," Global dofs sizes: all %D interface %D coarse %D\n",pc->pmat->rmap->N,(PetscInt)PetscRealPart(interface_size),pcbddc->coarse_size);CHKERRQ(ierr); 238 ierr = PetscViewerASCIIPrintf(viewer," Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr); 239 ierr = PetscViewerASCIIPrintf(viewer," Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr); 240 ierr = PetscViewerASCIIPrintf(viewer," Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr); 241 if (pcbddc->benign_have_null) { 242 ierr = PetscViewerASCIIPrintf(viewer," Benign subs : %D\n",(PetscInt)totbenign);CHKERRQ(ierr); 243 } 244 ierr = PetscViewerASCIIPrintf(viewer," Dofs type :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr); 245 ierr = PetscViewerASCIIPrintf(viewer," Interior dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]));CHKERRQ(ierr); 246 ierr = PetscViewerASCIIPrintf(viewer," Interface dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[2],(PetscInt)gmax[2],(PetscInt)(gsum[2]/gsum[0]));CHKERRQ(ierr); 247 ierr = PetscViewerASCIIPrintf(viewer," Primal dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[3],(PetscInt)gmax[3],(PetscInt)(gsum[3]/gsum[0]));CHKERRQ(ierr); 248 ierr = PetscViewerASCIIPrintf(viewer," Local dofs :\t%D\t%D\t%D\n",(PetscInt)gmin[4],(PetscInt)gmax[4],(PetscInt)(gsum[4]/gsum[0]));CHKERRQ(ierr); 249 ierr = PetscViewerASCIIPrintf(viewer," Local subs :\t%D\t%D\n" ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr); 250 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 251 252 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRMPI(ierr); 253 254 /* local solvers */ 255 ierr = PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr); 256 if (!rank) { 257 ierr = PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n");CHKERRQ(ierr); 258 ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr); 259 ierr = KSPView(pcbddc->ksp_D,subviewer);CHKERRQ(ierr); 260 ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr); 261 ierr = PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n");CHKERRQ(ierr); 262 ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr); 263 ierr = KSPView(pcbddc->ksp_R,subviewer);CHKERRQ(ierr); 264 ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr); 265 ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr); 266 } 267 ierr = PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr); 268 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 269 270 /* the coarse problem can be handled by a different communicator */ 271 if (pcbddc->coarse_ksp) color = 1; 272 else color = 0; 273 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr); 274 ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr); 275 ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr); 276 ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr); 277 ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr); 278 if (color == 1) { 279 ierr = PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n");CHKERRQ(ierr); 280 ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr); 281 ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr); 282 ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr); 283 ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr); 284 } 285 ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr); 286 ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr); 287 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 288 } 289 PetscFunctionReturn(0); 290 } 291 292 static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 293 { 294 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 295 PetscErrorCode ierr; 296 297 PetscFunctionBegin; 298 ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr); 299 ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr); 300 pcbddc->discretegradient = G; 301 pcbddc->nedorder = order > 0 ? order : -order; 302 pcbddc->nedfield = field; 303 pcbddc->nedglobal = global; 304 pcbddc->conforming = conforming; 305 PetscFunctionReturn(0); 306 } 307 308 /*@ 309 PCBDDCSetDiscreteGradient - Sets the discrete gradient 310 311 Collective on PC 312 313 Input Parameters: 314 + pc - the preconditioning context 315 . G - the discrete gradient matrix (should be in AIJ format) 316 . order - the order of the Nedelec space (1 for the lowest order) 317 . field - the field id of the Nedelec dofs (not used if the fields have not been specified) 318 . global - the type of global ordering for the rows of G 319 - conforming - whether the mesh is conforming or not 320 321 Level: advanced 322 323 Notes: 324 The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry. 325 For variable order spaces, the order should be set to zero. 326 If global is true, the rows of G should be given in global ordering for the whole dofs; 327 if false, the ordering should be global for the Nedelec field. 328 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 329 and geid the one for the Nedelec field. 330 331 .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal() 332 @*/ 333 PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 334 { 335 PetscErrorCode ierr; 336 337 PetscFunctionBegin; 338 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 339 PetscValidHeaderSpecific(G,MAT_CLASSID,2); 340 PetscValidLogicalCollectiveInt(pc,order,3); 341 PetscValidLogicalCollectiveInt(pc,field,4); 342 PetscValidLogicalCollectiveBool(pc,global,5); 343 PetscValidLogicalCollectiveBool(pc,conforming,6); 344 PetscCheckSameComm(pc,1,G,2); 345 ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr); 346 PetscFunctionReturn(0); 347 } 348 349 static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 350 { 351 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 352 PetscErrorCode ierr; 353 354 PetscFunctionBegin; 355 ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr); 356 ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr); 357 pcbddc->divudotp = divudotp; 358 pcbddc->divudotp_trans = trans; 359 pcbddc->compute_nonetflux = PETSC_TRUE; 360 if (vl2l) { 361 ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr); 362 ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr); 363 pcbddc->divudotp_vl2l = vl2l; 364 } 365 PetscFunctionReturn(0); 366 } 367 368 /*@ 369 PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx 370 371 Collective on PC 372 373 Input Parameters: 374 + pc - the preconditioning context 375 . divudotp - the matrix (must be of type MATIS) 376 . trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space. 377 - 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 378 379 Level: advanced 380 381 Notes: 382 This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries 383 If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix 384 385 .seealso: PCBDDC 386 @*/ 387 PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 388 { 389 PetscBool ismatis; 390 PetscErrorCode ierr; 391 392 PetscFunctionBegin; 393 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 394 PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2); 395 PetscCheckSameComm(pc,1,divudotp,2); 396 PetscValidLogicalCollectiveBool(pc,trans,3); 397 if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4); 398 ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr); 399 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS"); 400 ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr); 401 PetscFunctionReturn(0); 402 } 403 404 static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior) 405 { 406 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 407 PetscErrorCode ierr; 408 409 PetscFunctionBegin; 410 ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr); 411 ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr); 412 pcbddc->user_ChangeOfBasisMatrix = change; 413 pcbddc->change_interior = interior; 414 PetscFunctionReturn(0); 415 } 416 /*@ 417 PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 418 419 Collective on PC 420 421 Input Parameters: 422 + pc - the preconditioning context 423 . change - the change of basis matrix 424 - interior - whether or not the change of basis modifies interior dofs 425 426 Level: intermediate 427 428 Notes: 429 430 .seealso: PCBDDC 431 @*/ 432 PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior) 433 { 434 PetscErrorCode ierr; 435 436 PetscFunctionBegin; 437 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 438 PetscValidHeaderSpecific(change,MAT_CLASSID,2); 439 PetscCheckSameComm(pc,1,change,2); 440 if (pc->mat) { 441 PetscInt rows_c,cols_c,rows,cols; 442 ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr); 443 ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr); 444 if (rows_c != rows) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %D != %D",rows_c,rows); 445 if (cols_c != cols) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %D != %D",cols_c,cols); 446 ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr); 447 ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr); 448 if (rows_c != rows) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %D != %D",rows_c,rows); 449 if (cols_c != cols) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %D != %D",cols_c,cols); 450 } 451 ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr); 452 PetscFunctionReturn(0); 453 } 454 455 static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices) 456 { 457 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 458 PetscBool isequal = PETSC_FALSE; 459 PetscErrorCode ierr; 460 461 PetscFunctionBegin; 462 ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr); 463 if (pcbddc->user_primal_vertices) { 464 ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr); 465 } 466 ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr); 467 ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr); 468 pcbddc->user_primal_vertices = PrimalVertices; 469 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 470 PetscFunctionReturn(0); 471 } 472 473 /*@ 474 PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC 475 476 Collective 477 478 Input Parameters: 479 + pc - the preconditioning context 480 - PrimalVertices - index set of primal vertices in global numbering (can be empty) 481 482 Level: intermediate 483 484 Notes: 485 Any process can list any global node 486 487 .seealso: PCBDDC, PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS() 488 @*/ 489 PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices) 490 { 491 PetscErrorCode ierr; 492 493 PetscFunctionBegin; 494 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 495 PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 496 PetscCheckSameComm(pc,1,PrimalVertices,2); 497 ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr); 498 PetscFunctionReturn(0); 499 } 500 501 static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is) 502 { 503 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 504 505 PetscFunctionBegin; 506 *is = pcbddc->user_primal_vertices; 507 PetscFunctionReturn(0); 508 } 509 510 /*@ 511 PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS() 512 513 Collective 514 515 Input Parameters: 516 . pc - the preconditioning context 517 518 Output Parameters: 519 . is - index set of primal vertices in global numbering (NULL if not set) 520 521 Level: intermediate 522 523 Notes: 524 525 .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS() 526 @*/ 527 PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) 528 { 529 PetscErrorCode ierr; 530 531 PetscFunctionBegin; 532 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 533 PetscValidPointer(is,2); 534 ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr); 535 PetscFunctionReturn(0); 536 } 537 538 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 539 { 540 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 541 PetscBool isequal = PETSC_FALSE; 542 PetscErrorCode ierr; 543 544 PetscFunctionBegin; 545 ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr); 546 if (pcbddc->user_primal_vertices_local) { 547 ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr); 548 } 549 ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr); 550 ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr); 551 pcbddc->user_primal_vertices_local = PrimalVertices; 552 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 553 PetscFunctionReturn(0); 554 } 555 556 /*@ 557 PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC 558 559 Collective 560 561 Input Parameters: 562 + pc - the preconditioning context 563 - PrimalVertices - index set of primal vertices in local numbering (can be empty) 564 565 Level: intermediate 566 567 Notes: 568 569 .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCGetPrimalVerticesLocalIS() 570 @*/ 571 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 572 { 573 PetscErrorCode ierr; 574 575 PetscFunctionBegin; 576 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 577 PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 578 PetscCheckSameComm(pc,1,PrimalVertices,2); 579 ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr); 580 PetscFunctionReturn(0); 581 } 582 583 static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) 584 { 585 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 586 587 PetscFunctionBegin; 588 *is = pcbddc->user_primal_vertices_local; 589 PetscFunctionReturn(0); 590 } 591 592 /*@ 593 PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS() 594 595 Collective 596 597 Input Parameters: 598 . pc - the preconditioning context 599 600 Output Parameters: 601 . is - index set of primal vertices in local numbering (NULL if not set) 602 603 Level: intermediate 604 605 Notes: 606 607 .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS() 608 @*/ 609 PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) 610 { 611 PetscErrorCode ierr; 612 613 PetscFunctionBegin; 614 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 615 PetscValidPointer(is,2); 616 ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr); 617 PetscFunctionReturn(0); 618 } 619 620 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k) 621 { 622 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 623 624 PetscFunctionBegin; 625 pcbddc->coarsening_ratio = k; 626 PetscFunctionReturn(0); 627 } 628 629 /*@ 630 PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel 631 632 Logically collective on PC 633 634 Input Parameters: 635 + pc - the preconditioning context 636 - k - coarsening ratio (H/h at the coarser level) 637 638 Options Database Keys: 639 . -pc_bddc_coarsening_ratio 640 641 Level: intermediate 642 643 Notes: 644 Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level 645 646 .seealso: PCBDDC, PCBDDCSetLevels() 647 @*/ 648 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k) 649 { 650 PetscErrorCode ierr; 651 652 PetscFunctionBegin; 653 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 654 PetscValidLogicalCollectiveInt(pc,k,2); 655 ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr); 656 PetscFunctionReturn(0); 657 } 658 659 /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 660 static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg) 661 { 662 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 663 664 PetscFunctionBegin; 665 pcbddc->use_exact_dirichlet_trick = flg; 666 PetscFunctionReturn(0); 667 } 668 669 PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg) 670 { 671 PetscErrorCode ierr; 672 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 675 PetscValidLogicalCollectiveBool(pc,flg,2); 676 ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr); 677 PetscFunctionReturn(0); 678 } 679 680 static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level) 681 { 682 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 683 684 PetscFunctionBegin; 685 pcbddc->current_level = level; 686 PetscFunctionReturn(0); 687 } 688 689 PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level) 690 { 691 PetscErrorCode ierr; 692 693 PetscFunctionBegin; 694 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 695 PetscValidLogicalCollectiveInt(pc,level,2); 696 ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr); 697 PetscFunctionReturn(0); 698 } 699 700 static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels) 701 { 702 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 703 704 PetscFunctionBegin; 705 if (levels > PETSC_PCBDDC_MAXLEVELS-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of additional levels for BDDC is %d",PETSC_PCBDDC_MAXLEVELS-1); 706 pcbddc->max_levels = levels; 707 PetscFunctionReturn(0); 708 } 709 710 /*@ 711 PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC 712 713 Logically collective on PC 714 715 Input Parameters: 716 + pc - the preconditioning context 717 - levels - the maximum number of levels 718 719 Options Database Keys: 720 . -pc_bddc_levels 721 722 Level: intermediate 723 724 Notes: 725 The default value is 0, that gives the classical two-levels BDDC 726 727 .seealso: PCBDDC, PCBDDCSetCoarseningRatio() 728 @*/ 729 PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels) 730 { 731 PetscErrorCode ierr; 732 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 735 PetscValidLogicalCollectiveInt(pc,levels,2); 736 ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr); 737 PetscFunctionReturn(0); 738 } 739 740 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries) 741 { 742 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 743 PetscBool isequal = PETSC_FALSE; 744 PetscErrorCode ierr; 745 746 PetscFunctionBegin; 747 ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr); 748 if (pcbddc->DirichletBoundaries) { 749 ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr); 750 } 751 /* last user setting takes precendence -> destroy any other customization */ 752 ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr); 753 ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr); 754 pcbddc->DirichletBoundaries = DirichletBoundaries; 755 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 756 PetscFunctionReturn(0); 757 } 758 759 /*@ 760 PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem. 761 762 Collective 763 764 Input Parameters: 765 + pc - the preconditioning context 766 - DirichletBoundaries - parallel IS defining the Dirichlet boundaries 767 768 Level: intermediate 769 770 Notes: 771 Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node 772 773 .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns() 774 @*/ 775 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries) 776 { 777 PetscErrorCode ierr; 778 779 PetscFunctionBegin; 780 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 781 PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 782 PetscCheckSameComm(pc,1,DirichletBoundaries,2); 783 ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr); 784 PetscFunctionReturn(0); 785 } 786 787 static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries) 788 { 789 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 790 PetscBool isequal = PETSC_FALSE; 791 PetscErrorCode ierr; 792 793 PetscFunctionBegin; 794 ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr); 795 if (pcbddc->DirichletBoundariesLocal) { 796 ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr); 797 } 798 /* last user setting takes precendence -> destroy any other customization */ 799 ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr); 800 ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr); 801 pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 802 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 803 PetscFunctionReturn(0); 804 } 805 806 /*@ 807 PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering. 808 809 Collective 810 811 Input Parameters: 812 + pc - the preconditioning context 813 - DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering) 814 815 Level: intermediate 816 817 Notes: 818 819 .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns() 820 @*/ 821 PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries) 822 { 823 PetscErrorCode ierr; 824 825 PetscFunctionBegin; 826 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 827 PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 828 PetscCheckSameComm(pc,1,DirichletBoundaries,2); 829 ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr); 830 PetscFunctionReturn(0); 831 } 832 833 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries) 834 { 835 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 836 PetscBool isequal = PETSC_FALSE; 837 PetscErrorCode ierr; 838 839 PetscFunctionBegin; 840 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 841 if (pcbddc->NeumannBoundaries) { 842 ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr); 843 } 844 /* last user setting takes precendence -> destroy any other customization */ 845 ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr); 846 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 847 pcbddc->NeumannBoundaries = NeumannBoundaries; 848 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 849 PetscFunctionReturn(0); 850 } 851 852 /*@ 853 PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem. 854 855 Collective 856 857 Input Parameters: 858 + pc - the preconditioning context 859 - NeumannBoundaries - parallel IS defining the Neumann boundaries 860 861 Level: intermediate 862 863 Notes: 864 Any process can list any global node 865 866 .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal() 867 @*/ 868 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries) 869 { 870 PetscErrorCode ierr; 871 872 PetscFunctionBegin; 873 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 874 PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 875 PetscCheckSameComm(pc,1,NeumannBoundaries,2); 876 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 877 PetscFunctionReturn(0); 878 } 879 880 static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries) 881 { 882 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 883 PetscBool isequal = PETSC_FALSE; 884 PetscErrorCode ierr; 885 886 PetscFunctionBegin; 887 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 888 if (pcbddc->NeumannBoundariesLocal) { 889 ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr); 890 } 891 /* last user setting takes precendence -> destroy any other customization */ 892 ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr); 893 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 894 pcbddc->NeumannBoundariesLocal = NeumannBoundaries; 895 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 896 PetscFunctionReturn(0); 897 } 898 899 /*@ 900 PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering. 901 902 Collective 903 904 Input Parameters: 905 + pc - the preconditioning context 906 - NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering) 907 908 Level: intermediate 909 910 Notes: 911 912 .seealso: PCBDDC, PCBDDCSetNeumannBoundaries() 913 @*/ 914 PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries) 915 { 916 PetscErrorCode ierr; 917 918 PetscFunctionBegin; 919 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 920 PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 921 PetscCheckSameComm(pc,1,NeumannBoundaries,2); 922 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 923 PetscFunctionReturn(0); 924 } 925 926 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries) 927 { 928 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 929 930 PetscFunctionBegin; 931 *DirichletBoundaries = pcbddc->DirichletBoundaries; 932 PetscFunctionReturn(0); 933 } 934 935 /*@ 936 PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries 937 938 Collective 939 940 Input Parameters: 941 . pc - the preconditioning context 942 943 Output Parameters: 944 . DirichletBoundaries - index set defining the Dirichlet boundaries 945 946 Level: intermediate 947 948 Notes: 949 The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries 950 951 .seealso: PCBDDC 952 @*/ 953 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries) 954 { 955 PetscErrorCode ierr; 956 957 PetscFunctionBegin; 958 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 959 ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr); 960 PetscFunctionReturn(0); 961 } 962 963 static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries) 964 { 965 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 966 967 PetscFunctionBegin; 968 *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 969 PetscFunctionReturn(0); 970 } 971 972 /*@ 973 PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering) 974 975 Collective 976 977 Input Parameters: 978 . pc - the preconditioning context 979 980 Output Parameters: 981 . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 982 983 Level: intermediate 984 985 Notes: 986 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). 987 In the latter case, the IS will be available after PCSetUp. 988 989 .seealso: PCBDDC 990 @*/ 991 PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries) 992 { 993 PetscErrorCode ierr; 994 995 PetscFunctionBegin; 996 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 997 ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr); 998 PetscFunctionReturn(0); 999 } 1000 1001 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries) 1002 { 1003 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1004 1005 PetscFunctionBegin; 1006 *NeumannBoundaries = pcbddc->NeumannBoundaries; 1007 PetscFunctionReturn(0); 1008 } 1009 1010 /*@ 1011 PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries 1012 1013 Collective 1014 1015 Input Parameters: 1016 . pc - the preconditioning context 1017 1018 Output Parameters: 1019 . NeumannBoundaries - index set defining the Neumann boundaries 1020 1021 Level: intermediate 1022 1023 Notes: 1024 The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries 1025 1026 .seealso: PCBDDC 1027 @*/ 1028 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries) 1029 { 1030 PetscErrorCode ierr; 1031 1032 PetscFunctionBegin; 1033 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1034 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 1035 PetscFunctionReturn(0); 1036 } 1037 1038 static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries) 1039 { 1040 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1041 1042 PetscFunctionBegin; 1043 *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 1044 PetscFunctionReturn(0); 1045 } 1046 1047 /*@ 1048 PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering) 1049 1050 Collective 1051 1052 Input Parameters: 1053 . pc - the preconditioning context 1054 1055 Output Parameters: 1056 . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 1057 1058 Level: intermediate 1059 1060 Notes: 1061 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). 1062 In the latter case, the IS will be available after PCSetUp. 1063 1064 .seealso: PCBDDC 1065 @*/ 1066 PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries) 1067 { 1068 PetscErrorCode ierr; 1069 1070 PetscFunctionBegin; 1071 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1072 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 1073 PetscFunctionReturn(0); 1074 } 1075 1076 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 1077 { 1078 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1079 PCBDDCGraph mat_graph = pcbddc->mat_graph; 1080 PetscBool same_data = PETSC_FALSE; 1081 PetscErrorCode ierr; 1082 1083 PetscFunctionBegin; 1084 if (!nvtxs) { 1085 if (copymode == PETSC_OWN_POINTER) { 1086 ierr = PetscFree(xadj);CHKERRQ(ierr); 1087 ierr = PetscFree(adjncy);CHKERRQ(ierr); 1088 } 1089 ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr); 1090 PetscFunctionReturn(0); 1091 } 1092 if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */ 1093 if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE; 1094 if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) { 1095 ierr = PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data);CHKERRQ(ierr); 1096 if (same_data) { 1097 ierr = PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data);CHKERRQ(ierr); 1098 } 1099 } 1100 } 1101 if (!same_data) { 1102 /* free old CSR */ 1103 ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr); 1104 /* get CSR into graph structure */ 1105 if (copymode == PETSC_COPY_VALUES) { 1106 ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr); 1107 ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr); 1108 ierr = PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1);CHKERRQ(ierr); 1109 ierr = PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr); 1110 mat_graph->freecsr = PETSC_TRUE; 1111 } else if (copymode == PETSC_OWN_POINTER) { 1112 mat_graph->xadj = (PetscInt*)xadj; 1113 mat_graph->adjncy = (PetscInt*)adjncy; 1114 mat_graph->freecsr = PETSC_TRUE; 1115 } else if (copymode == PETSC_USE_POINTER) { 1116 mat_graph->xadj = (PetscInt*)xadj; 1117 mat_graph->adjncy = (PetscInt*)adjncy; 1118 mat_graph->freecsr = PETSC_FALSE; 1119 } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode); 1120 mat_graph->nvtxs_csr = nvtxs; 1121 pcbddc->recompute_topography = PETSC_TRUE; 1122 } 1123 PetscFunctionReturn(0); 1124 } 1125 1126 /*@ 1127 PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom. 1128 1129 Not collective 1130 1131 Input Parameters: 1132 + pc - the preconditioning context. 1133 . nvtxs - number of local vertices of the graph (i.e., the number of local dofs). 1134 . xadj, adjncy - the connectivity of the dofs in CSR format. 1135 - copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER. 1136 1137 Level: intermediate 1138 1139 Notes: 1140 A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative. 1141 1142 .seealso: PCBDDC,PetscCopyMode 1143 @*/ 1144 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 1145 { 1146 void (*f)(void) = NULL; 1147 PetscErrorCode ierr; 1148 1149 PetscFunctionBegin; 1150 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1151 if (nvtxs) { 1152 PetscValidIntPointer(xadj,3); 1153 if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4); 1154 } 1155 ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr); 1156 /* free arrays if PCBDDC is not the PC type */ 1157 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr); 1158 if (!f && copymode == PETSC_OWN_POINTER) { 1159 ierr = PetscFree(xadj);CHKERRQ(ierr); 1160 ierr = PetscFree(adjncy);CHKERRQ(ierr); 1161 } 1162 PetscFunctionReturn(0); 1163 } 1164 1165 static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 1166 { 1167 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1168 PetscInt i; 1169 PetscBool isequal = PETSC_FALSE; 1170 PetscErrorCode ierr; 1171 1172 PetscFunctionBegin; 1173 if (pcbddc->n_ISForDofsLocal == n_is) { 1174 for (i=0;i<n_is;i++) { 1175 PetscBool isequalt; 1176 ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr); 1177 if (!isequalt) break; 1178 } 1179 if (i == n_is) isequal = PETSC_TRUE; 1180 } 1181 for (i=0;i<n_is;i++) { 1182 ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr); 1183 } 1184 /* Destroy ISes if they were already set */ 1185 for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 1186 ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr); 1187 } 1188 ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr); 1189 /* last user setting takes precendence -> destroy any other customization */ 1190 for (i=0;i<pcbddc->n_ISForDofs;i++) { 1191 ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); 1192 } 1193 ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr); 1194 pcbddc->n_ISForDofs = 0; 1195 /* allocate space then set */ 1196 if (n_is) { 1197 ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr); 1198 } 1199 for (i=0;i<n_is;i++) { 1200 pcbddc->ISForDofsLocal[i] = ISForDofs[i]; 1201 } 1202 pcbddc->n_ISForDofsLocal = n_is; 1203 if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 1204 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 1205 PetscFunctionReturn(0); 1206 } 1207 1208 /*@ 1209 PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix 1210 1211 Collective 1212 1213 Input Parameters: 1214 + pc - the preconditioning context 1215 . n_is - number of index sets defining the fields 1216 - ISForDofs - array of IS describing the fields in local ordering 1217 1218 Level: intermediate 1219 1220 Notes: 1221 n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 1222 1223 .seealso: PCBDDC 1224 @*/ 1225 PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[]) 1226 { 1227 PetscInt i; 1228 PetscErrorCode ierr; 1229 1230 PetscFunctionBegin; 1231 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1232 PetscValidLogicalCollectiveInt(pc,n_is,2); 1233 for (i=0;i<n_is;i++) { 1234 PetscCheckSameComm(pc,1,ISForDofs[i],3); 1235 PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 1236 } 1237 ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr); 1238 PetscFunctionReturn(0); 1239 } 1240 1241 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 1242 { 1243 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1244 PetscInt i; 1245 PetscBool isequal = PETSC_FALSE; 1246 PetscErrorCode ierr; 1247 1248 PetscFunctionBegin; 1249 if (pcbddc->n_ISForDofs == n_is) { 1250 for (i=0;i<n_is;i++) { 1251 PetscBool isequalt; 1252 ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr); 1253 if (!isequalt) break; 1254 } 1255 if (i == n_is) isequal = PETSC_TRUE; 1256 } 1257 for (i=0;i<n_is;i++) { 1258 ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr); 1259 } 1260 /* Destroy ISes if they were already set */ 1261 for (i=0;i<pcbddc->n_ISForDofs;i++) { 1262 ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); 1263 } 1264 ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr); 1265 /* last user setting takes precendence -> destroy any other customization */ 1266 for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 1267 ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr); 1268 } 1269 ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr); 1270 pcbddc->n_ISForDofsLocal = 0; 1271 /* allocate space then set */ 1272 if (n_is) { 1273 ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr); 1274 } 1275 for (i=0;i<n_is;i++) { 1276 pcbddc->ISForDofs[i] = ISForDofs[i]; 1277 } 1278 pcbddc->n_ISForDofs = n_is; 1279 if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 1280 if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 1281 PetscFunctionReturn(0); 1282 } 1283 1284 /*@ 1285 PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix 1286 1287 Collective 1288 1289 Input Parameters: 1290 + pc - the preconditioning context 1291 . n_is - number of index sets defining the fields 1292 - ISForDofs - array of IS describing the fields in global ordering 1293 1294 Level: intermediate 1295 1296 Notes: 1297 Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 1298 1299 .seealso: PCBDDC 1300 @*/ 1301 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[]) 1302 { 1303 PetscInt i; 1304 PetscErrorCode ierr; 1305 1306 PetscFunctionBegin; 1307 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1308 PetscValidLogicalCollectiveInt(pc,n_is,2); 1309 for (i=0;i<n_is;i++) { 1310 PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 1311 PetscCheckSameComm(pc,1,ISForDofs[i],3); 1312 } 1313 ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr); 1314 PetscFunctionReturn(0); 1315 } 1316 1317 /* 1318 PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 1319 guess if a transformation of basis approach has been selected. 1320 1321 Input Parameter: 1322 + pc - the preconditioner context 1323 1324 Application Interface Routine: PCPreSolve() 1325 1326 Notes: 1327 The interface routine PCPreSolve() is not usually called directly by 1328 the user, but instead is called by KSPSolve(). 1329 */ 1330 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1331 { 1332 PetscErrorCode ierr; 1333 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1334 PC_IS *pcis = (PC_IS*)(pc->data); 1335 Vec used_vec; 1336 PetscBool iscg = PETSC_FALSE, save_rhs = PETSC_TRUE, benign_correction_computed; 1337 1338 PetscFunctionBegin; 1339 /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */ 1340 if (ksp) { 1341 PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr; 1342 1343 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr); 1344 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr); 1345 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr); 1346 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg);CHKERRQ(ierr); 1347 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr); 1348 iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr); 1349 if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) { 1350 ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr); 1351 } 1352 } 1353 if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) { 1354 ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr); 1355 } 1356 1357 /* Creates parallel work vectors used in presolve */ 1358 if (!pcbddc->original_rhs) { 1359 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr); 1360 } 1361 if (!pcbddc->temp_solution) { 1362 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr); 1363 } 1364 1365 pcbddc->temp_solution_used = PETSC_FALSE; 1366 if (x) { 1367 ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr); 1368 used_vec = x; 1369 } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 1370 ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr); 1371 used_vec = pcbddc->temp_solution; 1372 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 1373 pcbddc->temp_solution_used = PETSC_TRUE; 1374 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1375 save_rhs = PETSC_FALSE; 1376 pcbddc->eliminate_dirdofs = PETSC_TRUE; 1377 } 1378 1379 /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 1380 if (ksp) { 1381 /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 1382 ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 1383 if (!pcbddc->ksp_guess_nonzero) { 1384 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 1385 } 1386 } 1387 1388 pcbddc->rhs_change = PETSC_FALSE; 1389 /* Take into account zeroed rows -> change rhs and store solution removed */ 1390 if (rhs && pcbddc->eliminate_dirdofs) { 1391 IS dirIS = NULL; 1392 1393 /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 1394 ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr); 1395 if (dirIS) { 1396 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 1397 PetscInt dirsize,i,*is_indices; 1398 PetscScalar *array_x; 1399 const PetscScalar *array_diagonal; 1400 1401 ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr); 1402 ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr); 1403 ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1404 ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1405 ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1406 ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1407 ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr); 1408 ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 1409 ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 1410 ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 1411 for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 1412 ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 1413 ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 1414 ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 1415 ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1416 ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1417 pcbddc->rhs_change = PETSC_TRUE; 1418 ierr = ISDestroy(&dirIS);CHKERRQ(ierr); 1419 } 1420 } 1421 1422 /* remove the computed solution or the initial guess from the rhs */ 1423 if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) { 1424 /* save the original rhs */ 1425 if (save_rhs) { 1426 ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1427 save_rhs = PETSC_FALSE; 1428 } 1429 pcbddc->rhs_change = PETSC_TRUE; 1430 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1431 ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr); 1432 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1433 ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr); 1434 pcbddc->temp_solution_used = PETSC_TRUE; 1435 if (ksp) { 1436 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr); 1437 } 1438 } 1439 ierr = VecDestroy(&used_vec);CHKERRQ(ierr); 1440 1441 /* compute initial vector in benign space if needed 1442 and remove non-benign solution from the rhs */ 1443 benign_correction_computed = PETSC_FALSE; 1444 if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) { 1445 /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1) 1446 Recursively apply BDDC in the multilevel case */ 1447 if (!pcbddc->benign_vec) { 1448 ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr); 1449 } 1450 /* keep applying coarse solver unless we no longer have benign subdomains */ 1451 pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE; 1452 if (!pcbddc->benign_skip_correction) { 1453 ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr); 1454 benign_correction_computed = PETSC_TRUE; 1455 if (pcbddc->temp_solution_used) { 1456 ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr); 1457 } 1458 ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr); 1459 /* store the original rhs if not done earlier */ 1460 if (save_rhs) { 1461 ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1462 } 1463 if (pcbddc->rhs_change) { 1464 ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr); 1465 } else { 1466 ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr); 1467 } 1468 pcbddc->rhs_change = PETSC_TRUE; 1469 } 1470 pcbddc->benign_apply_coarse_only = PETSC_FALSE; 1471 } else { 1472 ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr); 1473 } 1474 1475 /* dbg output */ 1476 if (pcbddc->dbg_flag && benign_correction_computed) { 1477 Vec v; 1478 1479 ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr); 1480 if (pcbddc->ChangeOfBasisMatrix) { 1481 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr); 1482 } else { 1483 ierr = VecCopy(rhs,v);CHKERRQ(ierr); 1484 } 1485 ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr); 1486 ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr); 1487 ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr); 1488 ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr); 1489 ierr = VecDestroy(&v);CHKERRQ(ierr); 1490 } 1491 1492 /* set initial guess if using PCG */ 1493 pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 1494 if (x && pcbddc->use_exact_dirichlet_trick) { 1495 ierr = VecSet(x,0.0);CHKERRQ(ierr); 1496 if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 1497 if (benign_correction_computed) { /* we have already saved the changed rhs */ 1498 ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr); 1499 } else { 1500 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr); 1501 } 1502 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1503 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1504 } else { 1505 ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1506 ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1507 } 1508 ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 1509 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1510 ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 1511 ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr); 1512 if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 1513 ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr); 1514 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1515 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1516 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr); 1517 } else { 1518 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1519 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1520 } 1521 if (ksp) { 1522 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 1523 } 1524 pcbddc->exact_dirichlet_trick_app = PETSC_TRUE; 1525 } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) { 1526 ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr); 1527 } 1528 PetscFunctionReturn(0); 1529 } 1530 1531 /* 1532 PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1533 approach has been selected. Also, restores rhs to its original state. 1534 1535 Input Parameter: 1536 + pc - the preconditioner context 1537 1538 Application Interface Routine: PCPostSolve() 1539 1540 Notes: 1541 The interface routine PCPostSolve() is not usually called directly by 1542 the user, but instead is called by KSPSolve(). 1543 */ 1544 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1545 { 1546 PetscErrorCode ierr; 1547 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1548 1549 PetscFunctionBegin; 1550 /* add solution removed in presolve */ 1551 if (x && pcbddc->rhs_change) { 1552 if (pcbddc->temp_solution_used) { 1553 ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr); 1554 } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) { 1555 ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr); 1556 } 1557 /* restore to original state (not for FETI-DP) */ 1558 if (ksp) pcbddc->temp_solution_used = PETSC_FALSE; 1559 } 1560 1561 /* restore rhs to its original state (not needed for FETI-DP) */ 1562 if (rhs && pcbddc->rhs_change) { 1563 ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1564 pcbddc->rhs_change = PETSC_FALSE; 1565 } 1566 /* restore ksp guess state */ 1567 if (ksp) { 1568 ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 1569 /* reset flag for exact dirichlet trick */ 1570 pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 1571 } 1572 PetscFunctionReturn(0); 1573 } 1574 1575 /* 1576 PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 1577 by setting data structures and options. 1578 1579 Input Parameter: 1580 + pc - the preconditioner context 1581 1582 Application Interface Routine: PCSetUp() 1583 1584 Notes: 1585 The interface routine PCSetUp() is not usually called directly by 1586 the user, but instead is called by PCApply() if necessary. 1587 */ 1588 PetscErrorCode PCSetUp_BDDC(PC pc) 1589 { 1590 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 1591 PCBDDCSubSchurs sub_schurs; 1592 Mat_IS* matis; 1593 MatNullSpace nearnullspace; 1594 Mat lA; 1595 IS lP,zerodiag = NULL; 1596 PetscInt nrows,ncols; 1597 PetscMPIInt size; 1598 PetscBool computesubschurs; 1599 PetscBool computeconstraintsmatrix; 1600 PetscBool new_nearnullspace_provided,ismatis,rl; 1601 PetscErrorCode ierr; 1602 1603 PetscFunctionBegin; 1604 ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr); 1605 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS"); 1606 ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr); 1607 if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix"); 1608 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr); 1609 1610 matis = (Mat_IS*)pc->pmat->data; 1611 /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 1612 /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 1613 Also, BDDC builds its own KSP for the Dirichlet problem */ 1614 rl = pcbddc->recompute_topography; 1615 if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE; 1616 ierr = MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr); 1617 if (pcbddc->recompute_topography) { 1618 pcbddc->graphanalyzed = PETSC_FALSE; 1619 computeconstraintsmatrix = PETSC_TRUE; 1620 } else { 1621 computeconstraintsmatrix = PETSC_FALSE; 1622 } 1623 1624 /* check parameters' compatibility */ 1625 if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE; 1626 pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0); 1627 pcbddc->use_deluxe_scaling = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1); 1628 pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_selection && size > 1); 1629 pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined); 1630 if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1631 1632 computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 1633 1634 /* activate all connected components if the netflux has been requested */ 1635 if (pcbddc->compute_nonetflux) { 1636 pcbddc->use_vertices = PETSC_TRUE; 1637 pcbddc->use_edges = PETSC_TRUE; 1638 pcbddc->use_faces = PETSC_TRUE; 1639 } 1640 1641 /* Get stdout for dbg */ 1642 if (pcbddc->dbg_flag) { 1643 if (!pcbddc->dbg_viewer) { 1644 pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 1645 } 1646 ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr); 1647 ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1648 } 1649 1650 /* process topology information */ 1651 ierr = PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr); 1652 if (pcbddc->recompute_topography) { 1653 ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr); 1654 if (pcbddc->discretegradient) { 1655 ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr); 1656 } 1657 } 1658 if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE; 1659 1660 /* change basis if requested by the user */ 1661 if (pcbddc->user_ChangeOfBasisMatrix) { 1662 /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 1663 pcbddc->use_change_of_basis = PETSC_FALSE; 1664 ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr); 1665 } else { 1666 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1667 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1668 pcbddc->local_mat = matis->A; 1669 } 1670 1671 /* 1672 Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick 1673 This should come earlier then PCISSetUp for extracting the correct subdomain matrices 1674 */ 1675 ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr); 1676 if (pcbddc->benign_saddle_point) { 1677 PC_IS* pcis = (PC_IS*)pc->data; 1678 1679 if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE; 1680 /* detect local saddle point and change the basis in pcbddc->local_mat */ 1681 ierr = PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag);CHKERRQ(ierr); 1682 /* pop B0 mat from local mat */ 1683 ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr); 1684 /* give pcis a hint to not reuse submatrices during PCISCreate */ 1685 if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) { 1686 if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) { 1687 pcis->reusesubmatrices = PETSC_FALSE; 1688 } else { 1689 pcis->reusesubmatrices = PETSC_TRUE; 1690 } 1691 } else { 1692 pcis->reusesubmatrices = PETSC_FALSE; 1693 } 1694 } 1695 1696 /* propagate relevant information */ 1697 if (matis->A->symmetric_set) { 1698 ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr); 1699 } 1700 if (matis->A->spd_set) { 1701 ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr); 1702 } 1703 1704 /* Set up all the "iterative substructuring" common block without computing solvers */ 1705 { 1706 Mat temp_mat; 1707 1708 temp_mat = matis->A; 1709 matis->A = pcbddc->local_mat; 1710 ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1711 pcbddc->local_mat = matis->A; 1712 matis->A = temp_mat; 1713 } 1714 1715 /* Analyze interface */ 1716 if (!pcbddc->graphanalyzed) { 1717 ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr); 1718 computeconstraintsmatrix = PETSC_TRUE; 1719 if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) { 1720 SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling"); 1721 } 1722 if (pcbddc->compute_nonetflux) { 1723 MatNullSpace nnfnnsp; 1724 1725 if (!pcbddc->divudotp) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator"); 1726 ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr); 1727 /* TODO what if a nearnullspace is already attached? */ 1728 if (nnfnnsp) { 1729 ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr); 1730 ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr); 1731 } 1732 } 1733 } 1734 ierr = PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr); 1735 1736 /* check existence of a divergence free extension, i.e. 1737 b(v_I,p_0) = 0 for all v_I (raise error if not). 1738 Also, check that PCBDDCBenignGetOrSetP0 works */ 1739 if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) { 1740 ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr); 1741 } 1742 ierr = ISDestroy(&zerodiag);CHKERRQ(ierr); 1743 1744 /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 1745 if (computesubschurs && pcbddc->recompute_topography) { 1746 ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr); 1747 } 1748 /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/ 1749 if (!pcbddc->use_deluxe_scaling) { 1750 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 1751 } 1752 1753 /* finish setup solvers and do adaptive selection of constraints */ 1754 sub_schurs = pcbddc->sub_schurs; 1755 if (sub_schurs && sub_schurs->schur_explicit) { 1756 if (computesubschurs) { 1757 ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr); 1758 } 1759 ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1760 } else { 1761 ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1762 if (computesubschurs) { 1763 ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr); 1764 } 1765 } 1766 if (pcbddc->adaptive_selection) { 1767 ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr); 1768 computeconstraintsmatrix = PETSC_TRUE; 1769 } 1770 1771 /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1772 new_nearnullspace_provided = PETSC_FALSE; 1773 ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr); 1774 if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1775 if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1776 new_nearnullspace_provided = PETSC_TRUE; 1777 } else { 1778 /* determine if the two nullspaces are different (should be lightweight) */ 1779 if (nearnullspace != pcbddc->onearnullspace) { 1780 new_nearnullspace_provided = PETSC_TRUE; 1781 } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1782 PetscInt i; 1783 const Vec *nearnullvecs; 1784 PetscObjectState state; 1785 PetscInt nnsp_size; 1786 ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr); 1787 for (i=0;i<nnsp_size;i++) { 1788 ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr); 1789 if (pcbddc->onearnullvecs_state[i] != state) { 1790 new_nearnullspace_provided = PETSC_TRUE; 1791 break; 1792 } 1793 } 1794 } 1795 } 1796 } else { 1797 if (!nearnullspace) { /* both nearnullspaces are null */ 1798 new_nearnullspace_provided = PETSC_FALSE; 1799 } else { /* nearnullspace attached later */ 1800 new_nearnullspace_provided = PETSC_TRUE; 1801 } 1802 } 1803 1804 /* Setup constraints and related work vectors */ 1805 /* reset primal space flags */ 1806 ierr = PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr); 1807 pcbddc->new_primal_space = PETSC_FALSE; 1808 pcbddc->new_primal_space_local = PETSC_FALSE; 1809 if (computeconstraintsmatrix || new_nearnullspace_provided) { 1810 /* It also sets the primal space flags */ 1811 ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr); 1812 } 1813 /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 1814 ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr); 1815 1816 if (pcbddc->use_change_of_basis) { 1817 PC_IS *pcis = (PC_IS*)(pc->data); 1818 1819 ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr); 1820 if (pcbddc->benign_change) { 1821 ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr); 1822 /* pop B0 from pcbddc->local_mat */ 1823 ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr); 1824 } 1825 /* get submatrices */ 1826 ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr); 1827 ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr); 1828 ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr); 1829 ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr); 1830 ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr); 1831 ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr); 1832 /* set flag in pcis to not reuse submatrices during PCISCreate */ 1833 pcis->reusesubmatrices = PETSC_FALSE; 1834 } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) { 1835 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1836 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1837 pcbddc->local_mat = matis->A; 1838 } 1839 1840 /* interface pressure block row for B_C */ 1841 ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr); 1842 ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr); 1843 if (lA && lP) { 1844 PC_IS* pcis = (PC_IS*)pc->data; 1845 Mat B_BI,B_BB,Bt_BI,Bt_BB; 1846 PetscBool issym; 1847 ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr); 1848 if (issym) { 1849 ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr); 1850 ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr); 1851 ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr); 1852 ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr); 1853 } else { 1854 ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr); 1855 ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr); 1856 ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr); 1857 ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr); 1858 } 1859 ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr); 1860 ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr); 1861 ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr); 1862 ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr); 1863 ierr = MatDestroy(&B_BI);CHKERRQ(ierr); 1864 ierr = MatDestroy(&B_BB);CHKERRQ(ierr); 1865 ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr); 1866 ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr); 1867 } 1868 ierr = PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr); 1869 1870 /* SetUp coarse and local Neumann solvers */ 1871 ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr); 1872 /* SetUp Scaling operator */ 1873 if (pcbddc->use_deluxe_scaling) { 1874 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 1875 } 1876 1877 /* mark topography as done */ 1878 pcbddc->recompute_topography = PETSC_FALSE; 1879 1880 /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */ 1881 ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr); 1882 1883 if (pcbddc->dbg_flag) { 1884 ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1885 ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr); 1886 } 1887 PetscFunctionReturn(0); 1888 } 1889 1890 /* 1891 PCApply_BDDC - Applies the BDDC operator to a vector. 1892 1893 Input Parameters: 1894 + pc - the preconditioner context 1895 - r - input vector (global) 1896 1897 Output Parameter: 1898 . z - output vector (global) 1899 1900 Application Interface Routine: PCApply() 1901 */ 1902 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 1903 { 1904 PC_IS *pcis = (PC_IS*)(pc->data); 1905 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1906 Mat lA = NULL; 1907 PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 1908 PetscErrorCode ierr; 1909 const PetscScalar one = 1.0; 1910 const PetscScalar m_one = -1.0; 1911 const PetscScalar zero = 0.0; 1912 /* This code is similar to that provided in nn.c for PCNN 1913 NN interface preconditioner changed to BDDC 1914 Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 1915 1916 PetscFunctionBegin; 1917 ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr); 1918 if (pcbddc->switch_static) { 1919 ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr); 1920 } 1921 1922 if (pcbddc->ChangeOfBasisMatrix) { 1923 Vec swap; 1924 1925 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr); 1926 swap = pcbddc->work_change; 1927 pcbddc->work_change = r; 1928 r = swap; 1929 /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 1930 if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 1931 ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr); 1932 ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr); 1933 } 1934 } 1935 if (pcbddc->benign_have_null) { /* get p0 from r */ 1936 ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr); 1937 } 1938 if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1939 ierr = VecCopy(r,z);CHKERRQ(ierr); 1940 /* First Dirichlet solve */ 1941 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1942 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1943 /* 1944 Assembling right hand side for BDDC operator 1945 - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1946 - pcis->vec1_B the interface part of the global vector z 1947 */ 1948 if (n_D) { 1949 ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 1950 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1951 ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 1952 ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr); 1953 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1954 if (pcbddc->switch_static) { 1955 ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr); 1956 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1957 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1958 if (!pcbddc->switch_static_change) { 1959 ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1960 } else { 1961 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1962 ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 1963 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1964 } 1965 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1966 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1967 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1968 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1969 } else { 1970 ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1971 } 1972 } else { 1973 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 1974 } 1975 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1976 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1977 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1978 } else { 1979 if (!pcbddc->benign_apply_coarse_only) { 1980 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1981 } 1982 } 1983 if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 1984 if (!pcbddc->switch_static) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static"); 1985 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1986 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1987 } 1988 1989 /* Apply interface preconditioner 1990 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1991 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr); 1992 1993 /* Apply transpose of partition of unity operator */ 1994 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1995 if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 1996 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1997 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1998 PetscFunctionReturn(0); 1999 } 2000 /* Second Dirichlet solve and assembling of output */ 2001 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2002 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2003 if (n_B) { 2004 if (pcbddc->switch_static) { 2005 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2006 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2007 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2008 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2009 if (!pcbddc->switch_static_change) { 2010 ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2011 } else { 2012 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2013 ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 2014 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2015 } 2016 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2017 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2018 } else { 2019 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 2020 } 2021 } else if (pcbddc->switch_static) { /* n_B is zero */ 2022 if (!pcbddc->switch_static_change) { 2023 ierr = MatMult(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr); 2024 } else { 2025 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr); 2026 ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2027 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr); 2028 } 2029 } 2030 ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 2031 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 2032 ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 2033 ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr); 2034 2035 if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 2036 if (pcbddc->switch_static) { 2037 ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr); 2038 } else { 2039 ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr); 2040 } 2041 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2042 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2043 } else { 2044 if (pcbddc->switch_static) { 2045 ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr); 2046 } else { 2047 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 2048 } 2049 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2050 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2051 } 2052 if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 2053 if (pcbddc->benign_apply_coarse_only) { 2054 ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr); 2055 } 2056 ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr); 2057 } 2058 2059 if (pcbddc->ChangeOfBasisMatrix) { 2060 pcbddc->work_change = r; 2061 ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr); 2062 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr); 2063 } 2064 PetscFunctionReturn(0); 2065 } 2066 2067 /* 2068 PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 2069 2070 Input Parameters: 2071 + pc - the preconditioner context 2072 - r - input vector (global) 2073 2074 Output Parameter: 2075 . z - output vector (global) 2076 2077 Application Interface Routine: PCApplyTranspose() 2078 */ 2079 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z) 2080 { 2081 PC_IS *pcis = (PC_IS*)(pc->data); 2082 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 2083 Mat lA = NULL; 2084 PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 2085 PetscErrorCode ierr; 2086 const PetscScalar one = 1.0; 2087 const PetscScalar m_one = -1.0; 2088 const PetscScalar zero = 0.0; 2089 2090 PetscFunctionBegin; 2091 ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr); 2092 if (pcbddc->switch_static) { 2093 ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr); 2094 } 2095 if (pcbddc->ChangeOfBasisMatrix) { 2096 Vec swap; 2097 2098 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr); 2099 swap = pcbddc->work_change; 2100 pcbddc->work_change = r; 2101 r = swap; 2102 /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 2103 if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) { 2104 ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr); 2105 ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr); 2106 } 2107 } 2108 if (pcbddc->benign_have_null) { /* get p0 from r */ 2109 ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr); 2110 } 2111 if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 2112 ierr = VecCopy(r,z);CHKERRQ(ierr); 2113 /* First Dirichlet solve */ 2114 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2115 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2116 /* 2117 Assembling right hand side for BDDC operator 2118 - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 2119 - pcis->vec1_B the interface part of the global vector z 2120 */ 2121 if (n_D) { 2122 ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 2123 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 2124 ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 2125 ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr); 2126 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 2127 if (pcbddc->switch_static) { 2128 ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr); 2129 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2130 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2131 if (!pcbddc->switch_static_change) { 2132 ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2133 } else { 2134 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2135 ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 2136 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2137 } 2138 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2139 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2140 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2141 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2142 } else { 2143 ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 2144 } 2145 } else { 2146 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 2147 } 2148 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2149 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2150 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 2151 } else { 2152 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 2153 } 2154 2155 /* Apply interface preconditioner 2156 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 2157 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr); 2158 2159 /* Apply transpose of partition of unity operator */ 2160 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 2161 2162 /* Second Dirichlet solve and assembling of output */ 2163 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2164 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2165 if (n_B) { 2166 if (pcbddc->switch_static) { 2167 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2168 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2169 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2170 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2171 if (!pcbddc->switch_static_change) { 2172 ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2173 } else { 2174 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2175 ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 2176 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2177 } 2178 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2179 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2180 } else { 2181 ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 2182 } 2183 } else if (pcbddc->switch_static) { /* n_B is zero */ 2184 if (!pcbddc->switch_static_change) { 2185 ierr = MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr); 2186 } else { 2187 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr); 2188 ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 2189 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr); 2190 } 2191 } 2192 ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 2193 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 2194 ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr); 2195 ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr); 2196 if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 2197 if (pcbddc->switch_static) { 2198 ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr); 2199 } else { 2200 ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr); 2201 } 2202 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2203 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2204 } else { 2205 if (pcbddc->switch_static) { 2206 ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr); 2207 } else { 2208 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 2209 } 2210 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2211 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2212 } 2213 if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 2214 ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr); 2215 } 2216 if (pcbddc->ChangeOfBasisMatrix) { 2217 pcbddc->work_change = r; 2218 ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr); 2219 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr); 2220 } 2221 PetscFunctionReturn(0); 2222 } 2223 2224 PetscErrorCode PCReset_BDDC(PC pc) 2225 { 2226 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2227 PC_IS *pcis = (PC_IS*)pc->data; 2228 KSP kspD,kspR,kspC; 2229 PetscErrorCode ierr; 2230 2231 PetscFunctionBegin; 2232 /* free BDDC custom data */ 2233 ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr); 2234 /* destroy objects related to topography */ 2235 ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr); 2236 /* destroy objects for scaling operator */ 2237 ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr); 2238 /* free solvers stuff */ 2239 ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr); 2240 /* free global vectors needed in presolve */ 2241 ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr); 2242 ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr); 2243 /* free data created by PCIS */ 2244 ierr = PCISDestroy(pc);CHKERRQ(ierr); 2245 2246 /* restore defaults */ 2247 kspD = pcbddc->ksp_D; 2248 kspR = pcbddc->ksp_R; 2249 kspC = pcbddc->coarse_ksp; 2250 ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr); 2251 pcis->n_neigh = -1; 2252 pcis->scaling_factor = 1.0; 2253 pcis->reusesubmatrices = PETSC_TRUE; 2254 pcbddc->use_local_adj = PETSC_TRUE; 2255 pcbddc->use_vertices = PETSC_TRUE; 2256 pcbddc->use_edges = PETSC_TRUE; 2257 pcbddc->symmetric_primal = PETSC_TRUE; 2258 pcbddc->vertex_size = 1; 2259 pcbddc->recompute_topography = PETSC_TRUE; 2260 pcbddc->coarse_size = -1; 2261 pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 2262 pcbddc->coarsening_ratio = 8; 2263 pcbddc->coarse_eqs_per_proc = 1; 2264 pcbddc->benign_compute_correction = PETSC_TRUE; 2265 pcbddc->nedfield = -1; 2266 pcbddc->nedglobal = PETSC_TRUE; 2267 pcbddc->graphmaxcount = PETSC_MAX_INT; 2268 pcbddc->sub_schurs_layers = -1; 2269 pcbddc->ksp_D = kspD; 2270 pcbddc->ksp_R = kspR; 2271 pcbddc->coarse_ksp = kspC; 2272 PetscFunctionReturn(0); 2273 } 2274 2275 PetscErrorCode PCDestroy_BDDC(PC pc) 2276 { 2277 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2278 PetscErrorCode ierr; 2279 2280 PetscFunctionBegin; 2281 ierr = PCReset_BDDC(pc);CHKERRQ(ierr); 2282 ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr); 2283 ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr); 2284 ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr); 2285 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr); 2286 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr); 2287 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr); 2288 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr); 2289 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr); 2290 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr); 2291 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr); 2292 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr); 2293 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr); 2294 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 2295 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 2296 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 2297 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 2298 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 2299 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 2300 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 2301 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 2302 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr); 2303 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr); 2304 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr); 2305 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr); 2306 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr); 2307 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr); 2308 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr); 2309 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr); 2310 ierr = PetscFree(pc->data);CHKERRQ(ierr); 2311 PetscFunctionReturn(0); 2312 } 2313 2314 static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) 2315 { 2316 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2317 PCBDDCGraph mat_graph = pcbddc->mat_graph; 2318 PetscErrorCode ierr; 2319 2320 PetscFunctionBegin; 2321 ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr); 2322 ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr); 2323 ierr = PetscArraycpy(mat_graph->coords,coords,nloc*dim);CHKERRQ(ierr); 2324 mat_graph->cnloc = nloc; 2325 mat_graph->cdim = dim; 2326 mat_graph->cloc = PETSC_FALSE; 2327 /* flg setup */ 2328 pcbddc->recompute_topography = PETSC_TRUE; 2329 pcbddc->corner_selected = PETSC_FALSE; 2330 PetscFunctionReturn(0); 2331 } 2332 2333 static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change) 2334 { 2335 PetscFunctionBegin; 2336 *change = PETSC_TRUE; 2337 PetscFunctionReturn(0); 2338 } 2339 2340 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2341 { 2342 FETIDPMat_ctx mat_ctx; 2343 Vec work; 2344 PC_IS* pcis; 2345 PC_BDDC* pcbddc; 2346 PetscErrorCode ierr; 2347 2348 PetscFunctionBegin; 2349 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2350 pcis = (PC_IS*)mat_ctx->pc->data; 2351 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 2352 2353 ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr); 2354 /* copy rhs since we may change it during PCPreSolve_BDDC */ 2355 if (!pcbddc->original_rhs) { 2356 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr); 2357 } 2358 if (mat_ctx->rhs_flip) { 2359 ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr); 2360 } else { 2361 ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr); 2362 } 2363 if (mat_ctx->g2g_p) { 2364 /* interface pressure rhs */ 2365 ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2366 ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2367 ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2368 ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2369 if (!mat_ctx->rhs_flip) { 2370 ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr); 2371 } 2372 } 2373 /* 2374 change of basis for physical rhs if needed 2375 It also changes the rhs in case of dirichlet boundaries 2376 */ 2377 ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr); 2378 if (pcbddc->ChangeOfBasisMatrix) { 2379 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr); 2380 work = pcbddc->work_change; 2381 } else { 2382 work = pcbddc->original_rhs; 2383 } 2384 /* store vectors for computation of fetidp final solution */ 2385 ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2386 ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2387 /* scale rhs since it should be unassembled */ 2388 /* TODO use counter scaling? (also below) */ 2389 ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2390 ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2391 /* Apply partition of unity */ 2392 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 2393 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 2394 if (!pcbddc->switch_static) { 2395 /* compute partially subassembled Schur complement right-hand side */ 2396 ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr); 2397 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 2398 ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr); 2399 /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 2400 ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr); 2401 ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr); 2402 ierr = VecSet(work,0.0);CHKERRQ(ierr); 2403 ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2404 ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2405 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 2406 ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2407 ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2408 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 2409 } 2410 /* BDDC rhs */ 2411 ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr); 2412 if (pcbddc->switch_static) { 2413 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 2414 } 2415 /* apply BDDC */ 2416 ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr); 2417 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 2418 ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr); 2419 2420 /* Application of B_delta and assembling of rhs for fetidp fluxes */ 2421 ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr); 2422 ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2423 ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2424 /* Add contribution to interface pressures */ 2425 if (mat_ctx->l2g_p) { 2426 ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr); 2427 if (pcbddc->switch_static) { 2428 ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr); 2429 } 2430 ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2431 ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2432 } 2433 PetscFunctionReturn(0); 2434 } 2435 2436 /*@ 2437 PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side 2438 2439 Collective 2440 2441 Input Parameters: 2442 + fetidp_mat - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators 2443 - standard_rhs - the right-hand side of the original linear system 2444 2445 Output Parameters: 2446 . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 2447 2448 Level: developer 2449 2450 Notes: 2451 2452 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution 2453 @*/ 2454 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2455 { 2456 FETIDPMat_ctx mat_ctx; 2457 PetscErrorCode ierr; 2458 2459 PetscFunctionBegin; 2460 PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1); 2461 PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2); 2462 PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3); 2463 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2464 ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr); 2465 PetscFunctionReturn(0); 2466 } 2467 2468 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2469 { 2470 FETIDPMat_ctx mat_ctx; 2471 PC_IS* pcis; 2472 PC_BDDC* pcbddc; 2473 PetscErrorCode ierr; 2474 Vec work; 2475 2476 PetscFunctionBegin; 2477 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2478 pcis = (PC_IS*)mat_ctx->pc->data; 2479 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 2480 2481 /* apply B_delta^T */ 2482 ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr); 2483 ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2484 ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2485 ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr); 2486 if (mat_ctx->l2g_p) { 2487 ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2488 ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2489 ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr); 2490 } 2491 2492 /* compute rhs for BDDC application */ 2493 ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr); 2494 if (pcbddc->switch_static) { 2495 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 2496 if (mat_ctx->l2g_p) { 2497 ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr); 2498 ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); 2499 } 2500 } 2501 2502 /* apply BDDC */ 2503 ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr); 2504 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 2505 2506 /* put values into global vector */ 2507 if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change; 2508 else work = standard_sol; 2509 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2510 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2511 if (!pcbddc->switch_static) { 2512 /* compute values into the interior if solved for the partially subassembled Schur complement */ 2513 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr); 2514 ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr); 2515 ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr); 2516 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); 2517 ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr); 2518 /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 2519 } 2520 2521 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2522 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2523 /* add p0 solution to final solution */ 2524 ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr); 2525 if (pcbddc->ChangeOfBasisMatrix) { 2526 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr); 2527 } 2528 ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr); 2529 if (mat_ctx->g2g_p) { 2530 ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2531 ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2532 } 2533 PetscFunctionReturn(0); 2534 } 2535 2536 static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) 2537 { 2538 PetscErrorCode ierr; 2539 BDDCIPC_ctx bddcipc_ctx; 2540 PetscBool isascii; 2541 2542 PetscFunctionBegin; 2543 ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr); 2544 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 2545 if (isascii) { 2546 ierr = PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n");CHKERRQ(ierr); 2547 } 2548 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 2549 ierr = PCView(bddcipc_ctx->bddc,viewer);CHKERRQ(ierr); 2550 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 2551 PetscFunctionReturn(0); 2552 } 2553 2554 static PetscErrorCode PCSetUp_BDDCIPC(PC pc) 2555 { 2556 PetscErrorCode ierr; 2557 BDDCIPC_ctx bddcipc_ctx; 2558 PetscBool isbddc; 2559 Vec vv; 2560 IS is; 2561 PC_IS *pcis; 2562 2563 PetscFunctionBegin; 2564 ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr); 2565 ierr = PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc);CHKERRQ(ierr); 2566 if (!isbddc) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name); 2567 ierr = PCSetUp(bddcipc_ctx->bddc);CHKERRQ(ierr); 2568 2569 /* create interface scatter */ 2570 pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 2571 ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr); 2572 ierr = MatCreateVecs(pc->pmat,&vv,NULL);CHKERRQ(ierr); 2573 ierr = ISRenumber(pcis->is_B_global,NULL,NULL,&is);CHKERRQ(ierr); 2574 ierr = VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l);CHKERRQ(ierr); 2575 ierr = ISDestroy(&is);CHKERRQ(ierr); 2576 ierr = VecDestroy(&vv);CHKERRQ(ierr); 2577 PetscFunctionReturn(0); 2578 } 2579 2580 static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) 2581 { 2582 PetscErrorCode ierr; 2583 BDDCIPC_ctx bddcipc_ctx; 2584 PC_IS *pcis; 2585 VecScatter tmps; 2586 2587 PetscFunctionBegin; 2588 ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr); 2589 pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 2590 tmps = pcis->global_to_B; 2591 pcis->global_to_B = bddcipc_ctx->g2l; 2592 ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr); 2593 ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE);CHKERRQ(ierr); 2594 ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr); 2595 pcis->global_to_B = tmps; 2596 PetscFunctionReturn(0); 2597 } 2598 2599 static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) 2600 { 2601 PetscErrorCode ierr; 2602 BDDCIPC_ctx bddcipc_ctx; 2603 PC_IS *pcis; 2604 VecScatter tmps; 2605 2606 PetscFunctionBegin; 2607 ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr); 2608 pcis = (PC_IS*)(bddcipc_ctx->bddc->data); 2609 tmps = pcis->global_to_B; 2610 pcis->global_to_B = bddcipc_ctx->g2l; 2611 ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr); 2612 ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE);CHKERRQ(ierr); 2613 ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr); 2614 pcis->global_to_B = tmps; 2615 PetscFunctionReturn(0); 2616 } 2617 2618 static PetscErrorCode PCDestroy_BDDCIPC(PC pc) 2619 { 2620 PetscErrorCode ierr; 2621 BDDCIPC_ctx bddcipc_ctx; 2622 2623 PetscFunctionBegin; 2624 ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr); 2625 ierr = PCDestroy(&bddcipc_ctx->bddc);CHKERRQ(ierr); 2626 ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr); 2627 ierr = PetscFree(bddcipc_ctx);CHKERRQ(ierr); 2628 PetscFunctionReturn(0); 2629 } 2630 2631 /*@ 2632 PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 2633 2634 Collective 2635 2636 Input Parameters: 2637 + fetidp_mat - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators 2638 - fetidp_flux_sol - the solution of the FETI-DP linear system 2639 2640 Output Parameters: 2641 . standard_sol - the solution defined on the physical domain 2642 2643 Level: developer 2644 2645 Notes: 2646 2647 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS 2648 @*/ 2649 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2650 { 2651 FETIDPMat_ctx mat_ctx; 2652 PetscErrorCode ierr; 2653 2654 PetscFunctionBegin; 2655 PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1); 2656 PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2); 2657 PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3); 2658 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2659 ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr); 2660 PetscFunctionReturn(0); 2661 } 2662 2663 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc) 2664 { 2665 2666 FETIDPMat_ctx fetidpmat_ctx; 2667 Mat newmat; 2668 FETIDPPC_ctx fetidppc_ctx; 2669 PC newpc; 2670 MPI_Comm comm; 2671 PetscErrorCode ierr; 2672 2673 PetscFunctionBegin; 2674 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 2675 /* FETI-DP matrix */ 2676 ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr); 2677 fetidpmat_ctx->fully_redundant = fully_redundant; 2678 ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr); 2679 ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr); 2680 ierr = PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G");CHKERRQ(ierr); 2681 ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr); 2682 ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr); 2683 ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr); 2684 /* propagate MatOptions */ 2685 { 2686 PC_BDDC *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data; 2687 PetscBool issym; 2688 2689 ierr = MatGetOption(pc->mat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr); 2690 if (issym || pcbddc->symmetric_primal) { 2691 ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); 2692 } 2693 } 2694 ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr); 2695 ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr); 2696 ierr = MatSetUp(newmat);CHKERRQ(ierr); 2697 /* FETI-DP preconditioner */ 2698 ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr); 2699 ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr); 2700 ierr = PCCreate(comm,&newpc);CHKERRQ(ierr); 2701 ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr); 2702 ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr); 2703 ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr); 2704 ierr = PCSetErrorIfFailure(newpc,pc->erroriffailure);CHKERRQ(ierr); 2705 if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */ 2706 ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr); 2707 ierr = PCShellSetName(newpc,"FETI-DP multipliers");CHKERRQ(ierr); 2708 ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr); 2709 ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr); 2710 ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr); 2711 ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr); 2712 ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr); 2713 } else { /* saddle-point FETI-DP */ 2714 Mat M; 2715 PetscInt psize; 2716 PetscBool fake = PETSC_FALSE, isfieldsplit; 2717 2718 ierr = ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view");CHKERRQ(ierr); 2719 ierr = ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view");CHKERRQ(ierr); 2720 ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr); 2721 ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr); 2722 ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr); 2723 ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr); 2724 ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr); 2725 ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr); 2726 ierr = ISGetSize(fetidpmat_ctx->pressure,&psize);CHKERRQ(ierr); 2727 if (psize != M->rmap->N) { 2728 Mat M2; 2729 PetscInt lpsize; 2730 2731 fake = PETSC_TRUE; 2732 ierr = ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize);CHKERRQ(ierr); 2733 ierr = MatCreate(comm,&M2);CHKERRQ(ierr); 2734 ierr = MatSetType(M2,MATAIJ);CHKERRQ(ierr); 2735 ierr = MatSetSizes(M2,lpsize,lpsize,psize,psize);CHKERRQ(ierr); 2736 ierr = MatSetUp(M2);CHKERRQ(ierr); 2737 ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2738 ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2739 ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2);CHKERRQ(ierr); 2740 ierr = MatDestroy(&M2);CHKERRQ(ierr); 2741 } else { 2742 ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr); 2743 } 2744 ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr); 2745 2746 /* we need to setfromoptions and setup here to access the blocks */ 2747 ierr = PCSetFromOptions(newpc);CHKERRQ(ierr); 2748 ierr = PCSetUp(newpc);CHKERRQ(ierr); 2749 2750 /* user may have changed the type (e.g. -fetidp_pc_type none) */ 2751 ierr = PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit);CHKERRQ(ierr); 2752 if (isfieldsplit) { 2753 KSP *ksps; 2754 PC ppc,lagpc; 2755 PetscInt nn; 2756 PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE; 2757 2758 /* set the solver for the (0,0) block */ 2759 ierr = PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr); 2760 if (!nn) { /* not of type PC_COMPOSITE_SCHUR */ 2761 ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr); 2762 if (!fake) { /* pass pmat to the pressure solver */ 2763 Mat F; 2764 2765 ierr = KSPGetOperators(ksps[1],&F,NULL);CHKERRQ(ierr); 2766 ierr = KSPSetOperators(ksps[1],F,M);CHKERRQ(ierr); 2767 } 2768 } else { 2769 PetscBool issym; 2770 Mat S; 2771 2772 ierr = PCFieldSplitSchurGetS(newpc,&S);CHKERRQ(ierr); 2773 2774 ierr = MatGetOption(newmat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr); 2775 if (issym) { 2776 ierr = MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); 2777 } 2778 } 2779 ierr = KSPGetPC(ksps[0],&lagpc);CHKERRQ(ierr); 2780 ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr); 2781 ierr = PCShellSetName(lagpc,"FETI-DP multipliers");CHKERRQ(ierr); 2782 ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr); 2783 ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr); 2784 ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr); 2785 ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr); 2786 ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr); 2787 2788 /* Olof's idea: interface Schur complement preconditioner for the mass matrix */ 2789 ierr = KSPGetPC(ksps[1],&ppc);CHKERRQ(ierr); 2790 if (fake) { 2791 BDDCIPC_ctx bddcipc_ctx; 2792 PetscContainer c; 2793 2794 matisok = PETSC_TRUE; 2795 2796 /* create inner BDDC solver */ 2797 ierr = PetscNew(&bddcipc_ctx);CHKERRQ(ierr); 2798 ierr = PCCreate(comm,&bddcipc_ctx->bddc);CHKERRQ(ierr); 2799 ierr = PCSetType(bddcipc_ctx->bddc,PCBDDC);CHKERRQ(ierr); 2800 ierr = PCSetOperators(bddcipc_ctx->bddc,M,M);CHKERRQ(ierr); 2801 ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c);CHKERRQ(ierr); 2802 ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr); 2803 if (c && ismatis) { 2804 Mat lM; 2805 PetscInt *csr,n; 2806 2807 ierr = MatISGetLocalMat(M,&lM);CHKERRQ(ierr); 2808 ierr = MatGetSize(lM,&n,NULL);CHKERRQ(ierr); 2809 ierr = PetscContainerGetPointer(c,(void**)&csr);CHKERRQ(ierr); 2810 ierr = PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES);CHKERRQ(ierr); 2811 ierr = MatISRestoreLocalMat(M,&lM);CHKERRQ(ierr); 2812 } 2813 ierr = PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix);CHKERRQ(ierr); 2814 ierr = PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure);CHKERRQ(ierr); 2815 ierr = PCSetFromOptions(bddcipc_ctx->bddc);CHKERRQ(ierr); 2816 2817 /* wrap the interface application */ 2818 ierr = PCSetType(ppc,PCSHELL);CHKERRQ(ierr); 2819 ierr = PCShellSetName(ppc,"FETI-DP pressure");CHKERRQ(ierr); 2820 ierr = PCShellSetContext(ppc,bddcipc_ctx);CHKERRQ(ierr); 2821 ierr = PCShellSetSetUp(ppc,PCSetUp_BDDCIPC);CHKERRQ(ierr); 2822 ierr = PCShellSetApply(ppc,PCApply_BDDCIPC);CHKERRQ(ierr); 2823 ierr = PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC);CHKERRQ(ierr); 2824 ierr = PCShellSetView(ppc,PCView_BDDCIPC);CHKERRQ(ierr); 2825 ierr = PCShellSetDestroy(ppc,PCDestroy_BDDCIPC);CHKERRQ(ierr); 2826 } 2827 2828 /* determine if we need to assemble M to construct a preconditioner */ 2829 if (!matisok) { 2830 ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr); 2831 ierr = PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"");CHKERRQ(ierr); 2832 if (ismatis && !matisok) { 2833 ierr = MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M);CHKERRQ(ierr); 2834 } 2835 } 2836 2837 /* run the subproblems to check convergence */ 2838 ierr = PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL);CHKERRQ(ierr); 2839 if (check) { 2840 PetscInt i; 2841 2842 for (i=0;i<nn;i++) { 2843 KSP kspC; 2844 PC pc; 2845 Mat F,pF; 2846 Vec x,y; 2847 PetscBool isschur,prec = PETSC_TRUE; 2848 2849 ierr = KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC);CHKERRQ(ierr); 2850 ierr = KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix);CHKERRQ(ierr); 2851 ierr = KSPAppendOptionsPrefix(kspC,"check_");CHKERRQ(ierr); 2852 ierr = KSPGetOperators(ksps[i],&F,&pF);CHKERRQ(ierr); 2853 ierr = PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur);CHKERRQ(ierr); 2854 if (isschur) { 2855 KSP kspS,kspS2; 2856 Mat A00,pA00,A10,A01,A11; 2857 char prefix[256]; 2858 2859 ierr = MatSchurComplementGetKSP(F,&kspS);CHKERRQ(ierr); 2860 ierr = MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11);CHKERRQ(ierr); 2861 ierr = MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F);CHKERRQ(ierr); 2862 ierr = MatSchurComplementGetKSP(F,&kspS2);CHKERRQ(ierr); 2863 ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix);CHKERRQ(ierr); 2864 ierr = KSPSetOptionsPrefix(kspS2,prefix);CHKERRQ(ierr); 2865 ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr); 2866 ierr = PCSetType(pc,PCKSP);CHKERRQ(ierr); 2867 ierr = PCKSPSetKSP(pc,kspS);CHKERRQ(ierr); 2868 ierr = KSPSetFromOptions(kspS2);CHKERRQ(ierr); 2869 ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr); 2870 ierr = PCSetUseAmat(pc,PETSC_TRUE);CHKERRQ(ierr); 2871 } else { 2872 ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr); 2873 } 2874 ierr = KSPSetFromOptions(kspC);CHKERRQ(ierr); 2875 ierr = PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL);CHKERRQ(ierr); 2876 if (prec) { 2877 ierr = KSPGetPC(ksps[i],&pc);CHKERRQ(ierr); 2878 ierr = KSPSetPC(kspC,pc);CHKERRQ(ierr); 2879 } 2880 ierr = KSPSetOperators(kspC,F,pF);CHKERRQ(ierr); 2881 ierr = MatCreateVecs(F,&x,&y);CHKERRQ(ierr); 2882 ierr = VecSetRandom(x,NULL);CHKERRQ(ierr); 2883 ierr = MatMult(F,x,y);CHKERRQ(ierr); 2884 ierr = KSPSolve(kspC,y,x);CHKERRQ(ierr); 2885 ierr = KSPCheckSolve(kspC,pc,x);CHKERRQ(ierr); 2886 ierr = KSPDestroy(&kspC);CHKERRQ(ierr); 2887 ierr = MatDestroy(&F);CHKERRQ(ierr); 2888 ierr = VecDestroy(&x);CHKERRQ(ierr); 2889 ierr = VecDestroy(&y);CHKERRQ(ierr); 2890 } 2891 } 2892 ierr = PetscFree(ksps);CHKERRQ(ierr); 2893 } 2894 } 2895 /* return pointers for objects created */ 2896 *fetidp_mat = newmat; 2897 *fetidp_pc = newpc; 2898 PetscFunctionReturn(0); 2899 } 2900 2901 /*@C 2902 PCBDDCCreateFETIDPOperators - Create FETI-DP operators 2903 2904 Collective 2905 2906 Input Parameters: 2907 + pc - the BDDC preconditioning context (setup should have been called before) 2908 . fully_redundant - true for a fully redundant set of Lagrange multipliers 2909 - prefix - optional options database prefix for the objects to be created (can be NULL) 2910 2911 Output Parameters: 2912 + fetidp_mat - shell FETI-DP matrix object 2913 - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 2914 2915 Level: developer 2916 2917 Notes: 2918 Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose 2919 2920 .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution 2921 @*/ 2922 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) 2923 { 2924 PetscErrorCode ierr; 2925 2926 PetscFunctionBegin; 2927 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 2928 if (pc->setupcalled) { 2929 ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr); 2930 } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first"); 2931 PetscFunctionReturn(0); 2932 } 2933 /* -------------------------------------------------------------------------- */ 2934 /*MC 2935 PCBDDC - Balancing Domain Decomposition by Constraints. 2936 2937 An implementation of the BDDC preconditioner based on the bibliography found below. 2938 2939 The matrix to be preconditioned (Pmat) must be of type MATIS. 2940 2941 Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 2942 2943 It also works with unsymmetric and indefinite problems. 2944 2945 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. 2946 2947 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). 2948 2949 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() 2950 Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts. 2951 2952 Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD. 2953 2954 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. 2955 User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat() 2956 2957 The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object. 2958 2959 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. 2960 2961 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. 2962 2963 Options Database Keys (some of them, run with -help for a complete list): 2964 2965 + -pc_bddc_use_vertices <true> - use or not vertices in primal space 2966 . -pc_bddc_use_edges <true> - use or not edges in primal space 2967 . -pc_bddc_use_faces <false> - use or not faces in primal space 2968 . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 2969 . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 2970 . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 2971 . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 2972 . -pc_bddc_levels <0> - maximum number of levels for multilevel 2973 . -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) 2974 . -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) 2975 . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 2976 . -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) 2977 . -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) 2978 - -pc_bddc_check_level <0> - set verbosity level of debugging output 2979 2980 Options for Dirichlet, Neumann or coarse solver can be set with 2981 .vb 2982 -pc_bddc_dirichlet_ 2983 -pc_bddc_neumann_ 2984 -pc_bddc_coarse_ 2985 .ve 2986 e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU. 2987 2988 When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as 2989 .vb 2990 -pc_bddc_dirichlet_lN_ 2991 -pc_bddc_neumann_lN_ 2992 -pc_bddc_coarse_lN_ 2993 .ve 2994 Note that level number ranges from the finest (0) to the coarsest (N). 2995 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. 2996 .vb 2997 -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 2998 .ve 2999 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 3000 3001 References: 3002 + [1] - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007 3003 . [2] - 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 3004 . [3] - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008 3005 - [4] - C. Pechstein and C. R. Dohrmann. "Modern domain decomposition methods BDDC, deluxe scaling, and an algebraic approach", Seminar talk, Linz, December 2013, http://people.ricam.oeaw.ac.at/c.pechstein/pechstein-bddc2013.pdf 3006 3007 Level: intermediate 3008 3009 Developer Notes: 3010 3011 Contributed by Stefano Zampini 3012 3013 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 3014 M*/ 3015 3016 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 3017 { 3018 PetscErrorCode ierr; 3019 PC_BDDC *pcbddc; 3020 3021 PetscFunctionBegin; 3022 ierr = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr); 3023 pc->data = (void*)pcbddc; 3024 3025 /* create PCIS data structure */ 3026 ierr = PCISCreate(pc);CHKERRQ(ierr); 3027 3028 /* create local graph structure */ 3029 ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr); 3030 3031 /* BDDC nonzero defaults */ 3032 pcbddc->use_nnsp = PETSC_TRUE; 3033 pcbddc->use_local_adj = PETSC_TRUE; 3034 pcbddc->use_vertices = PETSC_TRUE; 3035 pcbddc->use_edges = PETSC_TRUE; 3036 pcbddc->symmetric_primal = PETSC_TRUE; 3037 pcbddc->vertex_size = 1; 3038 pcbddc->recompute_topography = PETSC_TRUE; 3039 pcbddc->coarse_size = -1; 3040 pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 3041 pcbddc->coarsening_ratio = 8; 3042 pcbddc->coarse_eqs_per_proc = 1; 3043 pcbddc->benign_compute_correction = PETSC_TRUE; 3044 pcbddc->nedfield = -1; 3045 pcbddc->nedglobal = PETSC_TRUE; 3046 pcbddc->graphmaxcount = PETSC_MAX_INT; 3047 pcbddc->sub_schurs_layers = -1; 3048 pcbddc->adaptive_threshold[0] = 0.0; 3049 pcbddc->adaptive_threshold[1] = 0.0; 3050 3051 /* function pointers */ 3052 pc->ops->apply = PCApply_BDDC; 3053 pc->ops->applytranspose = PCApplyTranspose_BDDC; 3054 pc->ops->setup = PCSetUp_BDDC; 3055 pc->ops->destroy = PCDestroy_BDDC; 3056 pc->ops->setfromoptions = PCSetFromOptions_BDDC; 3057 pc->ops->view = PCView_BDDC; 3058 pc->ops->applyrichardson = NULL; 3059 pc->ops->applysymmetricleft = NULL; 3060 pc->ops->applysymmetricright = NULL; 3061 pc->ops->presolve = PCPreSolve_BDDC; 3062 pc->ops->postsolve = PCPostSolve_BDDC; 3063 pc->ops->reset = PCReset_BDDC; 3064 3065 /* composing function */ 3066 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr); 3067 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr); 3068 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr); 3069 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr); 3070 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr); 3071 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr); 3072 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC);CHKERRQ(ierr); 3073 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr); 3074 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr); 3075 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr); 3076 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr); 3077 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr); 3078 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 3079 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr); 3080 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 3081 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr); 3082 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 3083 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr); 3084 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 3085 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr); 3086 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr); 3087 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr); 3088 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr); 3089 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr); 3090 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr); 3091 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr); 3092 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr); 3093 PetscFunctionReturn(0); 3094 } 3095 3096 /*@C 3097 PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called 3098 from PCInitializePackage(). 3099 3100 Level: developer 3101 3102 .seealso: PetscInitialize() 3103 @*/ 3104 PetscErrorCode PCBDDCInitializePackage(void) 3105 { 3106 PetscErrorCode ierr; 3107 int i; 3108 3109 PetscFunctionBegin; 3110 if (PCBDDCPackageInitialized) PetscFunctionReturn(0); 3111 PCBDDCPackageInitialized = PETSC_TRUE; 3112 ierr = PetscRegisterFinalize(PCBDDCFinalizePackage);CHKERRQ(ierr); 3113 3114 /* general events */ 3115 ierr = PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]);CHKERRQ(ierr); 3116 ierr = PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]);CHKERRQ(ierr); 3117 ierr = PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]);CHKERRQ(ierr); 3118 ierr = PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]);CHKERRQ(ierr); 3119 ierr = PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]);CHKERRQ(ierr); 3120 ierr = PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]);CHKERRQ(ierr); 3121 ierr = PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]);CHKERRQ(ierr); 3122 ierr = PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]);CHKERRQ(ierr); 3123 ierr = PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]);CHKERRQ(ierr); 3124 ierr = PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]);CHKERRQ(ierr); 3125 ierr = PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]);CHKERRQ(ierr); 3126 ierr = PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0]);CHKERRQ(ierr); 3127 ierr = PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1]);CHKERRQ(ierr); 3128 ierr = PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2]);CHKERRQ(ierr); 3129 for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) { 3130 char ename[32]; 3131 3132 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i);CHKERRQ(ierr); 3133 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]);CHKERRQ(ierr); 3134 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i);CHKERRQ(ierr); 3135 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]);CHKERRQ(ierr); 3136 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i);CHKERRQ(ierr); 3137 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]);CHKERRQ(ierr); 3138 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i);CHKERRQ(ierr); 3139 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]);CHKERRQ(ierr); 3140 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i);CHKERRQ(ierr); 3141 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]);CHKERRQ(ierr); 3142 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i);CHKERRQ(ierr); 3143 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]);CHKERRQ(ierr); 3144 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i);CHKERRQ(ierr); 3145 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]);CHKERRQ(ierr); 3146 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i);CHKERRQ(ierr); 3147 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]);CHKERRQ(ierr); 3148 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i);CHKERRQ(ierr); 3149 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]);CHKERRQ(ierr); 3150 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i);CHKERRQ(ierr); 3151 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]);CHKERRQ(ierr); 3152 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i);CHKERRQ(ierr); 3153 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]);CHKERRQ(ierr); 3154 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i);CHKERRQ(ierr); 3155 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0]);CHKERRQ(ierr); 3156 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i);CHKERRQ(ierr); 3157 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1]);CHKERRQ(ierr); 3158 ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i);CHKERRQ(ierr); 3159 ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2]);CHKERRQ(ierr); 3160 } 3161 PetscFunctionReturn(0); 3162 } 3163 3164 /*@C 3165 PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is 3166 called from PetscFinalize() automatically. 3167 3168 Level: developer 3169 3170 .seealso: PetscFinalize() 3171 @*/ 3172 PetscErrorCode PCBDDCFinalizePackage(void) 3173 { 3174 PetscFunctionBegin; 3175 PCBDDCPackageInitialized = PETSC_FALSE; 3176 PetscFunctionReturn(0); 3177 } 3178