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 if (pcbddc->switch_static || (!iscg && !ischeby && !isgroppcg && !ispipecg && !ispipecgrr)) { 1196 ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr); 1197 } 1198 } 1199 /* Creates parallel work vectors used in presolve */ 1200 if (!pcbddc->original_rhs) { 1201 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr); 1202 } 1203 if (!pcbddc->temp_solution) { 1204 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr); 1205 } 1206 1207 pcbddc->temp_solution_used = PETSC_FALSE; 1208 if (x) { 1209 ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr); 1210 used_vec = x; 1211 } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 1212 ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr); 1213 used_vec = pcbddc->temp_solution; 1214 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 1215 pcbddc->temp_solution_used = PETSC_TRUE; 1216 } 1217 1218 /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 1219 if (ksp) { 1220 /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 1221 ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 1222 if (!pcbddc->ksp_guess_nonzero) { 1223 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 1224 } 1225 } 1226 1227 pcbddc->rhs_change = PETSC_FALSE; 1228 /* Take into account zeroed rows -> change rhs and store solution removed */ 1229 if (rhs && pcbddc->eliminate_dirdofs) { 1230 IS dirIS = NULL; 1231 1232 /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 1233 ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr); 1234 if (dirIS) { 1235 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 1236 PetscInt dirsize,i,*is_indices; 1237 PetscScalar *array_x; 1238 const PetscScalar *array_diagonal; 1239 1240 ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr); 1241 ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr); 1242 ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1243 ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1244 ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1245 ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1246 ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr); 1247 ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 1248 ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 1249 ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 1250 for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 1251 ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 1252 ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 1253 ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 1254 ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1255 ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1256 pcbddc->rhs_change = PETSC_TRUE; 1257 ierr = ISDestroy(&dirIS);CHKERRQ(ierr); 1258 } 1259 } 1260 1261 /* remove the computed solution or the initial guess from the rhs */ 1262 if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) { 1263 /* save the original rhs */ 1264 if (save_rhs) { 1265 ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1266 save_rhs = PETSC_FALSE; 1267 } 1268 pcbddc->rhs_change = PETSC_TRUE; 1269 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1270 ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr); 1271 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1272 ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr); 1273 pcbddc->temp_solution_used = PETSC_TRUE; 1274 if (ksp) { 1275 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr); 1276 } 1277 } 1278 ierr = VecDestroy(&used_vec);CHKERRQ(ierr); 1279 1280 /* compute initial vector in benign space if needed (TODO: FETI-DP is untested) 1281 and remove non-benign solution from the rhs */ 1282 benign_correction_computed = PETSC_FALSE; 1283 if (rhs && pcbddc->benign_compute_correction && pcbddc->benign_have_null) { 1284 /* compute u^*_h as in Xuemin Tu's thesis (see Section 4.8.1) */ 1285 if (!pcbddc->benign_vec) { 1286 ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr); 1287 } 1288 pcbddc->benign_apply_coarse_only = PETSC_TRUE; 1289 if (!pcbddc->benign_skip_correction) { 1290 ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr); 1291 /* store the original rhs if not done earlier */ 1292 if (save_rhs) { 1293 ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1294 save_rhs = PETSC_FALSE; 1295 } 1296 benign_correction_computed = PETSC_TRUE; 1297 if (pcbddc->temp_solution_used) { 1298 ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr); 1299 } 1300 ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr); 1301 if (pcbddc->rhs_change) { 1302 ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr); 1303 } else { 1304 ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr); 1305 } 1306 pcbddc->rhs_change = PETSC_TRUE; 1307 } 1308 pcbddc->benign_apply_coarse_only = PETSC_FALSE; 1309 } 1310 1311 /* set initial guess if using PCG */ 1312 if (x && pcbddc->use_exact_dirichlet_trick) { 1313 ierr = VecSet(x,0.0);CHKERRQ(ierr); 1314 if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 1315 if (benign_correction_computed) { /* we have already saved the changed rhs */ 1316 ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr); 1317 } else { 1318 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr); 1319 } 1320 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1321 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1322 } else { 1323 ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1324 ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1325 } 1326 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1327 if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 1328 ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr); 1329 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1330 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1331 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr); 1332 } else { 1333 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1334 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1335 } 1336 if (ksp) { 1337 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 1338 } 1339 } 1340 PetscFunctionReturn(0); 1341 } 1342 1343 /* -------------------------------------------------------------------------- */ 1344 #undef __FUNCT__ 1345 #define __FUNCT__ "PCPostSolve_BDDC" 1346 /* -------------------------------------------------------------------------- */ 1347 /* 1348 PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1349 approach has been selected. Also, restores rhs to its original state. 1350 1351 Input Parameter: 1352 + pc - the preconditioner contex 1353 1354 Application Interface Routine: PCPostSolve() 1355 1356 Notes: 1357 The interface routine PCPostSolve() is not usually called directly by 1358 the user, but instead is called by KSPSolve(). 1359 */ 1360 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1361 { 1362 PetscErrorCode ierr; 1363 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1364 1365 PetscFunctionBegin; 1366 /* add solution removed in presolve */ 1367 if (x && pcbddc->rhs_change) { 1368 if (pcbddc->temp_solution_used) { 1369 ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr); 1370 } else if (pcbddc->benign_compute_correction) { 1371 ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr); 1372 } 1373 } 1374 pcbddc->temp_solution_used = PETSC_FALSE; 1375 1376 /* restore rhs to its original state */ 1377 if (rhs && pcbddc->rhs_change) { 1378 ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1379 } 1380 pcbddc->rhs_change = PETSC_FALSE; 1381 /* restore ksp guess state */ 1382 if (ksp) { 1383 ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 1384 } 1385 PetscFunctionReturn(0); 1386 } 1387 /* -------------------------------------------------------------------------- */ 1388 #undef __FUNCT__ 1389 #define __FUNCT__ "PCSetUp_BDDC" 1390 /* -------------------------------------------------------------------------- */ 1391 /* 1392 PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 1393 by setting data structures and options. 1394 1395 Input Parameter: 1396 + pc - the preconditioner context 1397 1398 Application Interface Routine: PCSetUp() 1399 1400 Notes: 1401 The interface routine PCSetUp() is not usually called directly by 1402 the user, but instead is called by PCApply() if necessary. 1403 */ 1404 PetscErrorCode PCSetUp_BDDC(PC pc) 1405 { 1406 PetscErrorCode ierr; 1407 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 1408 Mat_IS* matis; 1409 MatNullSpace nearnullspace; 1410 IS zerodiag = NULL; 1411 PetscInt nrows,ncols; 1412 PetscBool computetopography,computesolvers,computesubschurs; 1413 PetscBool computeconstraintsmatrix; 1414 PetscBool new_nearnullspace_provided,ismatis; 1415 1416 PetscFunctionBegin; 1417 ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr); 1418 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS"); 1419 ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr); 1420 if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix"); 1421 matis = (Mat_IS*)pc->pmat->data; 1422 /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 1423 /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 1424 Also, BDDC directly build the Dirichlet problem */ 1425 /* split work */ 1426 if (pc->setupcalled) { 1427 if (pc->flag == SAME_NONZERO_PATTERN) { 1428 computetopography = PETSC_FALSE; 1429 computesolvers = PETSC_TRUE; 1430 } else { /* DIFFERENT_NONZERO_PATTERN */ 1431 computetopography = PETSC_TRUE; 1432 computesolvers = PETSC_TRUE; 1433 } 1434 } else { 1435 computetopography = PETSC_TRUE; 1436 computesolvers = PETSC_TRUE; 1437 } 1438 if (pcbddc->recompute_topography) { 1439 computetopography = PETSC_TRUE; 1440 } 1441 pcbddc->recompute_topography = computetopography; 1442 computeconstraintsmatrix = PETSC_FALSE; 1443 1444 /* check parameters' compatibility */ 1445 if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE; 1446 pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0); 1447 pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined); 1448 if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1449 1450 computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 1451 if (pcbddc->switch_static) { 1452 PetscBool ismatis; 1453 ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr); 1454 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"When the static switch is one, the iteration matrix should be of type MATIS"); 1455 } 1456 1457 /* Get stdout for dbg */ 1458 if (pcbddc->dbg_flag) { 1459 if (!pcbddc->dbg_viewer) { 1460 pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 1461 ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr); 1462 } 1463 ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1464 } 1465 1466 if (pcbddc->user_ChangeOfBasisMatrix) { 1467 /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 1468 pcbddc->use_change_of_basis = PETSC_FALSE; 1469 ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr); 1470 } else { 1471 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1472 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1473 pcbddc->local_mat = matis->A; 1474 } 1475 1476 /* detect local disconnected subdomains if requested and not done before */ 1477 if (pcbddc->detect_disconnected && !pcbddc->n_local_subs) { 1478 ierr = MatDetectDisconnectedComponents(pcbddc->local_mat,PETSC_FALSE,&pcbddc->n_local_subs,&pcbddc->local_subs);CHKERRQ(ierr); 1479 } 1480 1481 /* 1482 Compute change of basis on local pressures (aka zerodiag dofs) 1483 This should come earlier then PCISSetUp for extracting the correct subdomain matrices 1484 */ 1485 ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr); 1486 if (pcbddc->benign_saddle_point) { 1487 PC_IS* pcis = (PC_IS*)pc->data; 1488 1489 if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE; 1490 /* detect local saddle point and change the basis in pcbddc->local_mat */ 1491 ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr); 1492 /* pop B0 mat from local mat */ 1493 ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr); 1494 /* give pcis a hint to not reuse submatrices during PCISCreate */ 1495 if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) { 1496 if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) { 1497 pcis->reusesubmatrices = PETSC_FALSE; 1498 } else { 1499 pcis->reusesubmatrices = PETSC_TRUE; 1500 } 1501 } else { 1502 pcis->reusesubmatrices = PETSC_FALSE; 1503 } 1504 } 1505 1506 /* propagate relevant information */ 1507 #if !defined(PETSC_USE_COMPLEX) /* workaround for reals */ 1508 if (matis->A->symmetric_set) { 1509 ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr); 1510 } 1511 #endif 1512 if (matis->A->symmetric_set) { 1513 ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr); 1514 } 1515 if (matis->A->spd_set) { 1516 ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr); 1517 } 1518 1519 /* Set up all the "iterative substructuring" common block without computing solvers */ 1520 { 1521 Mat temp_mat; 1522 1523 temp_mat = matis->A; 1524 matis->A = pcbddc->local_mat; 1525 ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr); 1526 pcbddc->local_mat = matis->A; 1527 matis->A = temp_mat; 1528 } 1529 1530 /* Analyze interface */ 1531 if (computetopography) { 1532 ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr); 1533 computeconstraintsmatrix = PETSC_TRUE; 1534 if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) { 1535 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling"); 1536 } 1537 } 1538 1539 /* check existence of a divergence free extension, i.e. 1540 b(v_I,p_0) = 0 for all v_I (raise error if not). 1541 Also, check that PCBDDCBenignGetOrSetP0 works */ 1542 #if defined(PETSC_USE_DEBUG) 1543 if (pcbddc->benign_saddle_point) { 1544 ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr); 1545 } 1546 #endif 1547 ierr = ISDestroy(&zerodiag);CHKERRQ(ierr); 1548 1549 /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 1550 if (computesolvers) { 1551 PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs; 1552 1553 if (computesubschurs && computetopography) { 1554 ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr); 1555 } 1556 /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/ 1557 if (!pcbddc->use_deluxe_scaling) { 1558 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 1559 } 1560 if (sub_schurs->schur_explicit) { 1561 if (computesubschurs) { 1562 ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr); 1563 } 1564 ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1565 } else { 1566 ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1567 if (computesubschurs) { 1568 ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr); 1569 } 1570 } 1571 if (pcbddc->adaptive_selection) { 1572 ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr); 1573 computeconstraintsmatrix = PETSC_TRUE; 1574 } 1575 } 1576 1577 /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1578 new_nearnullspace_provided = PETSC_FALSE; 1579 ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr); 1580 if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1581 if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1582 new_nearnullspace_provided = PETSC_TRUE; 1583 } else { 1584 /* determine if the two nullspaces are different (should be lightweight) */ 1585 if (nearnullspace != pcbddc->onearnullspace) { 1586 new_nearnullspace_provided = PETSC_TRUE; 1587 } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1588 PetscInt i; 1589 const Vec *nearnullvecs; 1590 PetscObjectState state; 1591 PetscInt nnsp_size; 1592 ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr); 1593 for (i=0;i<nnsp_size;i++) { 1594 ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr); 1595 if (pcbddc->onearnullvecs_state[i] != state) { 1596 new_nearnullspace_provided = PETSC_TRUE; 1597 break; 1598 } 1599 } 1600 } 1601 } 1602 } else { 1603 if (!nearnullspace) { /* both nearnullspaces are null */ 1604 new_nearnullspace_provided = PETSC_FALSE; 1605 } else { /* nearnullspace attached later */ 1606 new_nearnullspace_provided = PETSC_TRUE; 1607 } 1608 } 1609 1610 /* Setup constraints and related work vectors */ 1611 /* reset primal space flags */ 1612 pcbddc->new_primal_space = PETSC_FALSE; 1613 pcbddc->new_primal_space_local = PETSC_FALSE; 1614 if (computeconstraintsmatrix || new_nearnullspace_provided) { 1615 /* It also sets the primal space flags */ 1616 ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr); 1617 /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 1618 ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr); 1619 } 1620 1621 if (computesolvers || pcbddc->new_primal_space) { 1622 if (pcbddc->use_change_of_basis) { 1623 PC_IS *pcis = (PC_IS*)(pc->data); 1624 1625 ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr); 1626 if (pcbddc->benign_change) { 1627 ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr); 1628 /* pop B0 from pcbddc->local_mat */ 1629 ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr); 1630 } 1631 /* get submatrices */ 1632 ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr); 1633 ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr); 1634 ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr); 1635 ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr); 1636 ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr); 1637 ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr); 1638 /* set flag in pcis to not reuse submatrices during PCISCreate */ 1639 pcis->reusesubmatrices = PETSC_FALSE; 1640 } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) { 1641 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1642 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1643 pcbddc->local_mat = matis->A; 1644 } 1645 /* SetUp coarse and local Neumann solvers */ 1646 ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr); 1647 /* SetUp Scaling operator */ 1648 if (pcbddc->use_deluxe_scaling) { 1649 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 1650 } 1651 } 1652 /* mark topography as done */ 1653 pcbddc->recompute_topography = PETSC_FALSE; 1654 1655 /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */ 1656 ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr); 1657 1658 if (pcbddc->dbg_flag) { 1659 ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1660 } 1661 PetscFunctionReturn(0); 1662 } 1663 1664 /* -------------------------------------------------------------------------- */ 1665 /* 1666 PCApply_BDDC - Applies the BDDC operator to a vector. 1667 1668 Input Parameters: 1669 + pc - the preconditioner context 1670 - r - input vector (global) 1671 1672 Output Parameter: 1673 . z - output vector (global) 1674 1675 Application Interface Routine: PCApply() 1676 */ 1677 #undef __FUNCT__ 1678 #define __FUNCT__ "PCApply_BDDC" 1679 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 1680 { 1681 PC_IS *pcis = (PC_IS*)(pc->data); 1682 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1683 PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 1684 PetscErrorCode ierr; 1685 const PetscScalar one = 1.0; 1686 const PetscScalar m_one = -1.0; 1687 const PetscScalar zero = 0.0; 1688 1689 /* This code is similar to that provided in nn.c for PCNN 1690 NN interface preconditioner changed to BDDC 1691 Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 1692 1693 PetscFunctionBegin; 1694 if (pcbddc->ChangeOfBasisMatrix) { 1695 Vec swap; 1696 1697 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr); 1698 swap = pcbddc->work_change; 1699 pcbddc->work_change = r; 1700 r = swap; 1701 /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 1702 if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 1703 ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr); 1704 ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr); 1705 } 1706 } 1707 if (pcbddc->benign_have_null) { /* get p0 from r */ 1708 ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr); 1709 } 1710 if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) { 1711 ierr = VecCopy(r,z);CHKERRQ(ierr); 1712 /* First Dirichlet solve */ 1713 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1714 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1715 /* 1716 Assembling right hand side for BDDC operator 1717 - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1718 - pcis->vec1_B the interface part of the global vector z 1719 */ 1720 if (n_D) { 1721 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1722 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1723 if (pcbddc->switch_static) { 1724 Mat_IS *matis = (Mat_IS*)(pc->mat->data); 1725 1726 ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr); 1727 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1728 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1729 if (!pcbddc->switch_static_change) { 1730 ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1731 } else { 1732 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1733 ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 1734 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1735 } 1736 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1737 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1738 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1739 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1740 } else { 1741 ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1742 } 1743 } else { 1744 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 1745 } 1746 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1747 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1748 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1749 } else { 1750 if (!pcbddc->benign_apply_coarse_only) { 1751 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1752 } 1753 } 1754 1755 /* Apply interface preconditioner 1756 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1757 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr); 1758 1759 /* Apply transpose of partition of unity operator */ 1760 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1761 1762 /* Second Dirichlet solve and assembling of output */ 1763 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1764 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1765 if (n_B) { 1766 if (pcbddc->switch_static) { 1767 Mat_IS *matis = (Mat_IS*)(pc->mat->data); 1768 1769 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1770 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1771 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1772 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1773 if (!pcbddc->switch_static_change) { 1774 ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1775 } else { 1776 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1777 ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 1778 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1779 } 1780 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1781 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1782 } else { 1783 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1784 } 1785 } else if (pcbddc->switch_static) { /* n_B is zero */ 1786 Mat_IS *matis = (Mat_IS*)(pc->mat->data); 1787 1788 if (!pcbddc->switch_static_change) { 1789 ierr = MatMult(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr); 1790 } else { 1791 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr); 1792 ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1793 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr); 1794 } 1795 } 1796 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1797 1798 if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) { 1799 if (pcbddc->switch_static) { 1800 ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr); 1801 } else { 1802 ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr); 1803 } 1804 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1805 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1806 } else { 1807 if (pcbddc->switch_static) { 1808 ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr); 1809 } else { 1810 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1811 } 1812 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1813 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1814 } 1815 1816 if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 1817 if (pcbddc->benign_apply_coarse_only) { 1818 ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr); 1819 } 1820 ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr); 1821 } 1822 if (pcbddc->ChangeOfBasisMatrix) { 1823 Vec swap; 1824 1825 swap = r; 1826 r = pcbddc->work_change; 1827 pcbddc->work_change = swap; 1828 ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr); 1829 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr); 1830 } 1831 PetscFunctionReturn(0); 1832 } 1833 1834 /* -------------------------------------------------------------------------- */ 1835 /* 1836 PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 1837 1838 Input Parameters: 1839 + pc - the preconditioner context 1840 - r - input vector (global) 1841 1842 Output Parameter: 1843 . z - output vector (global) 1844 1845 Application Interface Routine: PCApplyTranspose() 1846 */ 1847 #undef __FUNCT__ 1848 #define __FUNCT__ "PCApplyTranspose_BDDC" 1849 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z) 1850 { 1851 PC_IS *pcis = (PC_IS*)(pc->data); 1852 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1853 PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 1854 PetscErrorCode ierr; 1855 const PetscScalar one = 1.0; 1856 const PetscScalar m_one = -1.0; 1857 const PetscScalar zero = 0.0; 1858 1859 PetscFunctionBegin; 1860 if (pcbddc->ChangeOfBasisMatrix) { 1861 Vec swap; 1862 1863 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr); 1864 swap = pcbddc->work_change; 1865 pcbddc->work_change = r; 1866 r = swap; 1867 /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 1868 if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 1869 ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr); 1870 ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr); 1871 } 1872 } 1873 if (pcbddc->benign_have_null) { /* get p0 from r */ 1874 ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr); 1875 } 1876 if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) { 1877 ierr = VecCopy(r,z);CHKERRQ(ierr); 1878 /* First Dirichlet solve */ 1879 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1880 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1881 /* 1882 Assembling right hand side for BDDC operator 1883 - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1884 - pcis->vec1_B the interface part of the global vector z 1885 */ 1886 if (n_D) { 1887 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1888 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1889 if (pcbddc->switch_static) { 1890 Mat_IS *matis = (Mat_IS*)(pc->mat->data); 1891 1892 ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr); 1893 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1894 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1895 if (!pcbddc->switch_static_change) { 1896 ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1897 } else { 1898 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1899 ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 1900 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1901 } 1902 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1903 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1904 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1905 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1906 } else { 1907 ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1908 } 1909 } else { 1910 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 1911 } 1912 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1913 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1914 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1915 } else { 1916 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1917 } 1918 1919 /* Apply interface preconditioner 1920 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1921 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr); 1922 1923 /* Apply transpose of partition of unity operator */ 1924 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1925 1926 /* Second Dirichlet solve and assembling of output */ 1927 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1928 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1929 if (n_B) { 1930 if (pcbddc->switch_static) { 1931 Mat_IS *matis = (Mat_IS*)(pc->mat->data); 1932 1933 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1934 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1935 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1936 ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1937 if (!pcbddc->switch_static_change) { 1938 ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1939 } else { 1940 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1941 ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr); 1942 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1943 } 1944 ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1945 ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1946 } else { 1947 ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1948 } 1949 } else if (pcbddc->switch_static) { /* n_B is zero */ 1950 Mat_IS *matis = (Mat_IS*)(pc->mat->data); 1951 1952 if (!pcbddc->switch_static_change) { 1953 ierr = MatMultTranspose(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr); 1954 } else { 1955 ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr); 1956 ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1957 ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr); 1958 } 1959 } 1960 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1961 if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) { 1962 if (pcbddc->switch_static) { 1963 ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr); 1964 } else { 1965 ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr); 1966 } 1967 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1968 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1969 } else { 1970 if (pcbddc->switch_static) { 1971 ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr); 1972 } else { 1973 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1974 } 1975 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1976 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1977 } 1978 if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 1979 ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr); 1980 } 1981 if (pcbddc->ChangeOfBasisMatrix) { 1982 Vec swap; 1983 1984 swap = r; 1985 r = pcbddc->work_change; 1986 pcbddc->work_change = swap; 1987 ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr); 1988 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr); 1989 } 1990 PetscFunctionReturn(0); 1991 } 1992 /* -------------------------------------------------------------------------- */ 1993 1994 #undef __FUNCT__ 1995 #define __FUNCT__ "PCDestroy_BDDC" 1996 PetscErrorCode PCDestroy_BDDC(PC pc) 1997 { 1998 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1999 PetscErrorCode ierr; 2000 2001 PetscFunctionBegin; 2002 /* free BDDC custom data */ 2003 ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr); 2004 /* destroy objects related to topography */ 2005 ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr); 2006 /* free allocated graph structure */ 2007 ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr); 2008 /* free allocated sub schurs structure */ 2009 ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr); 2010 /* destroy objects for scaling operator */ 2011 ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr); 2012 ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr); 2013 /* free solvers stuff */ 2014 ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr); 2015 /* free global vectors needed in presolve */ 2016 ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr); 2017 ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr); 2018 /* free data created by PCIS */ 2019 ierr = PCISDestroy(pc);CHKERRQ(ierr); 2020 /* remove functions */ 2021 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr); 2022 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr); 2023 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr); 2024 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr); 2025 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr); 2026 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr); 2027 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr); 2028 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr); 2029 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 2030 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 2031 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 2032 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 2033 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 2034 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 2035 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 2036 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 2037 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr); 2038 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr); 2039 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr); 2040 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr); 2041 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr); 2042 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr); 2043 /* Free the private data structure */ 2044 ierr = PetscFree(pc->data);CHKERRQ(ierr); 2045 PetscFunctionReturn(0); 2046 } 2047 /* -------------------------------------------------------------------------- */ 2048 2049 #undef __FUNCT__ 2050 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC" 2051 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2052 { 2053 FETIDPMat_ctx mat_ctx; 2054 Vec copy_standard_rhs; 2055 PC_IS* pcis; 2056 PC_BDDC* pcbddc; 2057 PetscErrorCode ierr; 2058 2059 PetscFunctionBegin; 2060 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2061 pcis = (PC_IS*)mat_ctx->pc->data; 2062 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 2063 2064 /* 2065 change of basis for physical rhs if needed 2066 It also changes the rhs in case of dirichlet boundaries 2067 TODO: better management when FETIDP will have its own class 2068 */ 2069 ierr = VecDuplicate(standard_rhs,©_standard_rhs);CHKERRQ(ierr); 2070 ierr = VecCopy(standard_rhs,copy_standard_rhs);CHKERRQ(ierr); 2071 ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,copy_standard_rhs,NULL);CHKERRQ(ierr); 2072 /* store vectors for computation of fetidp final solution */ 2073 ierr = VecScatterBegin(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2074 ierr = VecScatterEnd(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2075 /* scale rhs since it should be unassembled */ 2076 /* TODO use counter scaling? (also below) */ 2077 ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2078 ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2079 /* Apply partition of unity */ 2080 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 2081 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 2082 if (!pcbddc->switch_static) { 2083 /* compute partially subassembled Schur complement right-hand side */ 2084 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 2085 ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr); 2086 ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr); 2087 ierr = VecSet(copy_standard_rhs,0.0);CHKERRQ(ierr); 2088 ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2089 ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2090 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 2091 ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2092 ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2093 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 2094 } 2095 ierr = VecDestroy(©_standard_rhs);CHKERRQ(ierr); 2096 /* BDDC rhs */ 2097 ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr); 2098 if (pcbddc->switch_static) { 2099 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 2100 } 2101 /* apply BDDC */ 2102 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 2103 /* Application of B_delta and assembling of rhs for fetidp fluxes */ 2104 ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr); 2105 ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr); 2106 ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2107 ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2108 PetscFunctionReturn(0); 2109 } 2110 2111 #undef __FUNCT__ 2112 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS" 2113 /*@ 2114 PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side 2115 2116 Collective 2117 2118 Input Parameters: 2119 + fetidp_mat - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators 2120 - standard_rhs - the right-hand side of the original linear system 2121 2122 Output Parameters: 2123 . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 2124 2125 Level: developer 2126 2127 Notes: 2128 2129 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution 2130 @*/ 2131 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2132 { 2133 FETIDPMat_ctx mat_ctx; 2134 PetscErrorCode ierr; 2135 2136 PetscFunctionBegin; 2137 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2138 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr); 2139 PetscFunctionReturn(0); 2140 } 2141 /* -------------------------------------------------------------------------- */ 2142 2143 #undef __FUNCT__ 2144 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC" 2145 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2146 { 2147 FETIDPMat_ctx mat_ctx; 2148 PC_IS* pcis; 2149 PC_BDDC* pcbddc; 2150 PetscErrorCode ierr; 2151 2152 PetscFunctionBegin; 2153 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2154 pcis = (PC_IS*)mat_ctx->pc->data; 2155 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 2156 2157 /* apply B_delta^T */ 2158 ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2159 ierr = VecScatterEnd (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2160 ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr); 2161 /* compute rhs for BDDC application */ 2162 ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr); 2163 if (pcbddc->switch_static) { 2164 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 2165 } 2166 /* apply BDDC */ 2167 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 2168 /* put values into standard global vector */ 2169 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2170 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2171 if (!pcbddc->switch_static) { 2172 /* compute values into the interior if solved for the partially subassembled Schur complement */ 2173 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr); 2174 ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr); 2175 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 2176 } 2177 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2178 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2179 /* final change of basis if needed 2180 Is also sums the dirichlet part removed during RHS assembling */ 2181 ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr); 2182 PetscFunctionReturn(0); 2183 } 2184 2185 #undef __FUNCT__ 2186 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution" 2187 /*@ 2188 PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 2189 2190 Collective 2191 2192 Input Parameters: 2193 + fetidp_mat - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators 2194 - fetidp_flux_sol - the solution of the FETI-DP linear system 2195 2196 Output Parameters: 2197 . standard_sol - the solution defined on the physical domain 2198 2199 Level: developer 2200 2201 Notes: 2202 2203 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS 2204 @*/ 2205 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2206 { 2207 FETIDPMat_ctx mat_ctx; 2208 PetscErrorCode ierr; 2209 2210 PetscFunctionBegin; 2211 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 2212 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr); 2213 PetscFunctionReturn(0); 2214 } 2215 /* -------------------------------------------------------------------------- */ 2216 2217 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec); 2218 extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec); 2219 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat); 2220 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec); 2221 extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec); 2222 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC); 2223 2224 #undef __FUNCT__ 2225 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC" 2226 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 2227 { 2228 2229 FETIDPMat_ctx fetidpmat_ctx; 2230 Mat newmat; 2231 FETIDPPC_ctx fetidppc_ctx; 2232 PC newpc; 2233 MPI_Comm comm; 2234 PetscErrorCode ierr; 2235 2236 PetscFunctionBegin; 2237 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 2238 /* FETIDP linear matrix */ 2239 ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr); 2240 ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr); 2241 ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr); 2242 ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr); 2243 ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr); 2244 ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr); 2245 ierr = MatSetUp(newmat);CHKERRQ(ierr); 2246 /* FETIDP preconditioner */ 2247 ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr); 2248 ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr); 2249 ierr = PCCreate(comm,&newpc);CHKERRQ(ierr); 2250 ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr); 2251 ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr); 2252 ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr); 2253 ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr); 2254 ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr); 2255 ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr); 2256 ierr = PCSetUp(newpc);CHKERRQ(ierr); 2257 /* return pointers for objects created */ 2258 *fetidp_mat=newmat; 2259 *fetidp_pc=newpc; 2260 PetscFunctionReturn(0); 2261 } 2262 2263 #undef __FUNCT__ 2264 #define __FUNCT__ "PCBDDCCreateFETIDPOperators" 2265 /*@ 2266 PCBDDCCreateFETIDPOperators - Create FETI-DP operators 2267 2268 Collective 2269 2270 Input Parameters: 2271 . pc - the BDDC preconditioning context (setup should have been called before) 2272 2273 Output Parameters: 2274 + fetidp_mat - shell FETI-DP matrix object 2275 - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 2276 2277 Options Database Keys: 2278 . -fetidp_fullyredundant <false> - use or not a fully redundant set of Lagrange multipliers 2279 2280 Level: developer 2281 2282 Notes: 2283 Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose 2284 2285 .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution 2286 @*/ 2287 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 2288 { 2289 PetscErrorCode ierr; 2290 2291 PetscFunctionBegin; 2292 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 2293 if (pc->setupcalled) { 2294 ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr); 2295 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n"); 2296 PetscFunctionReturn(0); 2297 } 2298 /* -------------------------------------------------------------------------- */ 2299 /*MC 2300 PCBDDC - Balancing Domain Decomposition by Constraints. 2301 2302 An implementation of the BDDC preconditioner based on 2303 2304 .vb 2305 [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007 2306 [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 2307 [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977 2308 [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 2309 .ve 2310 2311 The matrix to be preconditioned (Pmat) must be of type MATIS. 2312 2313 Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 2314 2315 It also works with unsymmetric and indefinite problems. 2316 2317 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. 2318 2319 Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace() 2320 2321 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() 2322 Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts. 2323 2324 Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD. 2325 2326 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. 2327 User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat() 2328 2329 The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object. 2330 2331 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. 2332 2333 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. 2334 Deluxe scaling is not supported yet for FETI-DP. 2335 2336 Options Database Keys (some of them, run with -h for a complete list): 2337 2338 . -pc_bddc_use_vertices <true> - use or not vertices in primal space 2339 . -pc_bddc_use_edges <true> - use or not edges in primal space 2340 . -pc_bddc_use_faces <false> - use or not faces in primal space 2341 . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 2342 . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 2343 . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 2344 . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 2345 . -pc_bddc_levels <0> - maximum number of levels for multilevel 2346 . -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) 2347 . -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) 2348 . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 2349 . -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) 2350 . -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) 2351 - -pc_bddc_check_level <0> - set verbosity level of debugging output 2352 2353 Options for Dirichlet, Neumann or coarse solver can be set with 2354 .vb 2355 -pc_bddc_dirichlet_ 2356 -pc_bddc_neumann_ 2357 -pc_bddc_coarse_ 2358 .ve 2359 e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU. 2360 2361 When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as 2362 .vb 2363 -pc_bddc_dirichlet_lN_ 2364 -pc_bddc_neumann_lN_ 2365 -pc_bddc_coarse_lN_ 2366 .ve 2367 Note that level number ranges from the finest (0) to the coarsest (N). 2368 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. 2369 .vb 2370 -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 2371 .ve 2372 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 2373 2374 Level: intermediate 2375 2376 Developer notes: 2377 2378 Contributed by Stefano Zampini 2379 2380 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 2381 M*/ 2382 2383 #undef __FUNCT__ 2384 #define __FUNCT__ "PCCreate_BDDC" 2385 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 2386 { 2387 PetscErrorCode ierr; 2388 PC_BDDC *pcbddc; 2389 2390 PetscFunctionBegin; 2391 /* Creates the private data structure for this preconditioner and attach it to the PC object. */ 2392 ierr = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr); 2393 pc->data = (void*)pcbddc; 2394 2395 /* create PCIS data structure */ 2396 ierr = PCISCreate(pc);CHKERRQ(ierr); 2397 2398 /* BDDC customization */ 2399 pcbddc->use_local_adj = PETSC_TRUE; 2400 pcbddc->use_vertices = PETSC_TRUE; 2401 pcbddc->use_edges = PETSC_TRUE; 2402 pcbddc->use_faces = PETSC_FALSE; 2403 pcbddc->use_change_of_basis = PETSC_FALSE; 2404 pcbddc->use_change_on_faces = PETSC_FALSE; 2405 pcbddc->switch_static = PETSC_FALSE; 2406 pcbddc->use_nnsp_true = PETSC_FALSE; 2407 pcbddc->use_qr_single = PETSC_FALSE; 2408 pcbddc->symmetric_primal = PETSC_TRUE; 2409 pcbddc->benign_saddle_point = PETSC_FALSE; 2410 pcbddc->benign_have_null = PETSC_FALSE; 2411 pcbddc->vertex_size = 1; 2412 pcbddc->dbg_flag = 0; 2413 /* private */ 2414 pcbddc->local_primal_size = 0; 2415 pcbddc->local_primal_size_cc = 0; 2416 pcbddc->local_primal_ref_node = 0; 2417 pcbddc->local_primal_ref_mult = 0; 2418 pcbddc->n_vertices = 0; 2419 pcbddc->primal_indices_local_idxs = 0; 2420 pcbddc->recompute_topography = PETSC_FALSE; 2421 pcbddc->coarse_size = -1; 2422 pcbddc->new_primal_space = PETSC_FALSE; 2423 pcbddc->new_primal_space_local = PETSC_FALSE; 2424 pcbddc->global_primal_indices = 0; 2425 pcbddc->onearnullspace = 0; 2426 pcbddc->onearnullvecs_state = 0; 2427 pcbddc->user_primal_vertices = 0; 2428 pcbddc->user_primal_vertices_local = 0; 2429 pcbddc->NullSpace = 0; 2430 pcbddc->temp_solution = 0; 2431 pcbddc->original_rhs = 0; 2432 pcbddc->local_mat = 0; 2433 pcbddc->ChangeOfBasisMatrix = 0; 2434 pcbddc->user_ChangeOfBasisMatrix = 0; 2435 pcbddc->coarse_vec = 0; 2436 pcbddc->coarse_ksp = 0; 2437 pcbddc->coarse_phi_B = 0; 2438 pcbddc->coarse_phi_D = 0; 2439 pcbddc->coarse_psi_B = 0; 2440 pcbddc->coarse_psi_D = 0; 2441 pcbddc->vec1_P = 0; 2442 pcbddc->vec1_R = 0; 2443 pcbddc->vec2_R = 0; 2444 pcbddc->local_auxmat1 = 0; 2445 pcbddc->local_auxmat2 = 0; 2446 pcbddc->R_to_B = 0; 2447 pcbddc->R_to_D = 0; 2448 pcbddc->ksp_D = 0; 2449 pcbddc->ksp_R = 0; 2450 pcbddc->NeumannBoundaries = 0; 2451 pcbddc->NeumannBoundariesLocal = 0; 2452 pcbddc->DirichletBoundaries = 0; 2453 pcbddc->DirichletBoundariesLocal = 0; 2454 pcbddc->user_provided_isfordofs = PETSC_FALSE; 2455 pcbddc->n_ISForDofs = 0; 2456 pcbddc->n_ISForDofsLocal = 0; 2457 pcbddc->ISForDofs = 0; 2458 pcbddc->ISForDofsLocal = 0; 2459 pcbddc->ConstraintMatrix = 0; 2460 pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 2461 pcbddc->coarse_loc_to_glob = 0; 2462 pcbddc->coarsening_ratio = 8; 2463 pcbddc->coarse_adj_red = 0; 2464 pcbddc->current_level = 0; 2465 pcbddc->max_levels = 0; 2466 pcbddc->use_coarse_estimates = PETSC_FALSE; 2467 pcbddc->coarse_eqs_per_proc = 1; 2468 pcbddc->coarse_subassembling = 0; 2469 pcbddc->detect_disconnected = PETSC_FALSE; 2470 pcbddc->n_local_subs = 0; 2471 pcbddc->local_subs = NULL; 2472 2473 /* benign subspace trick */ 2474 pcbddc->benign_change = 0; 2475 pcbddc->benign_compute_correction = PETSC_TRUE; 2476 pcbddc->benign_vec = 0; 2477 pcbddc->benign_original_mat = 0; 2478 pcbddc->benign_sf = 0; 2479 pcbddc->benign_B0 = 0; 2480 pcbddc->benign_n = 0; 2481 pcbddc->benign_p0 = NULL; 2482 pcbddc->benign_p0_lidx = NULL; 2483 pcbddc->benign_p0_gidx = NULL; 2484 pcbddc->benign_null = PETSC_FALSE; 2485 2486 /* create local graph structure */ 2487 ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr); 2488 2489 /* scaling */ 2490 pcbddc->work_scaling = 0; 2491 pcbddc->use_deluxe_scaling = PETSC_FALSE; 2492 2493 /* create sub schurs structure */ 2494 ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr); 2495 pcbddc->sub_schurs_rebuild = PETSC_FALSE; 2496 pcbddc->sub_schurs_layers = -1; 2497 pcbddc->sub_schurs_use_useradj = PETSC_FALSE; 2498 2499 pcbddc->computed_rowadj = PETSC_FALSE; 2500 2501 /* adaptivity */ 2502 pcbddc->adaptive_threshold = 0.0; 2503 pcbddc->adaptive_nmax = 0; 2504 pcbddc->adaptive_nmin = 0; 2505 2506 /* function pointers */ 2507 pc->ops->apply = PCApply_BDDC; 2508 pc->ops->applytranspose = PCApplyTranspose_BDDC; 2509 pc->ops->setup = PCSetUp_BDDC; 2510 pc->ops->destroy = PCDestroy_BDDC; 2511 pc->ops->setfromoptions = PCSetFromOptions_BDDC; 2512 pc->ops->view = PCView_BDDC; 2513 pc->ops->applyrichardson = 0; 2514 pc->ops->applysymmetricleft = 0; 2515 pc->ops->applysymmetricright = 0; 2516 pc->ops->presolve = PCPreSolve_BDDC; 2517 pc->ops->postsolve = PCPostSolve_BDDC; 2518 2519 /* composing function */ 2520 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr); 2521 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr); 2522 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr); 2523 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr); 2524 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr); 2525 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr); 2526 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr); 2527 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr); 2528 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr); 2529 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 2530 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr); 2531 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 2532 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr); 2533 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 2534 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr); 2535 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 2536 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr); 2537 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr); 2538 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr); 2539 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr); 2540 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr); 2541 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr); 2542 PetscFunctionReturn(0); 2543 } 2544 2545