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