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