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