1 /* TODOLIST 2 remove // commments 3 remove coarse enums -> allows use of PCBDDCGetCoarseKSP 4 code refactoring 5 remove metis dependency -> use MatPartitioning for multilevel 6 analyze MatSetNearNullSpace as suggested by Jed 7 options structure 8 */ 9 10 /* ---------------------------------------------------------------------------------------------------------------------------------------------- 11 Implementation of BDDC preconditioner based on: 12 C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007 13 ---------------------------------------------------------------------------------------------------------------------------------------------- */ 14 15 #include "bddc.h" /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 16 17 /* -------------------------------------------------------------------------- */ 18 #undef __FUNCT__ 19 #define __FUNCT__ "PCSetFromOptions_BDDC" 20 PetscErrorCode PCSetFromOptions_BDDC(PC pc) 21 { 22 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 23 PetscErrorCode ierr; 24 25 PetscFunctionBegin; 26 ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr); 27 /* Verbose debugging of main data structures */ 28 ierr = PetscOptionsBool("-pc_bddc_check_all" ,"Verbose (debugging) output for PCBDDC" ,"none",pcbddc->check_flag ,&pcbddc->check_flag ,PETSC_NULL);CHKERRQ(ierr); 29 /* Some customization for default primal space */ 30 ierr = PetscOptionsBool("-pc_bddc_vertices_only" ,"Use vertices only in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag ,&pcbddc->vertices_flag ,PETSC_NULL);CHKERRQ(ierr); 31 ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use constraints only in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr); 32 ierr = PetscOptionsBool("-pc_bddc_faces_only" ,"Use faces only in coarse space (i.e. discard edges)" ,"none",pcbddc->faces_flag ,&pcbddc->faces_flag ,PETSC_NULL);CHKERRQ(ierr); 33 ierr = PetscOptionsBool("-pc_bddc_edges_only" ,"Use edges only in coarse space (i.e. discard faces)" ,"none",pcbddc->edges_flag ,&pcbddc->edges_flag ,PETSC_NULL);CHKERRQ(ierr); 34 /* Coarse solver context */ 35 static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h 36 ierr = PetscOptionsEnum("-pc_bddc_coarse_problem_type","Set coarse problem type","none",avail_coarse_problems,(PetscEnum)pcbddc->coarse_problem_type,(PetscEnum*)&pcbddc->coarse_problem_type,PETSC_NULL);CHKERRQ(ierr); 37 /* Two different application of BDDC to the whole set of dofs, internal and interface */ 38 ierr = PetscOptionsBool("-pc_bddc_switch_preconditioning_type","Switch between M_2 (default) and M_3 preconditioners (as defined by Dohrmann)","none",pcbddc->prec_type,&pcbddc->prec_type,PETSC_NULL);CHKERRQ(ierr); 39 ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,PETSC_NULL);CHKERRQ(ierr); 40 ierr = PetscOptionsTail();CHKERRQ(ierr); 41 PetscFunctionReturn(0); 42 } 43 44 /* -------------------------------------------------------------------------- */ 45 EXTERN_C_BEGIN 46 #undef __FUNCT__ 47 #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC" 48 static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT) 49 { 50 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 51 52 PetscFunctionBegin; 53 pcbddc->coarse_problem_type = CPT; 54 PetscFunctionReturn(0); 55 } 56 EXTERN_C_END 57 58 /* -------------------------------------------------------------------------- */ 59 #undef __FUNCT__ 60 #define __FUNCT__ "PCBDDCSetCoarseProblemType" 61 /*@ 62 PCBDDCSetCoarseProblemType - brief explanation 63 64 Collective on PC 65 66 Input Parameters: 67 + pc - the preconditioning context 68 - CoarseProblemType - pick a better name and explain what this is 69 70 Level: intermediate 71 72 Notes: 73 usage notes, perhaps an example 74 75 .seealso: PCBDDC 76 @*/ 77 PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT) 78 { 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 83 ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr); 84 PetscFunctionReturn(0); 85 } 86 87 /* -------------------------------------------------------------------------- */ 88 EXTERN_C_BEGIN 89 #undef __FUNCT__ 90 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC" 91 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries) 92 { 93 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 94 PetscErrorCode ierr; 95 96 PetscFunctionBegin; 97 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 98 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 99 ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 100 ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr); 101 PetscFunctionReturn(0); 102 } 103 EXTERN_C_END 104 105 /* -------------------------------------------------------------------------- */ 106 #undef __FUNCT__ 107 #define __FUNCT__ "PCBDDCSetNeumannBoundaries" 108 /*@ 109 PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of 110 Neumann boundaries for the global problem. 111 112 Logically Collective on PC 113 114 Input Parameters: 115 + pc - the preconditioning context 116 - NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 117 118 Level: intermediate 119 120 Notes: 121 usage notes, perhaps an example 122 123 .seealso: PCBDDC 124 @*/ 125 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries) 126 { 127 PetscErrorCode ierr; 128 129 PetscFunctionBegin; 130 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 131 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 132 PetscFunctionReturn(0); 133 } 134 /* -------------------------------------------------------------------------- */ 135 EXTERN_C_BEGIN 136 #undef __FUNCT__ 137 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC" 138 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries) 139 { 140 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 141 142 PetscFunctionBegin; 143 if(pcbddc->NeumannBoundaries) { 144 *NeumannBoundaries = pcbddc->NeumannBoundaries; 145 } else { 146 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__); 147 } 148 PetscFunctionReturn(0); 149 } 150 EXTERN_C_END 151 152 /* -------------------------------------------------------------------------- */ 153 #undef __FUNCT__ 154 #define __FUNCT__ "PCBDDCGetNeumannBoundaries" 155 /*@ 156 PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of 157 Neumann boundaries for the global problem. 158 159 Logically Collective on PC 160 161 Input Parameters: 162 + pc - the preconditioning context 163 164 Output Parameters: 165 + NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 166 167 Level: intermediate 168 169 Notes: 170 usage notes, perhaps an example 171 172 .seealso: PCBDDC 173 @*/ 174 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries) 175 { 176 PetscErrorCode ierr; 177 178 PetscFunctionBegin; 179 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 180 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 181 PetscFunctionReturn(0); 182 } 183 184 #undef __FUNCT__ 185 #define __FUNCT__ "PCSetUp_BDDC" 186 /* -------------------------------------------------------------------------- */ 187 /* 188 PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 189 by setting data structures and options. 190 191 Input Parameter: 192 + pc - the preconditioner context 193 194 Application Interface Routine: PCSetUp() 195 196 Notes: 197 The interface routine PCSetUp() is not usually called directly by 198 the user, but instead is called by PCApply() if necessary. 199 */ 200 PetscErrorCode PCSetUp_BDDC(PC pc) 201 { 202 PetscErrorCode ierr; 203 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 204 PC_IS *pcis = (PC_IS*)(pc->data); 205 206 PetscFunctionBegin; 207 if (!pc->setupcalled) { 208 209 /* For BDDC we need to define a local "Neumann" to that defined in PCISSetup 210 So, we set to pcnone the Neumann problem of pcid in order to avoid unneeded computation 211 Also, we decide to directly build the (same) Dirichlet problem */ 212 ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr); 213 ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr); 214 /* Set up all the "iterative substructuring" common block */ 215 ierr = PCISSetUp(pc);CHKERRQ(ierr); 216 /* Destroy some PC_IS data which is not needed by BDDC */ 217 //if (pcis->ksp_D) {ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);} 218 //if (pcis->ksp_N) {ierr = KSPDestroy(&pcis->ksp_N);CHKERRQ(ierr);} 219 //if (pcis->vec2_B) {ierr = VecDestroy(&pcis->vec2_B);CHKERRQ(ierr);} 220 //if (pcis->vec3_B) {ierr = VecDestroy(&pcis->vec3_B);CHKERRQ(ierr);} 221 //pcis->ksp_D = 0; 222 //pcis->ksp_N = 0; 223 //pcis->vec2_B = 0; 224 //pcis->vec3_B = 0; 225 226 //TODO MOVE CODE FRAGMENT 227 PetscInt im_active=0; 228 if(pcis->n) im_active = 1; 229 ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr); 230 //printf("Calling PCBDDC MANAGE with active procs %d (im_active = %d)\n",pcbddc->active_procs,im_active); 231 /* Set up grid quantities for BDDC */ 232 //TODO only active procs must call this -> remove synchronized print inside (the only point of sync) 233 ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr); 234 235 /* Create coarse and local stuffs used for evaluating action of preconditioner */ 236 ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr); 237 238 if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE; //processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo 239 /* We no more need this matrix */ 240 //if (pcis->A_BB) {ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);} 241 //pcis->A_BB = 0; 242 243 //printf("Using coarse problem type %d\n",pcbddc->coarse_problem_type); 244 //printf("Using coarse communications type %d\n",pcbddc->coarse_communications_type); 245 //printf("Using coarsening ratio %d\n",pcbddc->coarsening_ratio); 246 } 247 248 PetscFunctionReturn(0); 249 } 250 251 /* -------------------------------------------------------------------------- */ 252 /* 253 PCApply_BDDC - Applies the BDDC preconditioner to a vector. 254 255 Input Parameters: 256 . pc - the preconditioner context 257 . r - input vector (global) 258 259 Output Parameter: 260 . z - output vector (global) 261 262 Application Interface Routine: PCApply() 263 */ 264 #undef __FUNCT__ 265 #define __FUNCT__ "PCApply_BDDC" 266 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 267 { 268 PC_IS *pcis = (PC_IS*)(pc->data); 269 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 270 PetscErrorCode ierr; 271 PetscScalar one = 1.0; 272 PetscScalar m_one = -1.0; 273 274 /* This code is similar to that provided in nn.c for PCNN 275 NN interface preconditioner changed to BDDC 276 Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */ 277 278 PetscFunctionBegin; 279 /* First Dirichlet solve */ 280 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 281 ierr = VecScatterEnd (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 282 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 283 /* 284 Assembling right hand side for BDDC operator 285 - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE) 286 - the interface part of the global vector z 287 */ 288 //ierr = VecScatterBegin(pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 289 //ierr = VecScatterEnd (pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 290 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 291 ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 292 //ierr = MatMultAdd(pcis->A_BI,pcis->vec2_D,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr); 293 if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 294 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 295 ierr = VecCopy(r,z);CHKERRQ(ierr); 296 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 297 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 298 299 /* 300 Apply interface preconditioner 301 Results are stored in: 302 - vec1_D (if needed, i.e. with prec_type = PETSC_TRUE) 303 - the interface part of the global vector z 304 */ 305 ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr); 306 307 /* Second Dirichlet solves and assembling of output */ 308 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 309 ierr = VecScatterEnd (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 310 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 311 if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 312 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr); 313 ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr); 314 if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); } 315 ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr); 316 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 317 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 318 319 PetscFunctionReturn(0); 320 321 } 322 323 /* -------------------------------------------------------------------------- */ 324 /* 325 PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface. 326 327 */ 328 #undef __FUNCT__ 329 #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner" 330 static PetscErrorCode PCBDDCApplyInterfacePreconditioner(PC pc, Vec z) 331 { 332 PetscErrorCode ierr; 333 PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 334 PC_IS* pcis = (PC_IS*) (pc->data); 335 PetscScalar zero = 0.0; 336 337 PetscFunctionBegin; 338 /* Get Local boundary and apply partition of unity */ 339 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 340 ierr = VecScatterEnd (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 341 ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr); 342 343 /* Application of PHI^T */ 344 ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr); 345 if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); } 346 347 /* Scatter data of coarse_rhs */ 348 if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr); 349 ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 350 351 /* Local solution on R nodes */ 352 ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr); 353 ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 354 ierr = VecScatterEnd (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 355 if(pcbddc->prec_type) { 356 ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 357 ierr = VecScatterEnd (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 358 } 359 ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr); 360 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 361 ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 362 ierr = VecScatterEnd (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 363 if(pcbddc->prec_type) { 364 ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 365 ierr = VecScatterEnd (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 366 } 367 368 /* Coarse solution */ 369 ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 370 if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr); 371 ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 372 ierr = PCBDDCScatterCoarseDataEnd (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 373 374 /* Sum contributions from two levels */ 375 /* Apply partition of unity and sum boundary values */ 376 ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr); 377 ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr); 378 if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 379 ierr = VecSet(z,zero);CHKERRQ(ierr); 380 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 381 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 382 383 PetscFunctionReturn(0); 384 } 385 386 387 /* -------------------------------------------------------------------------- */ 388 /* 389 PCBDDCSolveSaddlePoint 390 391 */ 392 #undef __FUNCT__ 393 #define __FUNCT__ "PCBDDCSolveSaddlePoint" 394 static PetscErrorCode PCBDDCSolveSaddlePoint(PC pc) 395 { 396 PetscErrorCode ierr; 397 PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 398 399 PetscFunctionBegin; 400 401 ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr); 402 if(pcbddc->n_constraints) { 403 ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr); 404 ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr); 405 } 406 407 PetscFunctionReturn(0); 408 } 409 /* -------------------------------------------------------------------------- */ 410 /* 411 PCBDDCScatterCoarseDataBegin 412 413 */ 414 #undef __FUNCT__ 415 #define __FUNCT__ "PCBDDCScatterCoarseDataBegin" 416 static PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode) 417 { 418 PetscErrorCode ierr; 419 PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 420 421 PetscFunctionBegin; 422 423 switch(pcbddc->coarse_communications_type){ 424 case SCATTERS_BDDC: 425 ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr); 426 break; 427 case GATHERS_BDDC: 428 break; 429 } 430 PetscFunctionReturn(0); 431 432 } 433 /* -------------------------------------------------------------------------- */ 434 /* 435 PCBDDCScatterCoarseDataEnd 436 437 */ 438 #undef __FUNCT__ 439 #define __FUNCT__ "PCBDDCScatterCoarseDataEnd" 440 static PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode) 441 { 442 PetscErrorCode ierr; 443 PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); 444 PetscScalar* array_to; 445 PetscScalar* array_from; 446 MPI_Comm comm=((PetscObject)pc)->comm; 447 PetscInt i; 448 449 PetscFunctionBegin; 450 451 switch(pcbddc->coarse_communications_type){ 452 case SCATTERS_BDDC: 453 ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr); 454 break; 455 case GATHERS_BDDC: 456 if(vec_from) VecGetArray(vec_from,&array_from); 457 if(vec_to) VecGetArray(vec_to,&array_to); 458 switch(pcbddc->coarse_problem_type){ 459 case SEQUENTIAL_BDDC: 460 if(smode == SCATTER_FORWARD) { 461 ierr = MPI_Gatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,0,comm);CHKERRQ(ierr); 462 if(vec_to) { 463 for(i=0;i<pcbddc->replicated_primal_size;i++) 464 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i]; 465 } 466 } else { 467 if(vec_from) 468 for(i=0;i<pcbddc->replicated_primal_size;i++) 469 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]]; 470 ierr = MPI_Scatterv(&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,&array_to[0],pcbddc->local_primal_size,MPIU_SCALAR,0,comm);CHKERRQ(ierr); 471 } 472 break; 473 case REPLICATED_BDDC: 474 if(smode == SCATTER_FORWARD) { 475 ierr = MPI_Allgatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,comm);CHKERRQ(ierr); 476 for(i=0;i<pcbddc->replicated_primal_size;i++) 477 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i]; 478 } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */ 479 for(i=0;i<pcbddc->local_primal_size;i++) 480 array_to[i]=array_from[pcbddc->local_primal_indices[i]]; 481 } 482 break; 483 case MULTILEVEL_BDDC: 484 break; 485 case PARALLEL_BDDC: 486 break; 487 } 488 if(vec_from) VecRestoreArray(vec_from,&array_from); 489 if(vec_to) VecRestoreArray(vec_to,&array_to); 490 break; 491 } 492 PetscFunctionReturn(0); 493 494 } 495 496 /* -------------------------------------------------------------------------- */ 497 /* 498 PCDestroy_BDDC - Destroys the private context for the NN preconditioner 499 that was created with PCCreate_BDDC(). 500 501 Input Parameter: 502 . pc - the preconditioner context 503 504 Application Interface Routine: PCDestroy() 505 */ 506 #undef __FUNCT__ 507 #define __FUNCT__ "PCDestroy_BDDC" 508 PetscErrorCode PCDestroy_BDDC(PC pc) 509 { 510 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 511 PetscErrorCode ierr; 512 513 PetscFunctionBegin; 514 /* free data created by PCIS */ 515 ierr = PCISDestroy(pc);CHKERRQ(ierr); 516 /* free BDDC data */ 517 ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr); 518 ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr); 519 ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr); 520 ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr); 521 ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr); 522 ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr); 523 ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr); 524 ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr); 525 ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr); 526 ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr); 527 ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr); 528 ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr); 529 ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr); 530 ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr); 531 ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr); 532 ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr); 533 ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr); 534 ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr); 535 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 536 ierr = PetscFree(pcbddc->vertices);CHKERRQ(ierr); 537 ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr); 538 ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr); 539 if (pcbddc->replicated_local_primal_values) { free(pcbddc->replicated_local_primal_values); } 540 ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr); 541 ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr); 542 if (pcbddc->n_constraints) { 543 ierr = PetscFree(pcbddc->indices_to_constraint[0]);CHKERRQ(ierr); 544 ierr = PetscFree(pcbddc->indices_to_constraint);CHKERRQ(ierr); 545 ierr = PetscFree(pcbddc->quadrature_constraint[0]);CHKERRQ(ierr); 546 ierr = PetscFree(pcbddc->quadrature_constraint);CHKERRQ(ierr); 547 ierr = PetscFree(pcbddc->sizes_of_constraint);CHKERRQ(ierr); 548 } 549 /* Free the private data structure that was hanging off the PC */ 550 ierr = PetscFree(pcbddc);CHKERRQ(ierr); 551 PetscFunctionReturn(0); 552 } 553 554 /* -------------------------------------------------------------------------- */ 555 /*MC 556 PCBDDC - Balancing Domain Decomposition by Constraints. 557 558 Options Database Keys: 559 . -pc_is_damp_fixed <fact> - 560 . -pc_is_remove_nullspace_fixed - 561 . -pc_is_set_damping_factor_floating <fact> - 562 . -pc_is_not_damp_floating - 563 564 Level: intermediate 565 566 Notes: The matrix used with this preconditioner must be of type MATIS 567 568 Unlike more 'conventional' interface preconditioners, this iterates over ALL the 569 degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers 570 on the subdomains). 571 572 Options for the coarse grid preconditioner can be set with -pc_bddc_coarse_pc_xxx 573 Options for the Dirichlet subproblem can be set with -pc_bddc_localD_xxx 574 Options for the Neumann subproblem can be set with -pc_bddc_localN_xxx 575 576 Contributed by Stefano Zampini 577 578 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 579 M*/ 580 EXTERN_C_BEGIN 581 #undef __FUNCT__ 582 #define __FUNCT__ "PCCreate_BDDC" 583 PetscErrorCode PCCreate_BDDC(PC pc) 584 { 585 PetscErrorCode ierr; 586 PC_BDDC *pcbddc; 587 588 PetscFunctionBegin; 589 /* Creates the private data structure for this preconditioner and attach it to the PC object. */ 590 ierr = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr); 591 pc->data = (void*)pcbddc; 592 /* create PCIS data structure */ 593 ierr = PCISCreate(pc);CHKERRQ(ierr); 594 /* BDDC specific */ 595 pcbddc->coarse_vec = 0; 596 pcbddc->coarse_rhs = 0; 597 pcbddc->coarse_ksp = 0; 598 pcbddc->coarse_phi_B = 0; 599 pcbddc->coarse_phi_D = 0; 600 pcbddc->vec1_P = 0; 601 pcbddc->vec1_R = 0; 602 pcbddc->vec2_R = 0; 603 pcbddc->local_auxmat1 = 0; 604 pcbddc->local_auxmat2 = 0; 605 pcbddc->R_to_B = 0; 606 pcbddc->R_to_D = 0; 607 pcbddc->ksp_D = 0; 608 pcbddc->ksp_R = 0; 609 pcbddc->n_constraints = 0; 610 pcbddc->n_vertices = 0; 611 pcbddc->vertices = 0; 612 pcbddc->indices_to_constraint = 0; 613 pcbddc->quadrature_constraint = 0; 614 pcbddc->sizes_of_constraint = 0; 615 pcbddc->local_primal_indices = 0; 616 pcbddc->prec_type = PETSC_FALSE; 617 pcbddc->NeumannBoundaries = 0; 618 pcbddc->local_primal_sizes = 0; 619 pcbddc->local_primal_displacements = 0; 620 pcbddc->replicated_local_primal_indices = 0; 621 pcbddc->replicated_local_primal_values = 0; 622 pcbddc->coarse_loc_to_glob = 0; 623 pcbddc->check_flag = PETSC_FALSE; 624 pcbddc->vertices_flag = PETSC_FALSE; 625 pcbddc->constraints_flag = PETSC_FALSE; 626 pcbddc->faces_flag = PETSC_FALSE; 627 pcbddc->edges_flag = PETSC_FALSE; 628 pcbddc->coarsening_ratio = 8; 629 /* function pointers */ 630 pc->ops->apply = PCApply_BDDC; 631 pc->ops->applytranspose = 0; 632 pc->ops->setup = PCSetUp_BDDC; 633 pc->ops->destroy = PCDestroy_BDDC; 634 pc->ops->setfromoptions = PCSetFromOptions_BDDC; 635 pc->ops->view = 0; 636 pc->ops->applyrichardson = 0; 637 pc->ops->applysymmetricleft = 0; 638 pc->ops->applysymmetricright = 0; 639 /* composing function */ 640 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC", 641 PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr); 642 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC", 643 PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr); 644 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC", 645 PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr); 646 PetscFunctionReturn(0); 647 } 648 EXTERN_C_END 649 650 /* -------------------------------------------------------------------------- */ 651 /* 652 PCBDDCCoarseSetUp - 653 */ 654 #undef __FUNCT__ 655 #define __FUNCT__ "PCBDDCCoarseSetUp" 656 static PetscErrorCode PCBDDCCoarseSetUp(PC pc) 657 { 658 PetscErrorCode ierr; 659 660 PC_IS* pcis = (PC_IS*)(pc->data); 661 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 662 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 663 IS is_R_local; 664 IS is_V_local; 665 IS is_C_local; 666 IS is_aux1; 667 IS is_aux2; 668 PetscViewer viewer; 669 PetscBool check_flag=pcbddc->check_flag; 670 const VecType impVecType; 671 const MatType impMatType; 672 PetscInt n_R=0; 673 PetscInt n_D=0; 674 PetscInt n_B=0; 675 PetscMPIInt totprocs; 676 PetscScalar zero=0.0; 677 PetscScalar one=1.0; 678 PetscScalar m_one=-1.0; 679 PetscScalar* array; 680 PetscScalar *coarse_submat_vals; 681 PetscInt *idx_R_local; 682 PetscInt *idx_V_B; 683 PetscScalar *coarsefunctions_errors; 684 PetscScalar *constraints_errors; 685 /* auxiliary indices */ 686 PetscInt s,i,j,k; 687 688 PetscFunctionBegin; 689 if(pcbddc->check_flag) { 690 ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);CHKERRQ(ierr); 691 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 692 } 693 694 /* Set Non-overlapping dimensions */ 695 n_B = pcis->n_B; n_D = pcis->n - n_B; 696 /* Set local primal size */ 697 pcbddc->local_primal_size = pcbddc->n_vertices + pcbddc->n_constraints; 698 /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */ 699 ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr); 700 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 701 for (i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = zero; } 702 ierr = PetscMalloc(( pcis->n - pcbddc->n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr); 703 for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } } 704 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 705 if(check_flag) { 706 ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr); 707 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 708 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr); 709 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr); 710 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,pcbddc->n_vertices,pcbddc->n_constraints,pcbddc->local_primal_size);CHKERRQ(ierr); 711 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 712 } 713 /* Allocate needed vectors */ 714 /* Set Mat type for local matrices needed by BDDC precondtioner */ 715 // ierr = MatGetType(matis->A,&impMatType);CHKERRQ(ierr); 716 //ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr); 717 impMatType = MATSEQDENSE; 718 impVecType = VECSEQ; 719 ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr); 720 ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr); 721 ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr); 722 ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr); 723 ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr); 724 ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr); 725 ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr); 726 ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr); 727 ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr); 728 729 /* Creating some index sets needed */ 730 /* For submatrices */ 731 ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr); 732 if(pcbddc->n_vertices) { ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr); } 733 if(pcbddc->n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,pcbddc->n_vertices,1,&is_C_local);CHKERRQ(ierr); } 734 /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */ 735 { 736 PetscInt *aux_array1; 737 PetscInt *aux_array2; 738 PetscScalar value; 739 740 ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr); 741 ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr); 742 743 ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr); 744 ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 745 ierr = VecScatterEnd (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 746 ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 747 ierr = VecScatterEnd (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 748 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 749 ierr = VecScatterEnd (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 750 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 751 for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } } 752 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 753 ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr); 754 ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr); 755 for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } } 756 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 757 ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr); 758 ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr); 759 ierr = PetscFree(aux_array1);CHKERRQ(ierr); 760 ierr = PetscFree(aux_array2);CHKERRQ(ierr); 761 ierr = ISDestroy(&is_aux1);CHKERRQ(ierr); 762 ierr = ISDestroy(&is_aux2);CHKERRQ(ierr); 763 764 if(pcbddc->prec_type || check_flag ) { 765 ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr); 766 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 767 for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } } 768 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 769 ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr); 770 ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr); 771 ierr = PetscFree(aux_array1);CHKERRQ(ierr); 772 ierr = ISDestroy(&is_aux1);CHKERRQ(ierr); 773 } 774 775 /* Check scatters */ 776 if(check_flag) { 777 778 Vec vec_aux; 779 780 ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr); 781 ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr); 782 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 783 ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr); 784 ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr); 785 ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr); 786 ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr); 787 ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 788 ierr = VecScatterEnd (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 789 ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 790 ierr = VecScatterEnd (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 791 ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr); 792 ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr); 793 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr); 794 ierr = VecDestroy(&vec_aux);CHKERRQ(ierr); 795 796 ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr); 797 ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr); 798 ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr); 799 ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr); 800 ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 801 ierr = VecScatterEnd (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 802 ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 803 ierr = VecScatterEnd (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 804 ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr); 805 ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr); 806 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr); 807 ierr = VecDestroy(&vec_aux);CHKERRQ(ierr); 808 809 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 810 ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr); 811 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 812 813 ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr); 814 ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr); 815 ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr); 816 ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr); 817 ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 818 ierr = VecScatterEnd (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 819 ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 820 ierr = VecScatterEnd (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 821 ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr); 822 ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr); 823 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr); 824 ierr = VecDestroy(&vec_aux);CHKERRQ(ierr); 825 826 ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr); 827 ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr); 828 ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr); 829 ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr); 830 ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 831 ierr = VecScatterEnd (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 832 ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 833 ierr = VecScatterEnd (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 834 ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr); 835 ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr); 836 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr); 837 ierr = VecDestroy(&vec_aux);CHKERRQ(ierr); 838 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 839 840 } 841 } 842 843 /* vertices in boundary numbering */ 844 if(pcbddc->n_vertices) { 845 ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr); 846 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 847 for (i=0; i<pcbddc->n_vertices; i++) { array[ pcbddc->vertices[i] ] = i; } 848 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 849 ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 850 ierr = VecScatterEnd (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 851 ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr); 852 ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr); 853 //printf("vertices in boundary numbering\n"); 854 for (i=0; i<pcbddc->n_vertices; i++) { 855 s=0; 856 while (array[s] != i ) {s++;} 857 idx_V_B[i]=s; 858 //printf("idx_V_B[%d]=%d\n",i,s); 859 } 860 ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr); 861 } 862 863 864 /* Creating PC contexts for local Dirichlet and Neumann problems */ 865 { 866 Mat A_RR; 867 PC pc_temp; 868 /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */ 869 ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr); 870 ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr); 871 ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr); 872 ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr); 873 //ierr = KSPSetOptionsPrefix(pcbddc->pc_D,"pc_bddc_localD_");CHKERRQ(ierr); 874 /* default */ 875 ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr); 876 ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr); 877 /* Allow user's customization */ 878 ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr); 879 /* Set Up KSP for Dirichlet problem of BDDC */ 880 ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr); 881 /* Matrix for Neumann problem is A_RR -> we need to create it */ 882 ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr); 883 ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr); 884 ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr); 885 ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr); 886 ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr); 887 //ierr = PCSetOptionsPrefix(pcbddc->pc_R,"pc_bddc_localN_");CHKERRQ(ierr); 888 /* default */ 889 ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr); 890 ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr); 891 /* Allow user's customization */ 892 ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr); 893 /* Set Up KSP for Neumann problem of BDDC */ 894 ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr); 895 /* check Neumann solve */ 896 if(pcbddc->check_flag) { 897 Vec temp_vec; 898 PetscScalar value; 899 900 ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr); 901 ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr); 902 ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr); 903 ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr); 904 ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr); 905 ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr); 906 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 907 ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr); 908 ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Neumann problem\n");CHKERRQ(ierr); 909 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Neumann solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr); 910 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 911 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 912 } 913 /* free Neumann problem's matrix */ 914 ierr = MatDestroy(&A_RR);CHKERRQ(ierr); 915 } 916 917 /* Assemble all remaining stuff needed to apply BDDC */ 918 { 919 Mat A_RV,A_VR,A_VV; 920 Mat M1,M2; 921 Mat C_CR; 922 Mat CMAT,AUXMAT; 923 Vec vec1_C; 924 Vec vec2_C; 925 Vec vec1_V; 926 Vec vec2_V; 927 PetscInt *nnz; 928 PetscInt *auxindices; 929 PetscInt index; 930 PetscScalar* array2; 931 MatFactorInfo matinfo; 932 933 /* Allocating some extra storage just to be safe */ 934 ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr); 935 ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr); 936 for(i=0;i<pcis->n;i++) {auxindices[i]=i;} 937 938 /* some work vectors on vertices and/or constraints */ 939 if(pcbddc->n_vertices) { 940 ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr); 941 ierr = VecSetSizes(vec1_V,pcbddc->n_vertices,pcbddc->n_vertices);CHKERRQ(ierr); 942 ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr); 943 ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr); 944 } 945 if(pcbddc->n_constraints) { 946 ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr); 947 ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr); 948 ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr); 949 ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr); 950 ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr); 951 } 952 /* Create C matrix [I 0; 0 const] */ 953 ierr = MatCreate(PETSC_COMM_SELF,&CMAT);CHKERRQ(ierr); 954 ierr = MatSetType(CMAT,MATSEQAIJ);CHKERRQ(ierr); 955 ierr = MatSetSizes(CMAT,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr); 956 /* nonzeros */ 957 for(i=0;i<pcbddc->n_vertices;i++) { nnz[i]= 1; } 958 for(i=0;i<pcbddc->n_constraints;i++) { nnz[i+pcbddc->n_vertices]=pcbddc->sizes_of_constraint[i];} 959 ierr = MatSeqAIJSetPreallocation(CMAT,0,nnz);CHKERRQ(ierr); 960 for(i=0;i<pcbddc->n_vertices;i++) { 961 ierr = MatSetValue(CMAT,i,pcbddc->vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr); 962 } 963 for(i=0;i<pcbddc->n_constraints;i++) { 964 index=i+pcbddc->n_vertices; 965 ierr = MatSetValues(CMAT,1,&index,pcbddc->sizes_of_constraint[i],pcbddc->indices_to_constraint[i],pcbddc->quadrature_constraint[i],INSERT_VALUES);CHKERRQ(ierr); 966 } 967 //if(check_flag) printf("CMAT assembling\n"); 968 ierr = MatAssemblyBegin(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 969 ierr = MatAssemblyEnd(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 970 //ierr = MatView(CMAT,PETSC_VIEWER_STDOUT_SELF); 971 972 /* Precompute stuffs needed for preprocessing and application of BDDC*/ 973 974 if(pcbddc->n_constraints) { 975 /* some work vectors */ 976 ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr); 977 ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,pcbddc->n_constraints,n_R,pcbddc->n_constraints);CHKERRQ(ierr); 978 ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr); 979 980 /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */ 981 for(i=0;i<pcbddc->n_constraints;i++) { 982 ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr); 983 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 984 for(j=0;j<pcbddc->sizes_of_constraint[i];j++) { array[ pcbddc->indices_to_constraint[i][j] ] = - pcbddc->quadrature_constraint[i][j]; } 985 ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr); 986 for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; } 987 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 988 ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr); 989 ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr); 990 ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr); 991 index=i; 992 ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr); 993 ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr); 994 } 995 //if(check_flag) printf("pcbddc->local_auxmat2 assembling\n"); 996 ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 997 ierr = MatAssemblyEnd (pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 998 999 /* Create Constraint matrix on R nodes: C_{CR} */ 1000 ierr = MatGetSubMatrix(CMAT,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr); 1001 ierr = ISDestroy(&is_C_local);CHKERRQ(ierr); 1002 1003 /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */ 1004 ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr); 1005 ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr); 1006 ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,0,1,&is_aux1);CHKERRQ(ierr); 1007 ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr); 1008 ierr = ISDestroy(&is_aux1);CHKERRQ(ierr); 1009 1010 /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc (should be dense) */ 1011 ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr); 1012 ierr = MatSetSizes(M1,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr); 1013 ierr = MatSetType(M1,impMatType);CHKERRQ(ierr); 1014 for(i=0;i<pcbddc->n_constraints;i++) { 1015 ierr = VecSet(vec1_C,zero);CHKERRQ(ierr); 1016 ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr); 1017 ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr); 1018 ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr); 1019 ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr); 1020 ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr); 1021 ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr); 1022 index=i; 1023 ierr = MatSetValues(M1,pcbddc->n_constraints,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr); 1024 ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr); 1025 } 1026 //if(check_flag) printf("M1 assembling\n"); 1027 ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1028 ierr = MatAssemblyEnd (M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1029 ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr); 1030 /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */ 1031 //if(check_flag) printf("pcbddc->local_auxmat1 computing and assembling\n"); 1032 ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr); 1033 1034 } 1035 1036 /* Get submatrices from subdomain matrix */ 1037 if(pcbddc->n_vertices){ 1038 ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr); 1039 ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr); 1040 ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr); 1041 /* Assemble M2 = A_RR^{-1}A_RV */ 1042 ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr); 1043 ierr = MatSetSizes(M2,n_R,pcbddc->n_vertices,n_R,pcbddc->n_vertices);CHKERRQ(ierr); 1044 ierr = MatSetType(M2,impMatType);CHKERRQ(ierr); 1045 for(i=0;i<pcbddc->n_vertices;i++) { 1046 ierr = VecSet(vec1_V,zero);CHKERRQ(ierr); 1047 ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr); 1048 ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr); 1049 ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr); 1050 ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr); 1051 ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr); 1052 index=i; 1053 ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr); 1054 ierr = MatSetValues(M2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr); 1055 ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr); 1056 } 1057 //if(check_flag) printf("M2 assembling\n"); 1058 ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1059 ierr = MatAssemblyEnd (M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1060 } 1061 1062 /* Matrix of coarse basis functions (local) */ 1063 ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr); 1064 ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr); 1065 ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr); 1066 if(pcbddc->prec_type || check_flag ) { 1067 ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr); 1068 ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr); 1069 ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr); 1070 } 1071 1072 /* Subdomain contribution (Non-overlapping) to coarse matrix */ 1073 if(check_flag) { 1074 ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr); 1075 ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr); 1076 } 1077 ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr); 1078 1079 /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */ 1080 for(i=0;i<pcbddc->n_vertices;i++){ 1081 ierr = VecSet(vec1_V,zero);CHKERRQ(ierr); 1082 ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr); 1083 ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr); 1084 ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr); 1085 /* solution of saddle point problem */ 1086 ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr); 1087 ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr); 1088 if(pcbddc->n_constraints) { 1089 ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr); 1090 ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr); 1091 ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr); 1092 } 1093 ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); 1094 ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr); 1095 1096 /* Set values in coarse basis function and subdomain part of coarse_mat */ 1097 /* coarse basis functions */ 1098 index=i; 1099 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 1100 ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1101 ierr = VecScatterEnd (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1102 ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr); 1103 ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr); 1104 ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr); 1105 ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr); 1106 if( pcbddc->prec_type || check_flag ) { 1107 ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1108 ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1109 ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr); 1110 ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr); 1111 ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr); 1112 } 1113 /* subdomain contribution to coarse matrix */ 1114 ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr); 1115 for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering 1116 ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr); 1117 if( pcbddc->n_constraints) { 1118 ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr); 1119 for(j=0;j<pcbddc->n_constraints;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j+pcbddc->n_vertices]=array[j];} //WARNING -> column major ordering 1120 ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr); 1121 } 1122 1123 if( check_flag ) { 1124 /* assemble subdomain vector on nodes */ 1125 ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr); 1126 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1127 ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr); 1128 for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; } 1129 array[ pcbddc->vertices[i] ] = one; 1130 ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr); 1131 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1132 /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */ 1133 ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr); 1134 ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr); 1135 ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr); 1136 for(j=0;j<pcbddc->n_vertices;j++) { array2[j]=array[j]; } 1137 ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr); 1138 if(pcbddc->n_constraints) { 1139 ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr); 1140 for(j=0;j<pcbddc->n_constraints;j++) { array2[j+pcbddc->n_vertices]=array[j]; } 1141 ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr); 1142 } 1143 ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr); 1144 ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr); 1145 /* check saddle point solution */ 1146 ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1147 ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr); 1148 ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr); 1149 ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr); 1150 ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr); 1151 array[index]=array[index]+m_one; /* shift by the identity matrix */ 1152 ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr); 1153 ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr); 1154 } 1155 } 1156 1157 for(i=0;i<pcbddc->n_constraints;i++){ 1158 ierr = VecSet(vec2_C,zero);CHKERRQ(ierr); 1159 ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr); 1160 ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr); 1161 ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr); 1162 /* solution of saddle point problem */ 1163 ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr); 1164 ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr); 1165 ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr); 1166 if(pcbddc->n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); } 1167 /* Set values in coarse basis function and subdomain part of coarse_mat */ 1168 /* coarse basis functions */ 1169 index=i+pcbddc->n_vertices; 1170 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 1171 ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1172 ierr = VecScatterEnd (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1173 ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr); 1174 ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr); 1175 ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr); 1176 if( pcbddc->prec_type || check_flag ) { 1177 ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1178 ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1179 ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr); 1180 ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr); 1181 ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr); 1182 } 1183 /* subdomain contribution to coarse matrix */ 1184 if(pcbddc->n_vertices) { 1185 ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr); 1186 for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering 1187 ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr); 1188 } 1189 ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr); 1190 for(j=0;j<pcbddc->n_constraints;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j+pcbddc->n_vertices]=array[j];} //WARNING -> column major ordering 1191 ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr); 1192 1193 if( check_flag ) { 1194 /* assemble subdomain vector on nodes */ 1195 ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr); 1196 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1197 ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr); 1198 for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; } 1199 ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr); 1200 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1201 /* assemble subdomain vector of lagrange multipliers */ 1202 ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr); 1203 ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr); 1204 if( pcbddc->n_vertices) { 1205 ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr); 1206 for(j=0;j<pcbddc->n_vertices;j++) {array2[j]=-array[j];} 1207 ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr); 1208 } 1209 ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr); 1210 for(j=0;j<pcbddc->n_constraints;j++) {array2[j+pcbddc->n_vertices]=-array[j];} 1211 ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr); 1212 ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr); 1213 /* check saddle point solution */ 1214 ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1215 ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr); 1216 ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr); 1217 ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr); 1218 ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr); 1219 array[index]=array[index]+m_one; /* shift by the identity matrix */ 1220 ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr); 1221 ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr); 1222 } 1223 } 1224 ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1225 ierr = MatAssemblyEnd (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1226 if( pcbddc->prec_type || check_flag ) { 1227 ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1228 ierr = MatAssemblyEnd (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1229 } 1230 /* Checking coarse_sub_mat and coarse basis functios */ 1231 /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 1232 if(check_flag) { 1233 1234 Mat coarse_sub_mat; 1235 Mat TM1,TM2,TM3,TM4; 1236 Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI; 1237 const MatType checkmattype; 1238 PetscScalar value; 1239 1240 ierr = MatGetType(matis->A,&checkmattype);CHKERRQ(ierr); 1241 ierr = MatGetType(pcis->A_II,&checkmattype);CHKERRQ(ierr); 1242 checkmattype = MATSEQAIJ; 1243 ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr); 1244 ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr); 1245 ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr); 1246 ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr); 1247 ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr); 1248 ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr); 1249 ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr); 1250 ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr); 1251 1252 ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr); 1253 ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr); 1254 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1255 ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr); 1256 ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr); 1257 ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr); 1258 ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr); 1259 ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr); 1260 ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr); 1261 ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr); 1262 ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr); 1263 ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1264 ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1265 ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1266 ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 1267 ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr); 1268 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr); 1269 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr); 1270 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr); 1271 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr); 1272 for(i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr); } 1273 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr); 1274 for(i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr); } 1275 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1276 ierr = MatDestroy(&A_II);CHKERRQ(ierr); 1277 ierr = MatDestroy(&A_BB);CHKERRQ(ierr); 1278 ierr = MatDestroy(&A_IB);CHKERRQ(ierr); 1279 ierr = MatDestroy(&A_BI);CHKERRQ(ierr); 1280 ierr = MatDestroy(&TM1);CHKERRQ(ierr); 1281 ierr = MatDestroy(&TM2);CHKERRQ(ierr); 1282 ierr = MatDestroy(&TM3);CHKERRQ(ierr); 1283 ierr = MatDestroy(&TM4);CHKERRQ(ierr); 1284 ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr); 1285 ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr); 1286 ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr); 1287 ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr); 1288 ierr = PetscFree(constraints_errors);CHKERRQ(ierr); 1289 } 1290 1291 /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */ 1292 ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr); 1293 /* free memory */ 1294 ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr); 1295 ierr = PetscFree(auxindices);CHKERRQ(ierr); 1296 ierr = PetscFree(nnz);CHKERRQ(ierr); 1297 if(pcbddc->n_vertices) { 1298 ierr = VecDestroy(&vec1_V);CHKERRQ(ierr); 1299 ierr = VecDestroy(&vec2_V);CHKERRQ(ierr); 1300 ierr = MatDestroy(&M2);CHKERRQ(ierr); 1301 ierr = MatDestroy(&A_RV);CHKERRQ(ierr); 1302 ierr = MatDestroy(&A_VR);CHKERRQ(ierr); 1303 ierr = MatDestroy(&A_VV);CHKERRQ(ierr); 1304 } 1305 if(pcbddc->n_constraints) { 1306 ierr = VecDestroy(&vec1_C);CHKERRQ(ierr); 1307 ierr = VecDestroy(&vec2_C);CHKERRQ(ierr); 1308 ierr = MatDestroy(&M1);CHKERRQ(ierr); 1309 ierr = MatDestroy(&C_CR);CHKERRQ(ierr); 1310 } 1311 ierr = MatDestroy(&CMAT);CHKERRQ(ierr); 1312 } 1313 /* free memory */ 1314 if(pcbddc->n_vertices) { 1315 ierr = PetscFree(idx_V_B);CHKERRQ(ierr); 1316 ierr = ISDestroy(&is_V_local);CHKERRQ(ierr); 1317 } 1318 ierr = PetscFree(idx_R_local);CHKERRQ(ierr); 1319 ierr = ISDestroy(&is_R_local);CHKERRQ(ierr); 1320 1321 PetscFunctionReturn(0); 1322 } 1323 1324 /* -------------------------------------------------------------------------- */ 1325 1326 #undef __FUNCT__ 1327 #define __FUNCT__ "PCBDDCSetupCoarseEnvironment" 1328 static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals) 1329 { 1330 1331 1332 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 1333 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1334 PC_IS *pcis = (PC_IS*)pc->data; 1335 MPI_Comm prec_comm = ((PetscObject)pc)->comm; 1336 MPI_Comm coarse_comm; 1337 1338 /* common to all choiches */ 1339 PetscScalar *temp_coarse_mat_vals; 1340 PetscScalar *ins_coarse_mat_vals; 1341 PetscInt *ins_local_primal_indices; 1342 PetscMPIInt *localsizes2,*localdispl2; 1343 PetscMPIInt size_prec_comm; 1344 PetscMPIInt rank_prec_comm; 1345 PetscMPIInt active_rank=MPI_PROC_NULL; 1346 PetscMPIInt master_proc=0; 1347 PetscInt ins_local_primal_size; 1348 /* specific to MULTILEVEL_BDDC */ 1349 PetscMPIInt *ranks_recv; 1350 PetscMPIInt count_recv=0; 1351 PetscMPIInt rank_coarse_proc_send_to; 1352 PetscMPIInt coarse_color = MPI_UNDEFINED; 1353 ISLocalToGlobalMapping coarse_ISLG; 1354 /* some other variables */ 1355 PetscErrorCode ierr; 1356 const MatType coarse_mat_type; 1357 const PCType coarse_pc_type; 1358 const KSPType coarse_ksp_type; 1359 PC pc_temp; 1360 PetscInt i,j,k,bs; 1361 1362 PetscFunctionBegin; 1363 1364 ins_local_primal_indices = 0; 1365 ins_coarse_mat_vals = 0; 1366 localsizes2 = 0; 1367 localdispl2 = 0; 1368 temp_coarse_mat_vals = 0; 1369 coarse_ISLG = 0; 1370 1371 ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr); 1372 ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr); 1373 ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 1374 1375 /* Assign global numbering to coarse dofs */ 1376 { 1377 PetscScalar coarsesum,one=1.,zero=0.; 1378 PetscScalar *array; 1379 PetscMPIInt *auxlocal_primal; 1380 PetscMPIInt *auxglobal_primal; 1381 PetscMPIInt *all_auxglobal_primal; 1382 PetscMPIInt *all_auxglobal_primal_dummy; 1383 PetscMPIInt mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size; 1384 1385 /* Construct needed data structures for message passing */ 1386 ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr); 1387 ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr); 1388 ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr); 1389 /* Gather local_primal_size information for all processes */ 1390 ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr); 1391 pcbddc->replicated_primal_size = 0; 1392 if(rank_prec_comm == 0) { 1393 for (i=0; i<size_prec_comm; i++) { 1394 pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ; 1395 pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i]; 1396 } 1397 /* allocate some auxiliary space */ 1398 ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr); 1399 ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr); 1400 } 1401 ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr); 1402 ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr); 1403 1404 /* First let's count coarse dofs: note that we allow to have a constraint on a subdomain and not its counterpart on the neighbour subdomain (if user wants) 1405 This code fragment assumes that the number of local constraints per connected component 1406 is not greater than the number of nodes defined for the connected component 1407 (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */ 1408 /* auxlocal_primal : primal indices in local nodes numbering (internal and interface) */ 1409 ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr); 1410 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1411 for(i=0;i<pcbddc->n_vertices;i++) { 1412 array[ pcbddc->vertices[i] ] = one; 1413 auxlocal_primal[i] = pcbddc->vertices[i]; 1414 } 1415 for(i=0;i<pcbddc->n_constraints;i++) { 1416 for (j=0; j<pcbddc->sizes_of_constraint[i]; j++) { 1417 k = pcbddc->indices_to_constraint[i][j]; 1418 if( array[k] == zero ) { 1419 array[k] = one; 1420 auxlocal_primal[i+pcbddc->n_vertices] = k; 1421 break; 1422 } 1423 } 1424 } 1425 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1426 ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr); 1427 ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1428 ierr = VecScatterEnd (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1429 ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1430 ierr = VecScatterEnd (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1431 ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1432 for(i=0;i<pcis->n;i++) { if(array[i] > 0.0) array[i] = one/array[i]; } 1433 ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 1434 ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr); 1435 ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1436 ierr = VecScatterEnd (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1437 1438 ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr); 1439 pcbddc->coarse_size = (PetscInt) coarsesum; 1440 //if(check_flag) { 1441 // ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr); 1442 // ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d\n",pcbddc->coarse_size);CHKERRQ(ierr); 1443 // ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1444 //} 1445 /* Now assign them a global numbering */ 1446 /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */ 1447 ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr); 1448 /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */ 1449 ierr = MPI_Gatherv(&auxglobal_primal[0],pcbddc->local_primal_size,MPIU_INT,&all_auxglobal_primal[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,0,prec_comm);CHKERRQ(ierr); 1450 1451 /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */ 1452 /* It implements a function similar to PetscSortRemoveDupsInt */ 1453 if(rank_prec_comm==0) { 1454 /* dummy argument since PetscSortMPIInt doesn't exist! */ 1455 ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr); 1456 k=1; 1457 j=all_auxglobal_primal[0]; /* first dof in global numbering */ 1458 for(i=1;i< pcbddc->replicated_primal_size ;i++) { 1459 if(j != all_auxglobal_primal[i] ) { 1460 all_auxglobal_primal[k]=all_auxglobal_primal[i]; 1461 k++; 1462 j=all_auxglobal_primal[i]; 1463 } 1464 } 1465 } else { 1466 ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr); 1467 } 1468 /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array are garbage. */ 1469 ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr); 1470 1471 /* Now get global coarse numbering of local primal nodes */ 1472 for(i=0;i<pcbddc->local_primal_size;i++) { 1473 k=0; 1474 while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;} 1475 pcbddc->local_primal_indices[i]=k; 1476 } 1477 //if(check_flag) { 1478 // ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr); 1479 // ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr); 1480 // ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1481 // ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr); 1482 // for(i=0;i<pcbddc->local_primal_size;i++) { 1483 // ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]); 1484 // } 1485 // ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1486 //} 1487 /* free allocated memory */ 1488 ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr); 1489 ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr); 1490 ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr); 1491 ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr); 1492 } 1493 1494 /* adapt coarse problem type */ 1495 if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC ) 1496 pcbddc->coarse_problem_type = PARALLEL_BDDC; 1497 1498 switch(pcbddc->coarse_problem_type){ 1499 1500 case(MULTILEVEL_BDDC): //we define a coarse mesh where subdomains are elements 1501 { 1502 /* we need additional variables */ 1503 MetisInt n_subdomains,n_parts,objval,ncon,faces_nvtxs; 1504 MetisInt *metis_coarse_subdivision; 1505 MetisInt options[METIS_NOPTIONS]; 1506 PetscMPIInt size_coarse_comm,rank_coarse_comm; 1507 PetscMPIInt procs_jumps_coarse_comm; 1508 PetscMPIInt *coarse_subdivision; 1509 PetscMPIInt *total_count_recv; 1510 PetscMPIInt *total_ranks_recv; 1511 PetscMPIInt *displacements_recv; 1512 PetscMPIInt *my_faces_connectivity; 1513 PetscMPIInt *petsc_faces_adjncy; 1514 MetisInt *faces_adjncy; 1515 MetisInt *faces_xadj; 1516 PetscMPIInt *number_of_faces; 1517 PetscMPIInt *faces_displacements; 1518 PetscInt *array_int; 1519 PetscMPIInt my_faces=0; 1520 PetscMPIInt total_faces=0; 1521 1522 /* this code has a bug (see below) for more then three levels -> I can solve it quickly */ 1523 1524 /* define some quantities */ 1525 pcbddc->coarse_communications_type = SCATTERS_BDDC; 1526 coarse_mat_type = MATIS; 1527 coarse_pc_type = PCBDDC; 1528 coarse_ksp_type = KSPRICHARDSON; 1529 1530 /* details of coarse decomposition */ 1531 n_subdomains = pcbddc->active_procs; 1532 n_parts = n_subdomains/pcbddc->coarsening_ratio; 1533 procs_jumps_coarse_comm = pcbddc->coarsening_ratio*(size_prec_comm/pcbddc->active_procs); 1534 1535 ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr); 1536 ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],pcbddc->local_primal_size,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr); 1537 1538 /* build CSR graph of subdomains' connectivity through faces */ 1539 ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr); 1540 PetscMemzero(array_int,pcis->n*sizeof(PetscInt)); 1541 for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */ 1542 for(j=0;j<pcis->n_shared[i];j++){ 1543 array_int[ pcis->shared[i][j] ]+=1; 1544 } 1545 } 1546 for(i=1;i<pcis->n_neigh;i++){ 1547 for(j=0;j<pcis->n_shared[i];j++){ 1548 if(array_int[ pcis->shared[i][j] ] == 1 ){ 1549 my_faces++; 1550 break; 1551 } 1552 } 1553 } 1554 //printf("I found %d faces.\n",my_faces); 1555 1556 ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr); 1557 ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr); 1558 my_faces=0; 1559 for(i=1;i<pcis->n_neigh;i++){ 1560 for(j=0;j<pcis->n_shared[i];j++){ 1561 if(array_int[ pcis->shared[i][j] ] == 1 ){ 1562 my_faces_connectivity[my_faces]=pcis->neigh[i]; 1563 my_faces++; 1564 break; 1565 } 1566 } 1567 } 1568 if(rank_prec_comm == master_proc) { 1569 //printf("I found %d total faces.\n",total_faces); 1570 ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr); 1571 ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr); 1572 ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr); 1573 ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr); 1574 ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr); 1575 } 1576 ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr); 1577 if(rank_prec_comm == master_proc) { 1578 faces_xadj[0]=0; 1579 faces_displacements[0]=0; 1580 j=0; 1581 for(i=1;i<size_prec_comm+1;i++) { 1582 faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1]; 1583 if(number_of_faces[i-1]) { 1584 j++; 1585 faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1]; 1586 } 1587 } 1588 printf("The J I count is %d and should be %d\n",j,n_subdomains); 1589 printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces); 1590 } 1591 ierr = MPI_Gatherv(&my_faces_connectivity[0],my_faces,MPIU_INT,&petsc_faces_adjncy[0],number_of_faces,faces_displacements,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr); 1592 ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr); 1593 ierr = PetscFree(array_int);CHKERRQ(ierr); 1594 if(rank_prec_comm == master_proc) { 1595 for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]); ///procs_jumps_coarse_comm); // cast to MetisInt 1596 printf("This is the face connectivity (%d)\n",procs_jumps_coarse_comm); 1597 for(i=0;i<n_subdomains;i++){ 1598 printf("proc %d is connected with \n",i); 1599 for(j=faces_xadj[i];j<faces_xadj[i+1];j++) 1600 printf("%d ",faces_adjncy[j]); 1601 printf("\n"); 1602 } 1603 ierr = PetscFree(faces_displacements);CHKERRQ(ierr); 1604 ierr = PetscFree(number_of_faces);CHKERRQ(ierr); 1605 ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr); 1606 } 1607 1608 if( rank_prec_comm == master_proc ) { 1609 1610 ncon=1; 1611 faces_nvtxs=n_subdomains; 1612 /* partition graoh induced by face connectivity */ 1613 ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr); 1614 ierr = METIS_SetDefaultOptions(options); 1615 /* we need a contiguous partition of the coarse mesh */ 1616 options[METIS_OPTION_CONTIG]=1; 1617 options[METIS_OPTION_DBGLVL]=1; 1618 options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT; 1619 options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE; 1620 options[METIS_OPTION_NITER]=30; 1621 //options[METIS_OPTION_NCUTS]=1; 1622 //printf("METIS PART GRAPH\n"); 1623 /* BUG: faces_xadj and faces_adjncy content must be adapted using the coarsening factor*/ 1624 ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision); 1625 //printf("OKOKOKOKOKOKOKOK\n"); 1626 if(ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphKway (metis error code %D) called from PCBDDCSetupCoarseEnvironment\n",ierr); 1627 ierr = PetscFree(faces_xadj);CHKERRQ(ierr); 1628 ierr = PetscFree(faces_adjncy);CHKERRQ(ierr); 1629 coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */ 1630 /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */ 1631 for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;; 1632 k=size_prec_comm/pcbddc->active_procs; 1633 for(i=0;i<n_subdomains;i++) coarse_subdivision[k*i]=(PetscInt)(metis_coarse_subdivision[i]); 1634 ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr); 1635 1636 } 1637 1638 /* Create new communicator for coarse problem splitting the old one */ 1639 if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){ 1640 coarse_color=0; //for communicator splitting 1641 active_rank=rank_prec_comm; //for insertion of matrix values 1642 } 1643 // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards) 1644 // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator 1645 ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr); 1646 1647 if( coarse_color == 0 ) { 1648 ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr); 1649 ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr); 1650 //printf("Details of coarse comm\n"); 1651 //printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm); 1652 //printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts); 1653 } else { 1654 rank_coarse_comm = MPI_PROC_NULL; 1655 } 1656 1657 /* master proc take care of arranging and distributing coarse informations */ 1658 if(rank_coarse_comm == master_proc) { 1659 ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr); 1660 //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr); 1661 //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr); 1662 total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); 1663 total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt)); 1664 /* some initializations */ 1665 displacements_recv[0]=0; 1666 //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero 1667 /* count from how many processes the j-th process of the coarse decomposition will receive data */ 1668 for(j=0;j<size_coarse_comm;j++) 1669 for(i=0;i<n_subdomains;i++) 1670 if(coarse_subdivision[i]==j) 1671 total_count_recv[j]++; 1672 /* displacements needed for scatterv of total_ranks_recv */ 1673 for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1]; 1674 /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */ 1675 ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr); 1676 for(j=0;j<size_coarse_comm;j++) { 1677 for(i=0;i<n_subdomains;i++) { 1678 if(coarse_subdivision[i]==j) { 1679 total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i; 1680 total_count_recv[j]=total_count_recv[j]+1; 1681 } 1682 } 1683 } 1684 //for(j=0;j<size_coarse_comm;j++) { 1685 // printf("process %d in new rank will receive from %d processes (ranks follows)\n",j,total_count_recv[j]); 1686 // for(i=0;i<total_count_recv[j];i++) { 1687 // printf("%d ",total_ranks_recv[displacements_recv[j]+i]); 1688 // } 1689 // printf("\n"); 1690 // } 1691 1692 /* identify new decomposition in terms of ranks in the old communicator */ 1693 k=size_prec_comm/pcbddc->active_procs; 1694 for(i=0;i<n_subdomains;i++) coarse_subdivision[k*i]=coarse_subdivision[k*i]*procs_jumps_coarse_comm; 1695 printf("coarse_subdivision in old end new ranks\n"); 1696 for(i=0;i<size_prec_comm;i++) 1697 printf("(%d %d) ",coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm); 1698 printf("\n"); 1699 } 1700 1701 /* Scatter new decomposition for send details */ 1702 ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr); 1703 /* Scatter receiving details to members of coarse decomposition */ 1704 if( coarse_color == 0) { 1705 ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr); 1706 ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr); 1707 ierr = MPI_Scatterv(&total_ranks_recv[0],total_count_recv,displacements_recv,MPIU_INT,&ranks_recv[0],count_recv,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr); 1708 } 1709 1710 //printf("I will send my matrix data to proc %d\n",rank_coarse_proc_send_to); 1711 //if(coarse_color == 0) { 1712 // printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv); 1713 // for(i=0;i<count_recv;i++) 1714 // printf("%d ",ranks_recv[i]); 1715 // printf("\n"); 1716 //} 1717 1718 if(rank_prec_comm == master_proc) { 1719 //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr); 1720 //ierr = PetscFree(total_count_recv);CHKERRQ(ierr); 1721 //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr); 1722 free(coarse_subdivision); 1723 free(total_count_recv); 1724 free(total_ranks_recv); 1725 ierr = PetscFree(displacements_recv);CHKERRQ(ierr); 1726 } 1727 break; 1728 } 1729 1730 case(REPLICATED_BDDC): 1731 1732 pcbddc->coarse_communications_type = GATHERS_BDDC; 1733 coarse_mat_type = MATSEQAIJ; 1734 coarse_pc_type = PCLU; 1735 coarse_ksp_type = KSPPREONLY; 1736 coarse_comm = PETSC_COMM_SELF; 1737 active_rank = rank_prec_comm; 1738 break; 1739 1740 case(PARALLEL_BDDC): 1741 1742 pcbddc->coarse_communications_type = SCATTERS_BDDC; 1743 coarse_mat_type = MATMPIAIJ; 1744 coarse_pc_type = PCREDUNDANT; 1745 coarse_ksp_type = KSPPREONLY; 1746 coarse_comm = prec_comm; 1747 active_rank = rank_prec_comm; 1748 break; 1749 1750 case(SEQUENTIAL_BDDC): 1751 pcbddc->coarse_communications_type = GATHERS_BDDC; 1752 coarse_mat_type = MATSEQAIJ; 1753 coarse_pc_type = PCLU; 1754 coarse_ksp_type = KSPPREONLY; 1755 coarse_comm = PETSC_COMM_SELF; 1756 active_rank = master_proc; 1757 break; 1758 } 1759 1760 switch(pcbddc->coarse_communications_type){ 1761 1762 case(SCATTERS_BDDC): 1763 { 1764 if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) { 1765 1766 PetscMPIInt send_size; 1767 PetscInt *aux_ins_indices; 1768 PetscInt ii,jj; 1769 MPI_Request *requests; 1770 1771 /* allocate auxiliary space */ 1772 ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr); 1773 ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr); 1774 /* allocate stuffs for message massing */ 1775 ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr); 1776 for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL; 1777 ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr); 1778 ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr); 1779 /* fill up quantities */ 1780 j=0; 1781 for(i=0;i<count_recv;i++){ 1782 ii = ranks_recv[i]; 1783 localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii]; 1784 localdispl2[i]=j; 1785 j+=localsizes2[i]; 1786 jj = pcbddc->local_primal_displacements[ii]; 1787 for(k=0;k<pcbddc->local_primal_sizes[ii];k++) aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]]+=1; // it counts the coarse subdomains sharing the coarse node 1788 } 1789 //printf("aux_ins_indices 1\n"); 1790 //for(i=0;i<pcbddc->coarse_size;i++) 1791 // printf("%d ",aux_ins_indices[i]); 1792 //printf("\n"); 1793 /* temp_coarse_mat_vals used to store temporarly received matrix values */ 1794 ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr); 1795 /* evaluate how many values I will insert in coarse mat */ 1796 ins_local_primal_size=0; 1797 for(i=0;i<pcbddc->coarse_size;i++) 1798 if(aux_ins_indices[i]) 1799 ins_local_primal_size++; 1800 /* evaluate indices I will insert in coarse mat */ 1801 ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr); 1802 j=0; 1803 for(i=0;i<pcbddc->coarse_size;i++) 1804 if(aux_ins_indices[i]) 1805 ins_local_primal_indices[j++]=i; 1806 /* use aux_ins_indices to realize a global to local mapping */ 1807 j=0; 1808 for(i=0;i<pcbddc->coarse_size;i++){ 1809 if(aux_ins_indices[i]==0){ 1810 aux_ins_indices[i]=-1; 1811 } else { 1812 aux_ins_indices[i]=j; 1813 j++; 1814 } 1815 } 1816 1817 //printf("New details localsizes2 localdispl2\n"); 1818 //for(i=0;i<count_recv;i++) 1819 // printf("(%d %d) ",localsizes2[i],localdispl2[i]); 1820 //printf("\n"); 1821 //printf("aux_ins_indices 2\n"); 1822 //for(i=0;i<pcbddc->coarse_size;i++) 1823 // printf("%d ",aux_ins_indices[i]); 1824 //printf("\n"); 1825 //printf("ins_local_primal_indices\n"); 1826 //for(i=0;i<ins_local_primal_size;i++) 1827 // printf("%d ",ins_local_primal_indices[i]); 1828 //printf("\n"); 1829 //printf("coarse_submat_vals\n"); 1830 //for(i=0;i<pcbddc->local_primal_size;i++) 1831 // for(j=0;j<pcbddc->local_primal_size;j++) 1832 // printf("(%lf %d %d)\n",coarse_submat_vals[j*pcbddc->local_primal_size+i],pcbddc->local_primal_indices[i],pcbddc->local_primal_indices[j]); 1833 //printf("\n"); 1834 1835 /* processes partecipating in coarse problem receive matrix data from their friends */ 1836 for(i=0;i<count_recv;i++) ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr); 1837 if(rank_coarse_proc_send_to != MPI_PROC_NULL ) { 1838 send_size=pcbddc->local_primal_size*pcbddc->local_primal_size; 1839 ierr = MPI_Isend(&coarse_submat_vals[0],send_size,MPIU_SCALAR,rank_coarse_proc_send_to,666,prec_comm,&requests[count_recv]);CHKERRQ(ierr); 1840 } 1841 ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr); 1842 1843 //if(coarse_color == 0) { 1844 // printf("temp_coarse_mat_vals\n"); 1845 // for(k=0;k<count_recv;k++){ 1846 // printf("---- %d ----\n",ranks_recv[k]); 1847 // for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++) 1848 // for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++) 1849 // printf("(%lf %d %d)\n",temp_coarse_mat_vals[localdispl2[k]+j*pcbddc->local_primal_sizes[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+j]); 1850 // printf("\n"); 1851 // } 1852 //} 1853 /* calculate data to insert in coarse mat */ 1854 ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr); 1855 PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar)); 1856 1857 PetscMPIInt rr,kk,lps,lpd; 1858 PetscInt row_ind,col_ind; 1859 for(k=0;k<count_recv;k++){ 1860 rr = ranks_recv[k]; 1861 kk = localdispl2[k]; 1862 lps = pcbddc->local_primal_sizes[rr]; 1863 lpd = pcbddc->local_primal_displacements[rr]; 1864 //printf("Inserting the following indices (received from %d)\n",rr); 1865 for(j=0;j<lps;j++){ 1866 col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]]; 1867 for(i=0;i<lps;i++){ 1868 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]]; 1869 //printf("%d %d\n",row_ind,col_ind); 1870 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i]; 1871 } 1872 } 1873 } 1874 ierr = PetscFree(requests);CHKERRQ(ierr); 1875 ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr); 1876 ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); 1877 if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); } 1878 1879 /* create local to global mapping needed by coarse MATIS */ 1880 { 1881 IS coarse_IS; 1882 if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr); 1883 coarse_comm = prec_comm; 1884 active_rank=rank_prec_comm; 1885 ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr); 1886 //ierr = ISSetBlockSize(coarse_IS,bs);CHKERRQ(ierr); 1887 ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr); 1888 ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr); 1889 } 1890 } 1891 if(pcbddc->coarse_problem_type==PARALLEL_BDDC) { 1892 /* arrays for values insertion */ 1893 ins_local_primal_size = pcbddc->local_primal_size; 1894 ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr); 1895 ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr); 1896 for(j=0;j<ins_local_primal_size;j++){ 1897 ins_local_primal_indices[j]=pcbddc->local_primal_indices[j]; 1898 for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i]; 1899 } 1900 } 1901 break; 1902 1903 } 1904 1905 case(GATHERS_BDDC): 1906 { 1907 1908 PetscMPIInt mysize,mysize2; 1909 1910 if(rank_prec_comm==active_rank) { 1911 ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr); 1912 pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar)); 1913 ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr); 1914 ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr); 1915 /* arrays for values insertion */ 1916 ins_local_primal_size = pcbddc->coarse_size; 1917 ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr); 1918 ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr); 1919 for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i]; 1920 localdispl2[0]=0; 1921 for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1]; 1922 j=0; 1923 for(i=0;i<size_prec_comm;i++) j+=localsizes2[i]; 1924 ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr); 1925 } 1926 1927 mysize=pcbddc->local_primal_size; 1928 mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size; 1929 if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){ 1930 ierr = MPI_Gatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr); 1931 ierr = MPI_Gatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,master_proc,prec_comm);CHKERRQ(ierr); 1932 } else { 1933 ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr); 1934 ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr); 1935 } 1936 1937 /* free data structures no longer needed and allocate some space which will be needed in BDDC application */ 1938 if(rank_prec_comm==active_rank) { 1939 PetscInt offset,offset2,row_ind,col_ind; 1940 for(j=0;j<ins_local_primal_size;j++){ 1941 ins_local_primal_indices[j]=j; 1942 for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0; 1943 } 1944 for(k=0;k<size_prec_comm;k++){ 1945 offset=pcbddc->local_primal_displacements[k]; 1946 offset2=localdispl2[k]; 1947 for(j=0;j<pcbddc->local_primal_sizes[k];j++){ 1948 col_ind=pcbddc->replicated_local_primal_indices[offset+j]; 1949 for(i=0;i<pcbddc->local_primal_sizes[k];i++){ 1950 row_ind=pcbddc->replicated_local_primal_indices[offset+i]; 1951 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i]; 1952 } 1953 } 1954 } 1955 } 1956 break; 1957 }//switch on coarse problem and communications associated with finished 1958 } 1959 1960 /* Now create and fill up coarse matrix */ 1961 if( rank_prec_comm == active_rank ) { 1962 if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) { 1963 ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr); 1964 ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr); 1965 ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr); 1966 ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 1967 ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major 1968 } else { 1969 Mat matis_coarse_local_mat; 1970 ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr); 1971 ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr); 1972 ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major 1973 ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 1974 ierr = MatSetOption(matis_coarse_local_mat,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr); 1975 } 1976 ierr = MatSetValues(pcbddc->coarse_mat,ins_local_primal_size,ins_local_primal_indices,ins_local_primal_size,ins_local_primal_indices,ins_coarse_mat_vals,ADD_VALUES);CHKERRQ(ierr); 1977 ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1978 ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1979 if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) { 1980 Mat matis_coarse_local_mat; 1981 ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr); 1982 ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr); 1983 } 1984 1985 ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr); 1986 /* Preconditioner for coarse problem */ 1987 ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr); 1988 ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr); 1989 ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr); 1990 ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr); 1991 ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr); 1992 ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr); 1993 //ierr = PCSetOptionsPrefix(pcbddc->coarse_pc,"pc_bddc_coarse_");CHKERRQ(ierr); 1994 /* Allow user's customization */ 1995 ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr); 1996 /* Set Up PC for coarse problem BDDC */ 1997 //if(pcbddc->check_flag && pcbddc->coarse_problem_type == MULTILEVEL_BDDC) { 1998 if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) { 1999 PetscPrintf(PETSC_COMM_WORLD,"----------------Setting up a new level---------------\n"); 2000 ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr); 2001 } 2002 ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr); 2003 } 2004 if(pcbddc->coarse_communications_type == SCATTERS_BDDC) { 2005 IS local_IS,global_IS; 2006 ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr); 2007 ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr); 2008 ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr); 2009 ierr = ISDestroy(&local_IS);CHKERRQ(ierr); 2010 ierr = ISDestroy(&global_IS);CHKERRQ(ierr); 2011 } 2012 2013 2014 /* Check condition number of coarse problem */ 2015 if( pcbddc->check_flag && rank_prec_comm == active_rank ) { 2016 PetscScalar m_one=-1.0; 2017 PetscReal infty_error,lambda_min,lambda_max; 2018 2019 ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr); 2020 ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr); 2021 ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr); 2022 ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr); 2023 ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr); 2024 ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr); 2025 ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr); 2026 ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr); 2027 printf("eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max); 2028 printf("Error on coarse ksp %1.14e\n",infty_error); 2029 ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr); 2030 } 2031 2032 /* free data structures no longer needed */ 2033 if(coarse_ISLG) { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); } 2034 if(ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); } 2035 if(ins_coarse_mat_vals) { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);} 2036 if(localsizes2) { ierr = PetscFree(localsizes2);CHKERRQ(ierr);} 2037 if(localdispl2) { ierr = PetscFree(localdispl2);CHKERRQ(ierr);} 2038 if(temp_coarse_mat_vals) { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);} 2039 2040 PetscFunctionReturn(0); 2041 } 2042 2043 #undef __FUNCT__ 2044 #define __FUNCT__ "PCBDDCManageLocalBoundaries" 2045 static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc) 2046 { 2047 2048 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 2049 PC_IS *pcis = (PC_IS*)pc->data; 2050 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 2051 PetscInt *distinct_values; 2052 PetscInt **neighbours_set; 2053 PetscInt bs,ierr,i,j,s,k,iindex; 2054 PetscInt total_counts; 2055 PetscBool flg_row; 2056 PCBDDCGraph mat_graph; 2057 PetscInt neumann_bsize; 2058 const PetscInt* neumann_nodes; 2059 Mat mat_adj; 2060 2061 PetscFunctionBegin; 2062 2063 ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 2064 // allocate and initialize needed graph structure 2065 ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr); 2066 ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr); 2067 ierr = MatGetRowIJ(mat_adj,0,PETSC_FALSE,PETSC_FALSE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr); 2068 if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n"); 2069 ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->where);CHKERRQ(ierr); 2070 ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->count);CHKERRQ(ierr); 2071 ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->which_dof);CHKERRQ(ierr); 2072 ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->queue);CHKERRQ(ierr); 2073 ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->cptr);CHKERRQ(ierr); 2074 ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscBool),&mat_graph->touched);CHKERRQ(ierr); 2075 for(i=0;i<mat_graph->nvtxs;i++){ 2076 mat_graph->count[i]=0; 2077 mat_graph->touched[i]=PETSC_FALSE; 2078 } 2079 for(i=0;i<mat_graph->nvtxs/bs;i++) { 2080 for(s=0;s<bs;s++) { 2081 mat_graph->which_dof[i*bs+s]=s; 2082 } 2083 } 2084 //printf("nvtxs = %d\n",mat_graph->nvtxs); 2085 //printf("these are my IS data with n_neigh = %d\n",pcis->n_neigh); 2086 //for(i=0;i<pcis->n_neigh;i++){ 2087 // printf("number of shared nodes with rank %d is %d \n",pcis->neigh[i],pcis->n_shared[i]); 2088 // } 2089 2090 total_counts=0; 2091 for(i=0;i<pcis->n_neigh;i++){ 2092 s=pcis->n_shared[i]; 2093 total_counts+=s; 2094 //printf("computing neigh %d (rank = %d, n_shared = %d)\n",i,pcis->neigh[i],s); 2095 for(j=0;j<s;j++){ 2096 mat_graph->count[pcis->shared[i][j]] += 1; 2097 } 2098 } 2099 /* Take into account Neumann data incrementing number of sharing subdomains for all but faces nodes lying on the interface */ 2100 if(pcbddc->NeumannBoundaries) { 2101 ierr = ISGetLocalSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr); 2102 ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr); 2103 for(i=0;i<neumann_bsize;i++){ 2104 iindex = neumann_nodes[i]; 2105 if(mat_graph->count[iindex] > 2){ 2106 mat_graph->count[iindex]+=1; 2107 total_counts++; 2108 } 2109 } 2110 } 2111 2112 ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr); 2113 if(mat_graph->nvtxs) ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr); 2114 for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1]; 2115 2116 for(i=0;i<mat_graph->nvtxs;i++) mat_graph->count[i]=0; 2117 for(i=0;i<pcis->n_neigh;i++){ 2118 s=pcis->n_shared[i]; 2119 for(j=0;j<s;j++) { 2120 k=pcis->shared[i][j]; 2121 neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i]; 2122 mat_graph->count[k]+=1; 2123 } 2124 } 2125 /* set -1 fake neighbour */ 2126 if(pcbddc->NeumannBoundaries) { 2127 for(i=0;i<neumann_bsize;i++){ 2128 iindex = neumann_nodes[i]; 2129 if( mat_graph->count[iindex] > 2){ 2130 neighbours_set[iindex][mat_graph->count[iindex]] = -1; //An additional fake neighbour (with rank -1) 2131 mat_graph->count[iindex]+=1; 2132 } 2133 } 2134 ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr); 2135 } 2136 2137 /* sort sharing subdomains */ 2138 for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); } 2139 2140 /* Prepare for FindConnectedComponents 2141 Vertices will be eliminated later (if needed) */ 2142 PetscInt nodes_touched=0; 2143 for(i=0;i<mat_graph->nvtxs;i++){ 2144 if(!mat_graph->count[i]){ //internal nodes 2145 mat_graph->touched[i]=PETSC_TRUE; 2146 mat_graph->where[i]=0; 2147 nodes_touched++; 2148 } 2149 if(pcbddc->faces_flag){ 2150 if(mat_graph->count[i]>2){ //all but faces 2151 mat_graph->touched[i]=PETSC_TRUE; 2152 mat_graph->where[i]=0; 2153 nodes_touched++; 2154 } 2155 } 2156 if(pcbddc->edges_flag){ 2157 if(mat_graph->count[i]==2){ //faces 2158 mat_graph->touched[i]=PETSC_TRUE; 2159 mat_graph->where[i]=0; 2160 nodes_touched++; 2161 } 2162 } 2163 } 2164 2165 PetscInt rvalue=1; 2166 PetscBool same_set; 2167 mat_graph->ncmps = 0; 2168 while(nodes_touched<mat_graph->nvtxs) { 2169 // find first untouched node in local ordering 2170 i=0; 2171 while(mat_graph->touched[i]) i++; 2172 mat_graph->touched[i]=PETSC_TRUE; 2173 mat_graph->where[i]=rvalue; 2174 nodes_touched++; 2175 // now find other connected nodes shared by the same set of subdomains 2176 for(j=i+1;j<mat_graph->nvtxs;j++){ 2177 // check for same number of sharing subdomains and dof number 2178 if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){ 2179 // check for same set of sharing subdomains 2180 same_set=PETSC_TRUE; 2181 for(k=0;k<mat_graph->count[j];k++){ 2182 if(neighbours_set[i][k]!=neighbours_set[j][k]) { 2183 same_set=PETSC_FALSE; 2184 } 2185 } 2186 // OK, I found a friend of mine 2187 if(same_set) { 2188 mat_graph->where[j]=rvalue; 2189 mat_graph->touched[j]=PETSC_TRUE; 2190 nodes_touched++; 2191 } 2192 } 2193 } 2194 rvalue++; 2195 } 2196 // printf("where and count contains %d distinct values\n",rvalue); 2197 // for(j=0;j<mat_graph->nvtxs;j++) 2198 // printf("[%d %d %d]\n",j,mat_graph->where[j],mat_graph->count[j]); 2199 2200 if(mat_graph->nvtxs) { 2201 ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr); 2202 ierr = PetscFree(neighbours_set);CHKERRQ(ierr); 2203 } 2204 2205 rvalue--; 2206 ierr = PetscMalloc ( rvalue*sizeof(PetscInt),&distinct_values);CHKERRQ(ierr); 2207 for(i=0;i<rvalue;i++) distinct_values[i]=i+1; //initializiation 2208 if(rvalue) ierr = PCBDDCFindConnectedComponents(mat_graph, rvalue, distinct_values); 2209 //printf("total number of connected components %d \n",mat_graph->ncmps); 2210 //for (i=0; i<mat_graph->ncmps; i++) { 2211 // printf("[queue num %d] ptr %d, length %d, start index %d\n",i,mat_graph->cptr[i],mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->queue[mat_graph->cptr[i]]); 2212 //} 2213 PetscInt nfc=0; 2214 PetscInt nec=0; 2215 PetscInt nvc=0; 2216 for (i=0; i<mat_graph->ncmps; i++) { 2217 // sort each connected component (by local ordering) 2218 ierr = PetscSortInt(mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr); 2219 // count edge and faces 2220 if( !pcbddc->vertices_flag ) { 2221 if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){ 2222 if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==2){ 2223 nfc++; 2224 } else { 2225 nec++; 2226 } 2227 } 2228 } 2229 // count vertices 2230 if( !pcbddc->constraints_flag ){ 2231 if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){ 2232 nvc++; 2233 } 2234 } 2235 } 2236 2237 pcbddc->n_constraints = nec+nfc; 2238 pcbddc->n_vertices = nvc; 2239 2240 if(pcbddc->n_constraints){ 2241 /* allocate space for local constraints of BDDC */ 2242 ierr = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt*),&pcbddc->indices_to_constraint);CHKERRQ(ierr); 2243 ierr = PetscMalloc (pcbddc->n_constraints*sizeof(PetscScalar*),&pcbddc->quadrature_constraint);CHKERRQ(ierr); 2244 ierr = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt),&pcbddc->sizes_of_constraint);CHKERRQ(ierr); 2245 k=0; 2246 for (i=0; i<mat_graph->ncmps; i++) { 2247 if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){ 2248 pcbddc->sizes_of_constraint[k] = mat_graph->cptr[i+1]-mat_graph->cptr[i]; 2249 k++; 2250 } 2251 } 2252 // printf("check constraints %d (should be %d)\n",k,pcbddc->n_constraints); 2253 // for(i=0;i<k;i++) 2254 // printf("%d ",pcbddc->sizes_of_constraint[i]); 2255 // printf("\n"); 2256 k=0; 2257 for (i=0; i<pcbddc->n_constraints; i++) k+=pcbddc->sizes_of_constraint[i]; 2258 ierr = PetscMalloc (k*sizeof(PetscInt),&pcbddc->indices_to_constraint[0]);CHKERRQ(ierr); 2259 ierr = PetscMalloc (k*sizeof(PetscScalar),&pcbddc->quadrature_constraint[0]);CHKERRQ(ierr); 2260 for (i=1; i<pcbddc->n_constraints; i++) { 2261 pcbddc->indices_to_constraint[i] = pcbddc->indices_to_constraint[i-1] + pcbddc->sizes_of_constraint[i-1]; 2262 pcbddc->quadrature_constraint[i] = pcbddc->quadrature_constraint[i-1] + pcbddc->sizes_of_constraint[i-1]; 2263 } 2264 k=0; 2265 PetscScalar quad_value; 2266 for (i=0; i<mat_graph->ncmps; i++) { 2267 if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){ 2268 quad_value=1.0/( (PetscScalar) (mat_graph->cptr[i+1]-mat_graph->cptr[i]) ); 2269 for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) { 2270 pcbddc->indices_to_constraint[k][j] = mat_graph->queue[mat_graph->cptr[i]+j]; 2271 pcbddc->quadrature_constraint[k][j] = quad_value; 2272 } 2273 k++; 2274 } 2275 } 2276 } 2277 if(pcbddc->n_vertices){ 2278 /* allocate space for local vertices of BDDC */ 2279 ierr = PetscMalloc (pcbddc->n_vertices*sizeof(PetscInt),&pcbddc->vertices);CHKERRQ(ierr); 2280 k=0; 2281 for (i=0; i<mat_graph->ncmps; i++) { 2282 if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){ 2283 pcbddc->vertices[k] = mat_graph->queue[mat_graph->cptr[i]]; 2284 k++; 2285 } 2286 } 2287 // sort vertex set (by local ordering) 2288 ierr = PetscSortInt(pcbddc->n_vertices,pcbddc->vertices);CHKERRQ(ierr); 2289 } 2290 2291 if(pcbddc->check_flag) { 2292 PetscViewer viewer; 2293 ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);CHKERRQ(ierr); 2294 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 2295 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr); 2296 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr); 2297 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr); 2298 // PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n"); 2299 // PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n"); 2300 // for(i=0;i<mat_graph->nvtxs;i++) { 2301 // PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]); 2302 // for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){ 2303 // PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]); 2304 // } 2305 // PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n"); 2306 // } 2307 // TODO: APPLY Local to Global Mapping from IS object? 2308 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr); 2309 for(i=0;i<mat_graph->ncmps;i++) { 2310 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nSize and count for connected component %02d : %04d %01d\n", i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr); 2311 for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){ 2312 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->queue[j]);CHKERRQ(ierr); 2313 } 2314 } 2315 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr); 2316 if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); } 2317 if( nfc ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr); } 2318 if( nec ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr); } 2319 if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain vertices follows\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); } 2320 for(i=0;i<pcbddc->n_vertices;i++){ ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",pcbddc->vertices[i]);CHKERRQ(ierr); } 2321 if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr); } 2322 // if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"Indices and quadrature constraints"); 2323 // for(i=0;i<pcbddc->n_constraints;i++){ 2324 // PetscViewerASCIISynchronizedPrintf(viewer,"\nConstraint number %d\n",i); 2325 // for(j=0;j<pcbddc->sizes_of_constraint[i];j++) { 2326 // PetscViewerASCIISynchronizedPrintf(viewer,"(%d, %f) ",pcbddc->indices_to_constraint[i][j],pcbddc->quadrature_constraint[i][j]); 2327 // } 2328 // } 2329 // if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"\n"); 2330 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2331 } 2332 2333 // Restore CSR structure into sequantial matrix and free memory space no longer needed 2334 ierr = MatRestoreRowIJ(mat_adj,0,PETSC_FALSE,PETSC_TRUE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr); 2335 ierr = MatDestroy(&mat_adj);CHKERRQ(ierr); 2336 if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n"); 2337 ierr = PetscFree(distinct_values);CHKERRQ(ierr); 2338 // Free graph structure 2339 if(mat_graph->nvtxs){ 2340 ierr = PetscFree(mat_graph->where);CHKERRQ(ierr); 2341 ierr = PetscFree(mat_graph->touched);CHKERRQ(ierr); 2342 ierr = PetscFree(mat_graph->which_dof);CHKERRQ(ierr); 2343 ierr = PetscFree(mat_graph->queue);CHKERRQ(ierr); 2344 ierr = PetscFree(mat_graph->cptr);CHKERRQ(ierr); 2345 ierr = PetscFree(mat_graph->count);CHKERRQ(ierr); 2346 } 2347 ierr = PetscFree(mat_graph);CHKERRQ(ierr); 2348 2349 PetscFunctionReturn(0); 2350 2351 } 2352 2353 /* -------------------------------------------------------------------------- */ 2354 2355 /* The following code has been adapted from function IsConnectedSubdomain contained 2356 in source file contig.c of METIS library (version 5.0.1) */ 2357 2358 #undef __FUNCT__ 2359 #define __FUNCT__ "PCBDDCFindConnectedComponents" 2360 static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist, PetscInt *dist_vals) 2361 { 2362 PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid; 2363 PetscInt *xadj, *adjncy, *where, *queue; 2364 PetscInt *cptr; 2365 PetscBool *touched; 2366 2367 PetscFunctionBegin; 2368 2369 nvtxs = graph->nvtxs; 2370 xadj = graph->xadj; 2371 adjncy = graph->adjncy; 2372 where = graph->where; 2373 touched = graph->touched; 2374 queue = graph->queue; 2375 cptr = graph->cptr; 2376 2377 for (i=0; i<nvtxs; i++) 2378 touched[i] = PETSC_FALSE; 2379 2380 cum_queue=0; 2381 ncmps=0; 2382 2383 for(n=0; n<n_dist; n++) { 2384 pid = dist_vals[n]; 2385 nleft = 0; 2386 for (i=0; i<nvtxs; i++) { 2387 if (where[i] == pid) 2388 nleft++; 2389 } 2390 for (i=0; i<nvtxs; i++) { 2391 if (where[i] == pid) 2392 break; 2393 } 2394 touched[i] = PETSC_TRUE; 2395 queue[cum_queue] = i; 2396 first = 0; last = 1; 2397 cptr[ncmps] = cum_queue; /* This actually points to queue */ 2398 ncmps_pid = 0; 2399 while (first != nleft) { 2400 if (first == last) { /* Find another starting vertex */ 2401 cptr[++ncmps] = first+cum_queue; 2402 ncmps_pid++; 2403 for (i=0; i<nvtxs; i++) { 2404 if (where[i] == pid && !touched[i]) 2405 break; 2406 } 2407 queue[cum_queue+last] = i; 2408 last++; 2409 touched[i] = PETSC_TRUE; 2410 } 2411 i = queue[cum_queue+first]; 2412 first++; 2413 for (j=xadj[i]; j<xadj[i+1]; j++) { 2414 k = adjncy[j]; 2415 if (where[k] == pid && !touched[k]) { 2416 queue[cum_queue+last] = k; 2417 last++; 2418 touched[k] = PETSC_TRUE; 2419 } 2420 } 2421 } 2422 cptr[++ncmps] = first+cum_queue; 2423 ncmps_pid++; 2424 cum_queue=cptr[ncmps]; 2425 } 2426 graph->ncmps = ncmps; 2427 2428 PetscFunctionReturn(0); 2429 } 2430 2431