1 #include <petscdm.h> 2 #include <petscctable.h> 3 #include <petsc/private/matimpl.h> 4 #include <petsc/private/pcmgimpl.h> 5 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 6 7 typedef struct { 8 PC innerpc; /* A MG inner PC (Hypre or PCGAMG) to setup interpolations and coarse operators */ 9 char* innerpctype; /* PCGAMG or PCHYPRE */ 10 PetscBool reuseinterp; /* A flag indicates if or not to reuse the interpolations */ 11 PetscBool subcoarsening; /* If or not to use a subspace-based coarsening algorithm */ 12 PetscBool usematmaij; /* If or not to use MatMAIJ for saving memory */ 13 PetscInt component; /* Which subspace is used for the subspace-based coarsening algorithm? */ 14 } PC_HMG; 15 16 PetscErrorCode PCSetFromOptions_HMG(PetscOptionItems*,PC); 17 PetscErrorCode PCReset_MG(PC); 18 19 static PetscErrorCode PCHMGExtractSubMatrix_Private(Mat pmat,Mat *submat,MatReuse reuse,PetscInt component,PetscInt blocksize) 20 { 21 IS isrow; 22 PetscInt rstart,rend; 23 MPI_Comm comm; 24 25 PetscFunctionBegin; 26 CHKERRQ(PetscObjectGetComm((PetscObject)pmat,&comm)); 27 PetscCheckFalse(component>=blocksize,comm,PETSC_ERR_ARG_INCOMP,"Component %D should be less than block size %D ",component,blocksize); 28 CHKERRQ(MatGetOwnershipRange(pmat,&rstart,&rend)); 29 PetscCheckFalse((rend-rstart)%blocksize != 0,comm,PETSC_ERR_ARG_INCOMP,"Block size %D is inconsistent for [%D, %D) ",blocksize,rstart,rend); 30 CHKERRQ(ISCreateStride(comm,(rend-rstart)/blocksize,rstart+component,blocksize,&isrow)); 31 CHKERRQ(MatCreateSubMatrix(pmat,isrow,isrow,reuse,submat)); 32 CHKERRQ(ISDestroy(&isrow)); 33 PetscFunctionReturn(0); 34 } 35 36 static PetscErrorCode PCHMGExpandInterpolation_Private(Mat subinterp, Mat *interp, PetscInt blocksize) 37 { 38 PetscInt subrstart,subrend,subrowsize,subcolsize,subcstart,subcend,rowsize,colsize; 39 PetscInt subrow,row,nz,*d_nnz,*o_nnz,i,j,dnz,onz,max_nz,*indices; 40 const PetscInt *idx; 41 const PetscScalar *values; 42 MPI_Comm comm; 43 44 PetscFunctionBegin; 45 CHKERRQ(PetscObjectGetComm((PetscObject)subinterp,&comm)); 46 CHKERRQ(MatGetOwnershipRange(subinterp,&subrstart,&subrend)); 47 subrowsize = subrend-subrstart; 48 rowsize = subrowsize*blocksize; 49 CHKERRQ(PetscCalloc2(rowsize,&d_nnz,rowsize,&o_nnz)); 50 CHKERRQ(MatGetOwnershipRangeColumn(subinterp,&subcstart,&subcend)); 51 subcolsize = subcend - subcstart; 52 colsize = subcolsize*blocksize; 53 max_nz = 0; 54 for (subrow=subrstart;subrow<subrend;subrow++) { 55 CHKERRQ(MatGetRow(subinterp,subrow,&nz,&idx,NULL)); 56 if (max_nz<nz) max_nz = nz; 57 dnz = 0; onz = 0; 58 for (i=0;i<nz;i++) { 59 if (idx[i]>=subcstart && idx[i]<subcend) dnz++; 60 else onz++; 61 } 62 for (i=0;i<blocksize;i++) { 63 d_nnz[(subrow-subrstart)*blocksize+i] = dnz; 64 o_nnz[(subrow-subrstart)*blocksize+i] = onz; 65 } 66 CHKERRQ(MatRestoreRow(subinterp,subrow,&nz,&idx,NULL)); 67 } 68 CHKERRQ(MatCreateAIJ(comm,rowsize,colsize,PETSC_DETERMINE,PETSC_DETERMINE,0,d_nnz,0,o_nnz,interp)); 69 CHKERRQ(MatSetOption(*interp,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE)); 70 CHKERRQ(MatSetOption(*interp,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE)); 71 CHKERRQ(MatSetOption(*interp,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE)); 72 CHKERRQ(MatSetFromOptions(*interp)); 73 74 CHKERRQ(MatSetUp(*interp)); 75 CHKERRQ(PetscFree2(d_nnz,o_nnz)); 76 CHKERRQ(PetscMalloc1(max_nz,&indices)); 77 for (subrow=subrstart; subrow<subrend; subrow++) { 78 CHKERRQ(MatGetRow(subinterp,subrow,&nz,&idx,&values)); 79 for (i=0;i<blocksize;i++) { 80 row = subrow*blocksize+i; 81 for (j=0;j<nz;j++) { 82 indices[j] = idx[j]*blocksize+i; 83 } 84 CHKERRQ(MatSetValues(*interp,1,&row,nz,indices,values,INSERT_VALUES)); 85 } 86 CHKERRQ(MatRestoreRow(subinterp,subrow,&nz,&idx,&values)); 87 } 88 CHKERRQ(PetscFree(indices)); 89 CHKERRQ(MatAssemblyBegin(*interp,MAT_FINAL_ASSEMBLY)); 90 CHKERRQ(MatAssemblyEnd(*interp,MAT_FINAL_ASSEMBLY)); 91 PetscFunctionReturn(0); 92 } 93 94 PetscErrorCode PCSetUp_HMG(PC pc) 95 { 96 PetscErrorCode ierr; 97 Mat PA, submat; 98 PC_MG *mg = (PC_MG*)pc->data; 99 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 100 MPI_Comm comm; 101 PetscInt level; 102 PetscInt num_levels; 103 Mat *operators,*interpolations; 104 PetscInt blocksize; 105 const char *prefix; 106 PCMGGalerkinType galerkin; 107 108 PetscFunctionBegin; 109 CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm)); 110 if (pc->setupcalled) { 111 if (hmg->reuseinterp) { 112 /* If we did not use Galerkin in the last call or we have a different sparsity pattern now, 113 * we have to build from scratch 114 * */ 115 CHKERRQ(PCMGGetGalerkin(pc,&galerkin)); 116 if (galerkin == PC_MG_GALERKIN_NONE || pc->flag != SAME_NONZERO_PATTERN) pc->setupcalled = PETSC_FALSE; 117 CHKERRQ(PCMGSetGalerkin(pc,PC_MG_GALERKIN_PMAT)); 118 CHKERRQ(PCSetUp_MG(pc)); 119 PetscFunctionReturn(0); 120 } else { 121 CHKERRQ(PCReset_MG(pc)); 122 pc->setupcalled = PETSC_FALSE; 123 } 124 } 125 126 /* Create an inner PC (GAMG or HYPRE) */ 127 if (!hmg->innerpc) { 128 CHKERRQ(PCCreate(comm,&hmg->innerpc)); 129 /* If users do not set an inner pc type, we need to set a default value */ 130 if (!hmg->innerpctype) { 131 /* If hypre is available, use hypre, otherwise, use gamg */ 132 #if PETSC_HAVE_HYPRE 133 CHKERRQ(PetscStrallocpy(PCHYPRE,&(hmg->innerpctype))); 134 #else 135 CHKERRQ(PetscStrallocpy(PCGAMG,&(hmg->innerpctype))); 136 #endif 137 } 138 CHKERRQ(PCSetType(hmg->innerpc,hmg->innerpctype)); 139 } 140 CHKERRQ(PCGetOperators(pc,NULL,&PA)); 141 /* Users need to correctly set a block size of matrix in order to use subspace coarsening */ 142 CHKERRQ(MatGetBlockSize(PA,&blocksize)); 143 if (blocksize<=1) hmg->subcoarsening = PETSC_FALSE; 144 /* Extract a submatrix for constructing subinterpolations */ 145 if (hmg->subcoarsening) { 146 CHKERRQ(PCHMGExtractSubMatrix_Private(PA,&submat,MAT_INITIAL_MATRIX,hmg->component,blocksize)); 147 PA = submat; 148 } 149 CHKERRQ(PCSetOperators(hmg->innerpc,PA,PA)); 150 if (hmg->subcoarsening) { 151 CHKERRQ(MatDestroy(&PA)); 152 } 153 /* Setup inner PC correctly. During this step, matrix will be coarsened */ 154 CHKERRQ(PCSetUseAmat(hmg->innerpc,PETSC_FALSE)); 155 CHKERRQ(PetscObjectGetOptionsPrefix((PetscObject)pc,&prefix)); 156 CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)hmg->innerpc,prefix)); 157 CHKERRQ(PetscObjectAppendOptionsPrefix((PetscObject)hmg->innerpc,"hmg_inner_")); 158 CHKERRQ(PCSetFromOptions(hmg->innerpc)); 159 CHKERRQ(PCSetUp(hmg->innerpc)); 160 161 /* Obtain interpolations IN PLACE. For BoomerAMG, (I,J,data) is reused to avoid memory overhead */ 162 CHKERRQ(PCGetInterpolations(hmg->innerpc,&num_levels,&interpolations)); 163 /* We can reuse the coarse operators when we do the full space coarsening */ 164 if (!hmg->subcoarsening) { 165 CHKERRQ(PCGetCoarseOperators(hmg->innerpc,&num_levels,&operators)); 166 } 167 168 CHKERRQ(PCDestroy(&hmg->innerpc)); 169 hmg->innerpc = NULL; 170 CHKERRQ(PCMGSetLevels_MG(pc,num_levels,NULL)); 171 /* Set coarse matrices and interpolations to PCMG */ 172 for (level=num_levels-1; level>0; level--) { 173 Mat P=NULL, pmat=NULL; 174 Vec b, x,r; 175 if (hmg->subcoarsening) { 176 if (hmg->usematmaij) { 177 CHKERRQ(MatCreateMAIJ(interpolations[level-1],blocksize,&P)); 178 CHKERRQ(MatDestroy(&interpolations[level-1])); 179 } else { 180 /* Grow interpolation. In the future, we should use MAIJ */ 181 CHKERRQ(PCHMGExpandInterpolation_Private(interpolations[level-1],&P,blocksize)); 182 CHKERRQ(MatDestroy(&interpolations[level-1])); 183 } 184 } else { 185 P = interpolations[level-1]; 186 } 187 CHKERRQ(MatCreateVecs(P,&b,&r)); 188 CHKERRQ(PCMGSetInterpolation(pc,level,P)); 189 CHKERRQ(PCMGSetRestriction(pc,level,P)); 190 CHKERRQ(MatDestroy(&P)); 191 /* We reuse the matrices when we do not do subspace coarsening */ 192 if ((level-1)>=0 && !hmg->subcoarsening) { 193 pmat = operators[level-1]; 194 CHKERRQ(PCMGSetOperators(pc,level-1,pmat,pmat)); 195 CHKERRQ(MatDestroy(&pmat)); 196 } 197 CHKERRQ(PCMGSetRhs(pc,level-1,b)); 198 199 CHKERRQ(PCMGSetR(pc,level,r)); 200 CHKERRQ(VecDestroy(&r)); 201 202 CHKERRQ(VecDuplicate(b,&x)); 203 CHKERRQ(PCMGSetX(pc,level-1,x)); 204 CHKERRQ(VecDestroy(&x)); 205 CHKERRQ(VecDestroy(&b)); 206 } 207 CHKERRQ(PetscFree(interpolations)); 208 if (!hmg->subcoarsening) { 209 CHKERRQ(PetscFree(operators)); 210 } 211 /* Turn Galerkin off when we already have coarse operators */ 212 CHKERRQ(PCMGSetGalerkin(pc,hmg->subcoarsening ? PC_MG_GALERKIN_PMAT:PC_MG_GALERKIN_NONE)); 213 CHKERRQ(PCSetDM(pc,NULL)); 214 CHKERRQ(PCSetUseAmat(pc,PETSC_FALSE)); 215 ierr = PetscObjectOptionsBegin((PetscObject)pc);CHKERRQ(ierr); 216 CHKERRQ(PCSetFromOptions_MG(PetscOptionsObject,pc)); /* should be called in PCSetFromOptions_HMG(), but cannot be called prior to PCMGSetLevels() */ 217 ierr = PetscOptionsEnd();CHKERRQ(ierr); 218 CHKERRQ(PCSetUp_MG(pc)); 219 PetscFunctionReturn(0); 220 } 221 222 PetscErrorCode PCDestroy_HMG(PC pc) 223 { 224 PC_MG *mg = (PC_MG*)pc->data; 225 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 226 227 PetscFunctionBegin; 228 CHKERRQ(PCDestroy(&hmg->innerpc)); 229 CHKERRQ(PetscFree(hmg->innerpctype)); 230 CHKERRQ(PetscFree(hmg)); 231 CHKERRQ(PCDestroy_MG(pc)); 232 233 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetReuseInterpolation_C",NULL)); 234 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetUseSubspaceCoarsening_C",NULL)); 235 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetInnerPCType_C",NULL)); 236 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetCoarseningComponent_C",NULL)); 237 PetscFunctionReturn(0); 238 } 239 240 PetscErrorCode PCView_HMG(PC pc,PetscViewer viewer) 241 { 242 PC_MG *mg = (PC_MG*)pc->data; 243 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 244 PetscBool iascii; 245 246 PetscFunctionBegin; 247 CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 248 if (iascii) { 249 CHKERRQ(PetscViewerASCIIPrintf(viewer," Reuse interpolation: %s\n",hmg->reuseinterp? "true":"false")); 250 CHKERRQ(PetscViewerASCIIPrintf(viewer," Use subspace coarsening: %s\n",hmg->subcoarsening? "true":"false")); 251 CHKERRQ(PetscViewerASCIIPrintf(viewer," Coarsening component: %D \n",hmg->component)); 252 CHKERRQ(PetscViewerASCIIPrintf(viewer," Use MatMAIJ: %s \n",hmg->usematmaij? "true":"false")); 253 CHKERRQ(PetscViewerASCIIPrintf(viewer," Inner PC type: %s \n",hmg->innerpctype)); 254 } 255 CHKERRQ(PCView_MG(pc,viewer)); 256 PetscFunctionReturn(0); 257 } 258 259 PetscErrorCode PCSetFromOptions_HMG(PetscOptionItems *PetscOptionsObject,PC pc) 260 { 261 PC_MG *mg = (PC_MG*)pc->data; 262 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 263 264 PetscFunctionBegin; 265 CHKERRQ(PetscOptionsHead(PetscOptionsObject,"HMG")); 266 CHKERRQ(PetscOptionsBool("-pc_hmg_reuse_interpolation","Reuse the interpolation operators when possible (cheaper, weaker when matrix entries change a lot)","PCHMGSetReuseInterpolation",hmg->reuseinterp,&hmg->reuseinterp,NULL)); 267 CHKERRQ(PetscOptionsBool("-pc_hmg_use_subspace_coarsening","Use the subspace coarsening to compute the interpolations","PCHMGSetUseSubspaceCoarsening",hmg->subcoarsening,&hmg->subcoarsening,NULL)); 268 CHKERRQ(PetscOptionsBool("-pc_hmg_use_matmaij","Use MatMAIJ store interpolation for saving memory","PCHMGSetInnerPCType",hmg->usematmaij,&hmg->usematmaij,NULL)); 269 CHKERRQ(PetscOptionsInt("-pc_hmg_coarsening_component","Which component is chosen for the subspace-based coarsening algorithm","PCHMGSetCoarseningComponent",hmg->component,&hmg->component,NULL)); 270 CHKERRQ(PetscOptionsTail()); 271 PetscFunctionReturn(0); 272 } 273 274 static PetscErrorCode PCHMGSetReuseInterpolation_HMG(PC pc, PetscBool reuse) 275 { 276 PC_MG *mg = (PC_MG*)pc->data; 277 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 278 279 PetscFunctionBegin; 280 hmg->reuseinterp = reuse; 281 PetscFunctionReturn(0); 282 } 283 284 /*@ 285 PCHMGSetReuseInterpolation - Reuse interpolation matrices in HMG 286 287 Logically Collective on PC 288 289 Input Parameters: 290 + pc - the HMG context 291 - reuse - True indicates that HMG will reuse the interpolations 292 293 Options Database Keys: 294 . -pc_hmg_reuse_interpolation <true | false> - Whether or not to reuse the interpolations. If true, it potentially save the compute time. 295 296 Level: beginner 297 298 .keywords: HMG, multigrid, interpolation, reuse, set 299 300 .seealso: PCHMG 301 @*/ 302 PetscErrorCode PCHMGSetReuseInterpolation(PC pc, PetscBool reuse) 303 { 304 PetscFunctionBegin; 305 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 306 CHKERRQ(PetscUseMethod(pc,"PCHMGSetReuseInterpolation_C",(PC,PetscBool),(pc,reuse))); 307 PetscFunctionReturn(0); 308 } 309 310 static PetscErrorCode PCHMGSetUseSubspaceCoarsening_HMG(PC pc, PetscBool subspace) 311 { 312 PC_MG *mg = (PC_MG*)pc->data; 313 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 314 315 PetscFunctionBegin; 316 hmg->subcoarsening = subspace; 317 PetscFunctionReturn(0); 318 } 319 320 /*@ 321 PCHMGSetUseSubspaceCoarsening - Use subspace coarsening in HMG 322 323 Logically Collective on PC 324 325 Input Parameters: 326 + pc - the HMG context 327 - reuse - True indicates that HMG will use the subspace coarsening 328 329 Options Database Keys: 330 . -pc_hmg_use_subspace_coarsening <true | false> - Whether or not to use subspace coarsening (that is, coarsen a submatrix). 331 332 Level: beginner 333 334 .keywords: HMG, multigrid, interpolation, subspace, coarsening 335 336 .seealso: PCHMG 337 @*/ 338 PetscErrorCode PCHMGSetUseSubspaceCoarsening(PC pc, PetscBool subspace) 339 { 340 PetscFunctionBegin; 341 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 342 CHKERRQ(PetscUseMethod(pc,"PCHMGSetUseSubspaceCoarsening_C",(PC,PetscBool),(pc,subspace))); 343 PetscFunctionReturn(0); 344 } 345 346 static PetscErrorCode PCHMGSetInnerPCType_HMG(PC pc, PCType type) 347 { 348 PC_MG *mg = (PC_MG*)pc->data; 349 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 350 351 PetscFunctionBegin; 352 CHKERRQ(PetscStrallocpy(type,&(hmg->innerpctype))); 353 PetscFunctionReturn(0); 354 } 355 356 /*@C 357 PCHMGSetInnerPCType - Set an inner PC type 358 359 Logically Collective on PC 360 361 Input Parameters: 362 + pc - the HMG context 363 - type - <hypre, gamg> coarsening algorithm 364 365 Options Database Keys: 366 . -hmg_inner_pc_type <hypre, gamg> - What method is used to coarsen matrix 367 368 Level: beginner 369 370 .keywords: HMG, multigrid, interpolation, coarsening 371 372 .seealso: PCHMG, PCType 373 @*/ 374 PetscErrorCode PCHMGSetInnerPCType(PC pc, PCType type) 375 { 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 378 CHKERRQ(PetscUseMethod(pc,"PCHMGSetInnerPCType_C",(PC,PCType),(pc,type))); 379 PetscFunctionReturn(0); 380 } 381 382 static PetscErrorCode PCHMGSetCoarseningComponent_HMG(PC pc, PetscInt component) 383 { 384 PC_MG *mg = (PC_MG*)pc->data; 385 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 386 387 PetscFunctionBegin; 388 hmg->component = component; 389 PetscFunctionReturn(0); 390 } 391 392 /*@ 393 PCHMGSetCoarseningComponent - Set which component is used for the subspace-based coarsening algorithm 394 395 Logically Collective on PC 396 397 Input Parameters: 398 + pc - the HMG context 399 - component - which component PC will coarsen 400 401 Options Database Keys: 402 . -pc_hmg_coarsening_component - Which component is chosen for the subspace-based coarsening algorithm 403 404 Level: beginner 405 406 .keywords: HMG, multigrid, interpolation, coarsening, component 407 408 .seealso: PCHMG, PCType 409 @*/ 410 PetscErrorCode PCHMGSetCoarseningComponent(PC pc, PetscInt component) 411 { 412 PetscFunctionBegin; 413 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 414 CHKERRQ(PetscUseMethod(pc,"PCHMGSetCoarseningComponent_C",(PC,PetscInt),(pc,component))); 415 PetscFunctionReturn(0); 416 } 417 418 static PetscErrorCode PCHMGUseMatMAIJ_HMG(PC pc, PetscBool usematmaij) 419 { 420 PC_MG *mg = (PC_MG*)pc->data; 421 PC_HMG *hmg = (PC_HMG*) mg->innerctx; 422 423 PetscFunctionBegin; 424 hmg->usematmaij = usematmaij; 425 PetscFunctionReturn(0); 426 } 427 428 /*@ 429 PCHMGUseMatMAIJ - Set a flag that indicates if or not to use MatMAIJ for interpolations for saving memory 430 431 Logically Collective on PC 432 433 Input Parameters: 434 + pc - the HMG context 435 - usematmaij - if or not to use MatMAIJ for interpolations. By default, it is true for saving memory 436 437 Options Database Keys: 438 . -pc_hmg_use_matmaij - <true | false > 439 440 Level: beginner 441 442 .keywords: HMG, multigrid, interpolation, coarsening, MatMAIJ 443 444 .seealso: PCHMG, PCType 445 @*/ 446 PetscErrorCode PCHMGUseMatMAIJ(PC pc, PetscBool usematmaij) 447 { 448 PetscFunctionBegin; 449 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 450 CHKERRQ(PetscUseMethod(pc,"PCHMGUseMatMAIJ_C",(PC,PetscBool),(pc,usematmaij))); 451 PetscFunctionReturn(0); 452 } 453 454 /*MC 455 PCHMG - Hybrid of PETSc preconditioners (such as ASM, BJacobi, SOR, etc.) and Hypre BoomerAMG, GAMG or other multilevel methods. BoomerAMG, GAMG 456 or other multilevel methods is used to coarsen matrix and generate a sequence of coarse matrices and interpolations. The matrices and 457 interpolations are employed to construct PCMG, and then any available PETSc preconditioners can be chosen as smoothers and the coarse solver. 458 459 Options Database Keys: 460 + -pc_hmg_reuse_interpolation <true | false> - Whether or not to reuse the interpolations. If true, it potentially save the compute time. 461 . -pc_hmg_use_subspace_coarsening <true | false> - Whether or not to use subspace coarsening (that is, coarsen a submatrix). 462 . -hmg_inner_pc_type <hypre, gamg, ...> - What method is used to coarsen matrix 463 - -pc_hmg_use_matmaij <true | false> - Whether or not to use MatMAIJ for multicomponent problems for saving memory 464 465 Notes: 466 For multicomponent problems, we can just coarsen one submatrix associated with one particular component. In this way, the preconditioner setup 467 time is significantly reduced. One typical use case is neutron transport equations. There are many variables on each mesh vertex due to the 468 of angle and energy. Each variable, in fact, corresponds to the same PDEs but with different material properties. 469 470 Level: beginner 471 472 Concepts: Hybrid of ASM and MG, Subspace Coarsening 473 474 References: 475 . * - Fande Kong, Yaqi Wang, Derek R Gaston, Cody J Permann, Andrew E Slaughter, Alexander D Lindsay, Richard C Martineau, A highly parallel multilevel 476 Newton-Krylov-Schwarz method with subspace-based coarsening and partition-based balancing for the multigroup neutron transport equations on 477 3D unstructured meshes, arXiv preprint arXiv:1903.03659, 2019 478 479 .seealso: PCCreate(), PCSetType(), PCType, PC, PCMG, PCHYPRE, PCHMG, PCGetCoarseOperators(), PCGetInterpolations(), PCHMGSetReuseInterpolation(), PCHMGSetUseSubspaceCoarsening(), 480 PCHMGSetInnerPCType() 481 482 M*/ 483 PETSC_EXTERN PetscErrorCode PCCreate_HMG(PC pc) 484 { 485 PC_HMG *hmg; 486 PC_MG *mg; 487 488 PetscFunctionBegin; 489 /* if type was previously mg; must manually destroy it because call to PCSetType(pc,PCMG) will not destroy it */ 490 if (pc->ops->destroy) { 491 CHKERRQ((*pc->ops->destroy)(pc)); 492 pc->data = NULL; 493 } 494 CHKERRQ(PetscFree(((PetscObject)pc)->type_name)); 495 496 CHKERRQ(PCSetType(pc,PCMG)); 497 CHKERRQ(PetscObjectChangeTypeName((PetscObject)pc, PCHMG)); 498 CHKERRQ(PetscNew(&hmg)); 499 500 mg = (PC_MG*) pc->data; 501 mg->innerctx = hmg; 502 hmg->reuseinterp = PETSC_FALSE; 503 hmg->subcoarsening = PETSC_FALSE; 504 hmg->usematmaij = PETSC_TRUE; 505 hmg->component = 0; 506 hmg->innerpc = NULL; 507 508 pc->ops->setfromoptions = PCSetFromOptions_HMG; 509 pc->ops->view = PCView_HMG; 510 pc->ops->destroy = PCDestroy_HMG; 511 pc->ops->setup = PCSetUp_HMG; 512 513 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetReuseInterpolation_C",PCHMGSetReuseInterpolation_HMG)); 514 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetUseSubspaceCoarsening_C",PCHMGSetUseSubspaceCoarsening_HMG)); 515 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetInnerPCType_C",PCHMGSetInnerPCType_HMG)); 516 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGSetCoarseningComponent_C",PCHMGSetCoarseningComponent_HMG)); 517 CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCHMGUseMatMAIJ_C",PCHMGUseMatMAIJ_HMG)); 518 PetscFunctionReturn(0); 519 } 520