1 #include <petsc/private/dmforestimpl.h> /*I "petscdmforest.h" I*/ 2 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 3 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 4 #include <petscsf.h> 5 6 PetscBool DMForestPackageInitialized = PETSC_FALSE; 7 8 typedef struct _DMForestTypeLink*DMForestTypeLink; 9 10 struct _DMForestTypeLink 11 { 12 char *name; 13 DMForestTypeLink next; 14 }; 15 16 DMForestTypeLink DMForestTypeList; 17 18 static PetscErrorCode DMForestPackageFinalize(void) 19 { 20 DMForestTypeLink oldLink, link = DMForestTypeList; 21 PetscErrorCode ierr; 22 23 PetscFunctionBegin; 24 while (link) { 25 oldLink = link; 26 ierr = PetscFree(oldLink->name);CHKERRQ(ierr); 27 link = oldLink->next; 28 ierr = PetscFree(oldLink);CHKERRQ(ierr); 29 } 30 PetscFunctionReturn(0); 31 } 32 33 static PetscErrorCode DMForestPackageInitialize(void) 34 { 35 PetscErrorCode ierr; 36 37 PetscFunctionBegin; 38 if (DMForestPackageInitialized) PetscFunctionReturn(0); 39 DMForestPackageInitialized = PETSC_TRUE; 40 41 ierr = DMForestRegisterType(DMFOREST);CHKERRQ(ierr); 42 ierr = PetscRegisterFinalize(DMForestPackageFinalize);CHKERRQ(ierr); 43 PetscFunctionReturn(0); 44 } 45 46 /*@C 47 DMForestRegisterType - Registers a DMType as a subtype of DMFOREST (so that DMIsForest() will be correct) 48 49 Not Collective 50 51 Input parameter: 52 . name - the name of the type 53 54 Level: advanced 55 56 .seealso: DMFOREST, DMIsForest() 57 @*/ 58 PetscErrorCode DMForestRegisterType(DMType name) 59 { 60 DMForestTypeLink link; 61 PetscErrorCode ierr; 62 63 PetscFunctionBegin; 64 ierr = DMForestPackageInitialize();CHKERRQ(ierr); 65 ierr = PetscNew(&link);CHKERRQ(ierr); 66 ierr = PetscStrallocpy(name,&link->name);CHKERRQ(ierr); 67 link->next = DMForestTypeList; 68 DMForestTypeList = link; 69 PetscFunctionReturn(0); 70 } 71 72 /*@ 73 DMIsForest - Check whether a DM uses the DMFOREST interface for hierarchically-refined meshes 74 75 Not Collective 76 77 Input parameter: 78 . dm - the DM object 79 80 Output parameter: 81 . isForest - whether dm is a subtype of DMFOREST 82 83 Level: intermediate 84 85 .seealso: DMFOREST, DMForestRegisterType() 86 @*/ 87 PetscErrorCode DMIsForest(DM dm, PetscBool *isForest) 88 { 89 DMForestTypeLink link = DMForestTypeList; 90 PetscErrorCode ierr; 91 92 PetscFunctionBegin; 93 while (link) { 94 PetscBool sameType; 95 ierr = PetscObjectTypeCompare((PetscObject)dm,link->name,&sameType);CHKERRQ(ierr); 96 if (sameType) { 97 *isForest = PETSC_TRUE; 98 PetscFunctionReturn(0); 99 } 100 link = link->next; 101 } 102 *isForest = PETSC_FALSE; 103 PetscFunctionReturn(0); 104 } 105 106 /*@ 107 DMForestTemplate - Create a new DM that will be adapted from a source DM. The new DM reproduces the configuration 108 of the source, but is not yet setup, so that the user can then define only the ways that the new DM should differ 109 (by, e.g., refinement or repartitioning). The source DM is also set as the adaptivity source DM of the new DM (see 110 DMForestSetAdaptivityForest()). 111 112 Collective on dm 113 114 Input Parameters: 115 + dm - the source DM object 116 - comm - the communicator for the new DM (this communicator is currently ignored, but is present so that DMForestTemplate() can be used within DMCoarsen()) 117 118 Output Parameter: 119 . tdm - the new DM object 120 121 Level: intermediate 122 123 .seealso: DMForestSetAdaptivityForest() 124 @*/ 125 PetscErrorCode DMForestTemplate(DM dm, MPI_Comm comm, DM *tdm) 126 { 127 DM_Forest *forest = (DM_Forest*) dm->data; 128 DMType type; 129 DM base; 130 DMForestTopology topology; 131 MatType mtype; 132 PetscInt dim, overlap, ref, factor; 133 DMForestAdaptivityStrategy strat; 134 void *ctx; 135 PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void*); 136 void *mapCtx; 137 PetscErrorCode ierr; 138 139 PetscFunctionBegin; 140 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 141 ierr = DMCreate(PetscObjectComm((PetscObject)dm),tdm);CHKERRQ(ierr); 142 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 143 ierr = DMSetType(*tdm,type);CHKERRQ(ierr); 144 ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr); 145 ierr = DMForestSetBaseDM(*tdm,base);CHKERRQ(ierr); 146 ierr = DMForestGetTopology(dm,&topology);CHKERRQ(ierr); 147 ierr = DMForestSetTopology(*tdm,topology);CHKERRQ(ierr); 148 ierr = DMForestGetAdjacencyDimension(dm,&dim);CHKERRQ(ierr); 149 ierr = DMForestSetAdjacencyDimension(*tdm,dim);CHKERRQ(ierr); 150 ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr); 151 ierr = DMForestSetPartitionOverlap(*tdm,overlap);CHKERRQ(ierr); 152 ierr = DMForestGetMinimumRefinement(dm,&ref);CHKERRQ(ierr); 153 ierr = DMForestSetMinimumRefinement(*tdm,ref);CHKERRQ(ierr); 154 ierr = DMForestGetMaximumRefinement(dm,&ref);CHKERRQ(ierr); 155 ierr = DMForestSetMaximumRefinement(*tdm,ref);CHKERRQ(ierr); 156 ierr = DMForestGetAdaptivityStrategy(dm,&strat);CHKERRQ(ierr); 157 ierr = DMForestSetAdaptivityStrategy(*tdm,strat);CHKERRQ(ierr); 158 ierr = DMForestGetGradeFactor(dm,&factor);CHKERRQ(ierr); 159 ierr = DMForestSetGradeFactor(*tdm,factor);CHKERRQ(ierr); 160 ierr = DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx);CHKERRQ(ierr); 161 ierr = DMForestSetBaseCoordinateMapping(*tdm,map,mapCtx);CHKERRQ(ierr); 162 if (forest->ftemplate) { 163 ierr = (*forest->ftemplate)(dm, *tdm);CHKERRQ(ierr); 164 } 165 ierr = DMForestSetAdaptivityForest(*tdm,dm);CHKERRQ(ierr); 166 ierr = DMCopyDisc(dm,*tdm);CHKERRQ(ierr); 167 ierr = DMGetApplicationContext(dm,&ctx);CHKERRQ(ierr); 168 ierr = DMSetApplicationContext(*tdm,&ctx);CHKERRQ(ierr); 169 { 170 PetscBool isper; 171 const PetscReal *maxCell, *L; 172 const DMBoundaryType *bd; 173 174 ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 175 ierr = DMSetPeriodicity(*tdm,isper,maxCell,L,bd);CHKERRQ(ierr); 176 } 177 ierr = DMCopyBoundary(dm,*tdm);CHKERRQ(ierr); 178 ierr = DMGetMatType(dm,&mtype);CHKERRQ(ierr); 179 ierr = DMSetMatType(*tdm,mtype);CHKERRQ(ierr); 180 PetscFunctionReturn(0); 181 } 182 183 static PetscErrorCode DMInitialize_Forest(DM dm); 184 185 PETSC_EXTERN PetscErrorCode DMClone_Forest(DM dm, DM *newdm) 186 { 187 DM_Forest *forest = (DM_Forest*) dm->data; 188 const char *type; 189 PetscErrorCode ierr; 190 191 PetscFunctionBegin; 192 forest->refct++; 193 (*newdm)->data = forest; 194 ierr = PetscObjectGetType((PetscObject) dm, &type);CHKERRQ(ierr); 195 ierr = PetscObjectChangeTypeName((PetscObject) *newdm, type);CHKERRQ(ierr); 196 ierr = DMInitialize_Forest(*newdm);CHKERRQ(ierr); 197 PetscFunctionReturn(0); 198 } 199 200 static PetscErrorCode DMDestroy_Forest(DM dm) 201 { 202 DM_Forest *forest = (DM_Forest*) dm->data; 203 PetscErrorCode ierr; 204 205 PetscFunctionBegin; 206 if (--forest->refct > 0) PetscFunctionReturn(0); 207 if (forest->destroy) {ierr = (*forest->destroy)(dm);CHKERRQ(ierr);} 208 ierr = PetscSFDestroy(&forest->cellSF);CHKERRQ(ierr); 209 ierr = PetscSFDestroy(&forest->preCoarseToFine);CHKERRQ(ierr); 210 ierr = PetscSFDestroy(&forest->coarseToPreFine);CHKERRQ(ierr); 211 ierr = DMLabelDestroy(&forest->adaptLabel);CHKERRQ(ierr); 212 ierr = PetscFree(forest->adaptStrategy);CHKERRQ(ierr); 213 ierr = DMDestroy(&forest->base);CHKERRQ(ierr); 214 ierr = DMDestroy(&forest->adapt);CHKERRQ(ierr); 215 ierr = PetscFree(forest->topology);CHKERRQ(ierr); 216 ierr = PetscFree(forest);CHKERRQ(ierr); 217 PetscFunctionReturn(0); 218 } 219 220 /*@C 221 DMForestSetTopology - Set the topology of a DMForest during the pre-setup phase. The topology is a string (e.g. 222 "cube", "shell") and can be interpreted by subtypes of DMFOREST) to construct the base DM of a forest during 223 DMSetUp(). 224 225 Logically collective on dm 226 227 Input parameters: 228 + dm - the forest 229 - topology - the topology of the forest 230 231 Level: intermediate 232 233 .seealso: DMForestGetTopology(), DMForestSetBaseDM() 234 @*/ 235 PetscErrorCode DMForestSetTopology(DM dm, DMForestTopology topology) 236 { 237 DM_Forest *forest = (DM_Forest*) dm->data; 238 PetscErrorCode ierr; 239 240 PetscFunctionBegin; 241 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 242 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the topology after setup"); 243 ierr = PetscFree(forest->topology);CHKERRQ(ierr); 244 ierr = PetscStrallocpy((const char*)topology,(char**) &forest->topology);CHKERRQ(ierr); 245 PetscFunctionReturn(0); 246 } 247 248 /*@C 249 DMForestGetTopology - Get a string describing the topology of a DMForest. 250 251 Not collective 252 253 Input parameter: 254 . dm - the forest 255 256 Output parameter: 257 . topology - the topology of the forest (e.g., 'cube', 'shell') 258 259 Level: intermediate 260 261 .seealso: DMForestSetTopology() 262 @*/ 263 PetscErrorCode DMForestGetTopology(DM dm, DMForestTopology *topology) 264 { 265 DM_Forest *forest = (DM_Forest*) dm->data; 266 267 PetscFunctionBegin; 268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 269 PetscValidPointer(topology,2); 270 *topology = forest->topology; 271 PetscFunctionReturn(0); 272 } 273 274 /*@ 275 DMForestSetBaseDM - During the pre-setup phase, set the DM that defines the base mesh of a DMForest forest. The 276 forest will be hierarchically refined from the base, and all refinements/coarsenings of the forest will share its 277 base. In general, two forest must share a base to be comparable, to do things like construct interpolators. 278 279 Logically collective on dm 280 281 Input Parameters: 282 + dm - the forest 283 - base - the base DM of the forest 284 285 Notes: 286 Currently the base DM must be a DMPLEX 287 288 Level: intermediate 289 290 .seealso: DMForestGetBaseDM() 291 @*/ 292 PetscErrorCode DMForestSetBaseDM(DM dm, DM base) 293 { 294 DM_Forest *forest = (DM_Forest*) dm->data; 295 PetscInt dim, dimEmbed; 296 PetscErrorCode ierr; 297 298 PetscFunctionBegin; 299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 300 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the base after setup"); 301 ierr = PetscObjectReference((PetscObject)base);CHKERRQ(ierr); 302 ierr = DMDestroy(&forest->base);CHKERRQ(ierr); 303 forest->base = base; 304 if (base) { 305 PetscBool isper; 306 const PetscReal *maxCell, *L; 307 const DMBoundaryType *bd; 308 309 PetscValidHeaderSpecific(base, DM_CLASSID, 2); 310 ierr = DMGetDimension(base,&dim);CHKERRQ(ierr); 311 ierr = DMSetDimension(dm,dim);CHKERRQ(ierr); 312 ierr = DMGetCoordinateDim(base,&dimEmbed);CHKERRQ(ierr); 313 ierr = DMSetCoordinateDim(dm,dimEmbed);CHKERRQ(ierr); 314 ierr = DMGetPeriodicity(base,&isper,&maxCell,&L,&bd);CHKERRQ(ierr); 315 ierr = DMSetPeriodicity(dm,isper,maxCell,L,bd);CHKERRQ(ierr); 316 } else { 317 ierr = DMSetPeriodicity(dm,PETSC_FALSE,NULL,NULL,NULL);CHKERRQ(ierr); 318 } 319 PetscFunctionReturn(0); 320 } 321 322 /*@ 323 DMForestGetBaseDM - Get the base DM of a DMForest forest. The forest will be hierarchically refined from the base, 324 and all refinements/coarsenings of the forest will share its base. In general, two forest must share a base to be 325 comparable, to do things like construct interpolators. 326 327 Not collective 328 329 Input Parameter: 330 . dm - the forest 331 332 Output Parameter: 333 . base - the base DM of the forest 334 335 Notes: 336 After DMSetUp(), the base DM will be redundantly distributed across MPI processes 337 338 Level: intermediate 339 340 .seealso: DMForestSetBaseDM() 341 @*/ 342 PetscErrorCode DMForestGetBaseDM(DM dm, DM *base) 343 { 344 DM_Forest *forest = (DM_Forest*) dm->data; 345 346 PetscFunctionBegin; 347 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 348 PetscValidPointer(base, 2); 349 *base = forest->base; 350 PetscFunctionReturn(0); 351 } 352 353 PetscErrorCode DMForestSetBaseCoordinateMapping(DM dm, PetscErrorCode (*func)(DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx) 354 { 355 DM_Forest *forest = (DM_Forest*) dm->data; 356 357 PetscFunctionBegin; 358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 359 forest->mapcoordinates = func; 360 forest->mapcoordinatesctx = ctx; 361 PetscFunctionReturn(0); 362 } 363 364 PetscErrorCode DMForestGetBaseCoordinateMapping(DM dm, PetscErrorCode (**func) (DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx) 365 { 366 DM_Forest *forest = (DM_Forest*) dm->data; 367 368 PetscFunctionBegin; 369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 370 if (func) *func = forest->mapcoordinates; 371 if (ctx) *((void**) ctx) = forest->mapcoordinatesctx; 372 PetscFunctionReturn(0); 373 } 374 375 /*@ 376 DMForestSetAdaptivityForest - During the pre-setup phase, set the forest from which the current forest will be 377 adapted (e.g., the current forest will be refined/coarsened/repartitioned from it) im DMSetUp(). Usually not needed 378 by users directly: DMForestTemplate() constructs a new forest to be adapted from an old forest and calls this 379 routine. 380 381 Note that this can be called after setup with adapt = NULL, which will clear all internal data related to the 382 adaptivity forest from dm. This way, repeatedly adapting does not leave stale DM objects in memory. 383 384 Logically collective on dm 385 386 Input Parameter: 387 + dm - the new forest, which will be constructed from adapt 388 - adapt - the old forest 389 390 Level: intermediate 391 392 .seealso: DMForestGetAdaptivityForest(), DMForestSetAdaptivityPurpose() 393 @*/ 394 PetscErrorCode DMForestSetAdaptivityForest(DM dm,DM adapt) 395 { 396 DM_Forest *forest, *adaptForest, *oldAdaptForest; 397 DM oldAdapt; 398 PetscBool isForest; 399 PetscErrorCode ierr; 400 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 403 if (adapt) PetscValidHeaderSpecific(adapt, DM_CLASSID, 2); 404 ierr = DMIsForest(dm, &isForest);CHKERRQ(ierr); 405 if (!isForest) PetscFunctionReturn(0); 406 if (adapt != NULL && dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adaptation forest after setup"); 407 forest = (DM_Forest*) dm->data; 408 ierr = DMForestGetAdaptivityForest(dm,&oldAdapt);CHKERRQ(ierr); 409 adaptForest = (DM_Forest*) (adapt ? adapt->data : NULL); 410 oldAdaptForest = (DM_Forest*) (oldAdapt ? oldAdapt->data : NULL); 411 if (adaptForest != oldAdaptForest) { 412 ierr = PetscSFDestroy(&forest->preCoarseToFine);CHKERRQ(ierr); 413 ierr = PetscSFDestroy(&forest->coarseToPreFine);CHKERRQ(ierr); 414 if (forest->clearadaptivityforest) {ierr = (*forest->clearadaptivityforest)(dm);CHKERRQ(ierr);} 415 } 416 switch (forest->adaptPurpose) { 417 case DM_ADAPT_DETERMINE: 418 ierr = PetscObjectReference((PetscObject)adapt);CHKERRQ(ierr); 419 ierr = DMDestroy(&(forest->adapt));CHKERRQ(ierr); 420 forest->adapt = adapt; 421 break; 422 case DM_ADAPT_REFINE: 423 ierr = DMSetCoarseDM(dm,adapt);CHKERRQ(ierr); 424 break; 425 case DM_ADAPT_COARSEN: 426 case DM_ADAPT_COARSEN_LAST: 427 ierr = DMSetFineDM(dm,adapt);CHKERRQ(ierr); 428 break; 429 default: 430 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose"); 431 } 432 PetscFunctionReturn(0); 433 } 434 435 /*@ 436 DMForestGetAdaptivityForest - Get the forest from which the current forest is adapted. 437 438 Not collective 439 440 Input Parameter: 441 . dm - the forest 442 443 Output Parameter: 444 . adapt - the forest from which dm is/was adapted 445 446 Level: intermediate 447 448 .seealso: DMForestSetAdaptivityForest(), DMForestSetAdaptivityPurpose() 449 @*/ 450 PetscErrorCode DMForestGetAdaptivityForest(DM dm, DM *adapt) 451 { 452 DM_Forest *forest; 453 PetscErrorCode ierr; 454 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 457 forest = (DM_Forest*) dm->data; 458 switch (forest->adaptPurpose) { 459 case DM_ADAPT_DETERMINE: 460 *adapt = forest->adapt; 461 break; 462 case DM_ADAPT_REFINE: 463 ierr = DMGetCoarseDM(dm,adapt);CHKERRQ(ierr); 464 break; 465 case DM_ADAPT_COARSEN: 466 case DM_ADAPT_COARSEN_LAST: 467 ierr = DMGetFineDM(dm,adapt);CHKERRQ(ierr); 468 break; 469 default: 470 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose"); 471 } 472 PetscFunctionReturn(0); 473 } 474 475 /*@ 476 DMForestSetAdaptivityPurpose - During the pre-setup phase, set whether the current DM is being adapted from its 477 source (set with DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening 478 (DM_ADAPT_COARSEN), or undefined (DM_ADAPT_DETERMINE). This only matters for the purposes of reference counting: 479 during DMDestroy(), cyclic references can be found between DMs only if the cyclic reference is due to a fine/coarse 480 relationship (see DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does 481 not maintain a reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can 482 cause a memory leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies. 483 484 Logically collective on dm 485 486 Input Parameters: 487 + dm - the forest 488 - purpose - the adaptivity purpose 489 490 Level: advanced 491 492 .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest(), DMAdaptFlag 493 @*/ 494 PetscErrorCode DMForestSetAdaptivityPurpose(DM dm, DMAdaptFlag purpose) 495 { 496 DM_Forest *forest; 497 PetscErrorCode ierr; 498 499 PetscFunctionBegin; 500 forest = (DM_Forest*) dm->data; 501 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adaptation forest after setup"); 502 if (purpose != forest->adaptPurpose) { 503 DM adapt; 504 505 ierr = DMForestGetAdaptivityForest(dm,&adapt);CHKERRQ(ierr); 506 ierr = PetscObjectReference((PetscObject)adapt);CHKERRQ(ierr); 507 ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr); 508 509 forest->adaptPurpose = purpose; 510 511 ierr = DMForestSetAdaptivityForest(dm,adapt);CHKERRQ(ierr); 512 ierr = DMDestroy(&adapt);CHKERRQ(ierr); 513 } 514 PetscFunctionReturn(0); 515 } 516 517 /*@ 518 DMForestGetAdaptivityPurpose - Get whether the current DM is being adapted from its source (set with 519 DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening (DM_ADAPT_COARSEN), 520 coarsening only the last level (DM_ADAPT_COARSEN_LAST) or undefined (DM_ADAPT_DETERMINE). 521 This only matters for the purposes of reference counting: during DMDestroy(), cyclic 522 references can be found between DMs only if the cyclic reference is due to a fine/coarse relationship (see 523 DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does not maintain a 524 reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can cause a memory 525 leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies. 526 527 Not collective 528 529 Input Parameter: 530 . dm - the forest 531 532 Output Parameter: 533 . purpose - the adaptivity purpose 534 535 Level: advanced 536 537 .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest(), DMAdaptFlag 538 @*/ 539 PetscErrorCode DMForestGetAdaptivityPurpose(DM dm, DMAdaptFlag *purpose) 540 { 541 DM_Forest *forest; 542 543 PetscFunctionBegin; 544 forest = (DM_Forest*) dm->data; 545 *purpose = forest->adaptPurpose; 546 PetscFunctionReturn(0); 547 } 548 549 /*@ 550 DMForestSetAdjacencyDimension - During the pre-setup phase, set the dimension of interface points that determine 551 cell adjacency (for the purposes of partitioning and overlap). 552 553 Logically collective on dm 554 555 Input Parameters: 556 + dm - the forest 557 - adjDim - default 0 (i.e., vertices determine adjacency) 558 559 Level: intermediate 560 561 .seealso: DMForestGetAdjacencyDimension(), DMForestSetAdjacencyCodimension(), DMForestSetPartitionOverlap() 562 @*/ 563 PetscErrorCode DMForestSetAdjacencyDimension(DM dm, PetscInt adjDim) 564 { 565 PetscInt dim; 566 DM_Forest *forest = (DM_Forest*) dm->data; 567 PetscErrorCode ierr; 568 569 PetscFunctionBegin; 570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 571 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adjacency dimension after setup"); 572 if (adjDim < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be < 0: %d", adjDim); 573 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 574 if (adjDim > dim) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be > %d: %d", dim, adjDim); 575 forest->adjDim = adjDim; 576 PetscFunctionReturn(0); 577 } 578 579 /*@ 580 DMForestSetAdjacencyCodimension - Like DMForestSetAdjacencyDimension(), but specified as a co-dimension (so that, 581 e.g., adjacency based on facets can be specified by codimension 1 in all cases) 582 583 Logically collective on dm 584 585 Input Parameters: 586 + dm - the forest 587 - adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices 588 589 Level: intermediate 590 591 .seealso: DMForestGetAdjacencyCodimension(), DMForestSetAdjacencyDimension() 592 @*/ 593 PetscErrorCode DMForestSetAdjacencyCodimension(DM dm, PetscInt adjCodim) 594 { 595 PetscInt dim; 596 PetscErrorCode ierr; 597 598 PetscFunctionBegin; 599 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 600 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 601 ierr = DMForestSetAdjacencyDimension(dm,dim-adjCodim);CHKERRQ(ierr); 602 PetscFunctionReturn(0); 603 } 604 605 /*@ 606 DMForestGetAdjacencyDimension - Get the dimension of interface points that determine cell adjacency (for the 607 purposes of partitioning and overlap). 608 609 Not collective 610 611 Input Parameter: 612 . dm - the forest 613 614 Output Parameter: 615 . adjDim - default 0 (i.e., vertices determine adjacency) 616 617 Level: intermediate 618 619 .seealso: DMForestSetAdjacencyDimension(), DMForestGetAdjacencyCodimension(), DMForestSetPartitionOverlap() 620 @*/ 621 PetscErrorCode DMForestGetAdjacencyDimension(DM dm, PetscInt *adjDim) 622 { 623 DM_Forest *forest = (DM_Forest*) dm->data; 624 625 PetscFunctionBegin; 626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 627 PetscValidIntPointer(adjDim,2); 628 *adjDim = forest->adjDim; 629 PetscFunctionReturn(0); 630 } 631 632 /*@ 633 DMForestGetAdjacencyCodimension - Like DMForestGetAdjacencyDimension(), but specified as a co-dimension (so that, 634 e.g., adjacency based on facets can be specified by codimension 1 in all cases) 635 636 Not collective 637 638 Input Parameter: 639 . dm - the forest 640 641 Output Parameter: 642 . adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices 643 644 Level: intermediate 645 646 .seealso: DMForestSetAdjacencyCodimension(), DMForestGetAdjacencyDimension() 647 @*/ 648 PetscErrorCode DMForestGetAdjacencyCodimension(DM dm, PetscInt *adjCodim) 649 { 650 DM_Forest *forest = (DM_Forest*) dm->data; 651 PetscInt dim; 652 PetscErrorCode ierr; 653 654 PetscFunctionBegin; 655 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 656 PetscValidIntPointer(adjCodim,2); 657 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 658 *adjCodim = dim - forest->adjDim; 659 PetscFunctionReturn(0); 660 } 661 662 /*@ 663 DMForestSetPartitionOverlap - During the pre-setup phase, set the amount of cell-overlap present in parallel 664 partitions of a forest, with values > 0 indicating subdomains that are expanded by that many iterations of adding 665 adjacent cells 666 667 Logically collective on dm 668 669 Input Parameters: 670 + dm - the forest 671 - overlap - default 0 672 673 Level: intermediate 674 675 .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension() 676 @*/ 677 PetscErrorCode DMForestSetPartitionOverlap(DM dm, PetscInt overlap) 678 { 679 DM_Forest *forest = (DM_Forest*) dm->data; 680 681 PetscFunctionBegin; 682 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 683 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the overlap after setup"); 684 if (overlap < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"overlap cannot be < 0: %d", overlap); 685 forest->overlap = overlap; 686 PetscFunctionReturn(0); 687 } 688 689 /*@ 690 DMForestGetPartitionOverlap - Get the amount of cell-overlap present in parallel partitions of a forest, with values 691 > 0 indicating subdomains that are expanded by that many iterations of adding adjacent cells 692 693 Not collective 694 695 Input Parameter: 696 . dm - the forest 697 698 Output Parameter: 699 . overlap - default 0 700 701 Level: intermediate 702 703 .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension() 704 @*/ 705 PetscErrorCode DMForestGetPartitionOverlap(DM dm, PetscInt *overlap) 706 { 707 DM_Forest *forest = (DM_Forest*) dm->data; 708 709 PetscFunctionBegin; 710 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 711 PetscValidIntPointer(overlap,2); 712 *overlap = forest->overlap; 713 PetscFunctionReturn(0); 714 } 715 716 /*@ 717 DMForestSetMinimumRefinement - During the pre-setup phase, set the minimum level of refinement (relative to the base 718 DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest 719 (see DMForestGetAdaptivityForest()) this limits the amount of coarsening. 720 721 Logically collective on dm 722 723 Input Parameters: 724 + dm - the forest 725 - minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest) 726 727 Level: intermediate 728 729 .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest() 730 @*/ 731 PetscErrorCode DMForestSetMinimumRefinement(DM dm, PetscInt minRefinement) 732 { 733 DM_Forest *forest = (DM_Forest*) dm->data; 734 735 PetscFunctionBegin; 736 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 737 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the minimum refinement after setup"); 738 forest->minRefinement = minRefinement; 739 PetscFunctionReturn(0); 740 } 741 742 /*@ 743 DMForestGetMinimumRefinement - Get the minimum level of refinement (relative to the base DM, see 744 DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest (see 745 DMForestGetAdaptivityForest()), this limits the amount of coarsening. 746 747 Not collective 748 749 Input Parameter: 750 . dm - the forest 751 752 Output Parameter: 753 . minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest) 754 755 Level: intermediate 756 757 .seealso: DMForestSetMinimumRefinement(), DMForestGetMaximumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest() 758 @*/ 759 PetscErrorCode DMForestGetMinimumRefinement(DM dm, PetscInt *minRefinement) 760 { 761 DM_Forest *forest = (DM_Forest*) dm->data; 762 763 PetscFunctionBegin; 764 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 765 PetscValidIntPointer(minRefinement,2); 766 *minRefinement = forest->minRefinement; 767 PetscFunctionReturn(0); 768 } 769 770 /*@ 771 DMForestSetInitialRefinement - During the pre-setup phase, set the initial level of refinement (relative to the base 772 DM, see DMForestGetBaseDM()) allowed in the forest. 773 774 Logically collective on dm 775 776 Input Parameters: 777 + dm - the forest 778 - initefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest) 779 780 Level: intermediate 781 782 .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM() 783 @*/ 784 PetscErrorCode DMForestSetInitialRefinement(DM dm, PetscInt initRefinement) 785 { 786 DM_Forest *forest = (DM_Forest*) dm->data; 787 788 PetscFunctionBegin; 789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 790 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the initial refinement after setup"); 791 forest->initRefinement = initRefinement; 792 PetscFunctionReturn(0); 793 } 794 795 /*@ 796 DMForestGetInitialRefinement - Get the initial level of refinement (relative to the base DM, see 797 DMForestGetBaseDM()) allowed in the forest. 798 799 Not collective 800 801 Input Parameter: 802 . dm - the forest 803 804 Output Paramater: 805 . initRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest) 806 807 Level: intermediate 808 809 .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM() 810 @*/ 811 PetscErrorCode DMForestGetInitialRefinement(DM dm, PetscInt *initRefinement) 812 { 813 DM_Forest *forest = (DM_Forest*) dm->data; 814 815 PetscFunctionBegin; 816 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 817 PetscValidIntPointer(initRefinement,2); 818 *initRefinement = forest->initRefinement; 819 PetscFunctionReturn(0); 820 } 821 822 /*@ 823 DMForestSetMaximumRefinement - During the pre-setup phase, set the maximum level of refinement (relative to the base 824 DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest 825 (see DMForestGetAdaptivityForest()), this limits the amount of refinement. 826 827 Logically collective on dm 828 829 Input Parameters: 830 + dm - the forest 831 - maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest) 832 833 Level: intermediate 834 835 .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityDM() 836 @*/ 837 PetscErrorCode DMForestSetMaximumRefinement(DM dm, PetscInt maxRefinement) 838 { 839 DM_Forest *forest = (DM_Forest*) dm->data; 840 841 PetscFunctionBegin; 842 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 843 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the maximum refinement after setup"); 844 forest->maxRefinement = maxRefinement; 845 PetscFunctionReturn(0); 846 } 847 848 /*@ 849 DMForestGetMaximumRefinement - Get the maximum level of refinement (relative to the base DM, see 850 DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest (see 851 DMForestGetAdaptivityForest()), this limits the amount of refinement. 852 853 Not collective 854 855 Input Parameter: 856 . dm - the forest 857 858 Output Parameter: 859 . maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest) 860 861 Level: intermediate 862 863 .seealso: DMForestSetMaximumRefinement(), DMForestGetMinimumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest() 864 @*/ 865 PetscErrorCode DMForestGetMaximumRefinement(DM dm, PetscInt *maxRefinement) 866 { 867 DM_Forest *forest = (DM_Forest*) dm->data; 868 869 PetscFunctionBegin; 870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 871 PetscValidIntPointer(maxRefinement,2); 872 *maxRefinement = forest->maxRefinement; 873 PetscFunctionReturn(0); 874 } 875 876 /*@C 877 DMForestSetAdaptivityStrategy - During the pre-setup phase, set the strategy for combining adaptivity labels from multiple processes. 878 Subtypes of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all processes must agree 879 for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only one process needs to 880 specify refinement/coarsening. 881 882 Logically collective on dm 883 884 Input Parameters: 885 + dm - the forest 886 - adaptStrategy - default DMFORESTADAPTALL 887 888 Level: advanced 889 890 .seealso: DMForestGetAdaptivityStrategy() 891 @*/ 892 PetscErrorCode DMForestSetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy adaptStrategy) 893 { 894 DM_Forest *forest = (DM_Forest*) dm->data; 895 PetscErrorCode ierr; 896 897 PetscFunctionBegin; 898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 899 ierr = PetscFree(forest->adaptStrategy);CHKERRQ(ierr); 900 ierr = PetscStrallocpy((const char*) adaptStrategy,(char**)&forest->adaptStrategy);CHKERRQ(ierr); 901 PetscFunctionReturn(0); 902 } 903 904 /*@C 905 DMForestSetAdaptivityStrategy - Get the strategy for combining adaptivity labels from multiple processes. Subtypes 906 of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all 907 processes must agree for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only 908 one process needs to specify refinement/coarsening. 909 910 Not collective 911 912 Input Parameter: 913 . dm - the forest 914 915 Output Parameter: 916 . adaptStrategy - the adaptivity strategy (default DMFORESTADAPTALL) 917 918 Level: advanced 919 920 .seealso: DMForestSetAdaptivityStrategy() 921 @*/ 922 PetscErrorCode DMForestGetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy *adaptStrategy) 923 { 924 DM_Forest *forest = (DM_Forest*) dm->data; 925 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 928 PetscValidPointer(adaptStrategy,2); 929 *adaptStrategy = forest->adaptStrategy; 930 PetscFunctionReturn(0); 931 } 932 933 /*@ 934 DMForestGetAdaptivitySuccess - Return whether the requested adaptation (refinement, coarsening, repartitioning, 935 etc.) was successful. PETSC_FALSE indicates that the post-adaptation forest is the same as the pre-adpatation 936 forest. A requested adaptation may have been unsuccessful if, for example, the requested refinement would have 937 exceeded the maximum refinement level. 938 939 Collective on dm 940 941 Input Parameter: 942 943 . dm - the post-adaptation forest 944 945 Output Parameter: 946 947 . success - PETSC_TRUE if the post-adaptation forest is different from the pre-adaptation forest. 948 949 Level: intermediate 950 951 .see 952 @*/ 953 PetscErrorCode DMForestGetAdaptivitySuccess(DM dm, PetscBool *success) 954 { 955 DM_Forest *forest; 956 PetscErrorCode ierr; 957 958 PetscFunctionBegin; 959 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 960 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"DMSetUp() has not been called yet."); 961 forest = (DM_Forest *) dm->data; 962 ierr = (forest->getadaptivitysuccess)(dm,success);CHKERRQ(ierr); 963 PetscFunctionReturn(0); 964 } 965 966 /*@ 967 DMForestSetComputeAdaptivitySF - During the pre-setup phase, set whether transfer PetscSFs should be computed 968 relating the cells of the pre-adaptation forest to the post-adaptiation forest. After DMSetUp() is called, these transfer PetscSFs can be accessed with DMForestGetAdaptivitySF(). 969 970 Logically collective on dm 971 972 Input Parameters: 973 + dm - the post-adaptation forest 974 - computeSF - default PETSC_TRUE 975 976 Level: advanced 977 978 .seealso: DMForestGetComputeAdaptivitySF(), DMForestGetAdaptivitySF() 979 @*/ 980 PetscErrorCode DMForestSetComputeAdaptivitySF(DM dm, PetscBool computeSF) 981 { 982 DM_Forest *forest; 983 984 PetscFunctionBegin; 985 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 986 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot compute adaptivity PetscSFs after setup is called"); 987 forest = (DM_Forest*) dm->data; 988 forest->computeAdaptSF = computeSF; 989 PetscFunctionReturn(0); 990 } 991 992 PetscErrorCode DMForestTransferVec(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time) 993 { 994 DM_Forest *forest; 995 PetscErrorCode ierr; 996 997 PetscFunctionBegin; 998 PetscValidHeaderSpecific(dmIn ,DM_CLASSID ,1); 999 PetscValidHeaderSpecific(vecIn ,VEC_CLASSID ,2); 1000 PetscValidHeaderSpecific(dmOut ,DM_CLASSID ,3); 1001 PetscValidHeaderSpecific(vecOut ,VEC_CLASSID ,4); 1002 forest = (DM_Forest *) dmIn->data; 1003 if (!forest->transfervec) SETERRQ(PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"DMForestTransferVec() not implemented"); 1004 ierr = (forest->transfervec)(dmIn,vecIn,dmOut,vecOut,useBCs,time);CHKERRQ(ierr); 1005 PetscFunctionReturn(0); 1006 } 1007 1008 PetscErrorCode DMForestTransferVecFromBase(DM dm, Vec vecIn, Vec vecOut) 1009 { 1010 DM_Forest *forest; 1011 PetscErrorCode ierr; 1012 1013 PetscFunctionBegin; 1014 PetscValidHeaderSpecific(dm ,DM_CLASSID ,1); 1015 PetscValidHeaderSpecific(vecIn ,VEC_CLASSID ,2); 1016 PetscValidHeaderSpecific(vecOut ,VEC_CLASSID ,3); 1017 forest = (DM_Forest *) dm->data; 1018 if (!forest->transfervecfrombase) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMForestTransferVecFromBase() not implemented"); 1019 ierr = (forest->transfervecfrombase)(dm,vecIn,vecOut);CHKERRQ(ierr); 1020 PetscFunctionReturn(0); 1021 } 1022 1023 /*@ 1024 DMForestGetComputeAdaptivitySF - Get whether transfer PetscSFs should be computed relating the cells of the 1025 pre-adaptation forest to the post-adaptiation forest. After DMSetUp() is called, these transfer PetscSFs can be 1026 accessed with DMForestGetAdaptivitySF(). 1027 1028 Not collective 1029 1030 Input Parameter: 1031 . dm - the post-adaptation forest 1032 1033 Output Parameter: 1034 . computeSF - default PETSC_TRUE 1035 1036 Level: advanced 1037 1038 .seealso: DMForestSetComputeAdaptivitySF(), DMForestGetAdaptivitySF() 1039 @*/ 1040 PetscErrorCode DMForestGetComputeAdaptivitySF(DM dm, PetscBool *computeSF) 1041 { 1042 DM_Forest *forest; 1043 1044 PetscFunctionBegin; 1045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1046 forest = (DM_Forest*) dm->data; 1047 *computeSF = forest->computeAdaptSF; 1048 PetscFunctionReturn(0); 1049 } 1050 1051 /*@ 1052 DMForestGetAdaptivitySF - Get PetscSFs that relate the pre-adaptation forest to the post-adaptation forest. 1053 Adaptation can be any combination of refinement, coarsening, repartition, and change of overlap, so there may be 1054 some cells of the pre-adaptation that are parents of post-adaptation cells, and vice versa. Therefore there are two 1055 PetscSFs: one that relates pre-adaptation coarse cells to post-adaptation fine cells, and one that relates 1056 pre-adaptation fine cells to post-adaptation coarse cells. 1057 1058 Not collective 1059 1060 Input Parameter: 1061 dm - the post-adaptation forest 1062 1063 Output Parameter: 1064 preCoarseToFine - pre-adaptation coarse cells to post-adaptation fine cells: BCast goes from pre- to post- 1065 coarseToPreFine - post-adaptation coarse cells to pre-adaptation fine cells: BCast goes from post- to pre- 1066 1067 Level: advanced 1068 1069 .seealso: DMForestGetComputeAdaptivitySF(), DMForestSetComputeAdaptivitySF() 1070 @*/ 1071 PetscErrorCode DMForestGetAdaptivitySF(DM dm, PetscSF *preCoarseToFine, PetscSF *coarseToPreFine) 1072 { 1073 DM_Forest *forest; 1074 PetscErrorCode ierr; 1075 1076 PetscFunctionBegin; 1077 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1078 ierr = DMSetUp(dm);CHKERRQ(ierr); 1079 forest = (DM_Forest*) dm->data; 1080 if (preCoarseToFine) *preCoarseToFine = forest->preCoarseToFine; 1081 if (coarseToPreFine) *coarseToPreFine = forest->coarseToPreFine; 1082 PetscFunctionReturn(0); 1083 } 1084 1085 /*@ 1086 DMForestSetGradeFactor - During the pre-setup phase, set the desired amount of grading in the mesh, e.g. give 2 to 1087 indicate that the diameter of neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may 1088 only support one particular choice of grading factor. 1089 1090 Logically collective on dm 1091 1092 Input Parameters: 1093 + dm - the forest 1094 - grade - the grading factor 1095 1096 Level: advanced 1097 1098 .seealso: DMForestGetGradeFactor() 1099 @*/ 1100 PetscErrorCode DMForestSetGradeFactor(DM dm, PetscInt grade) 1101 { 1102 DM_Forest *forest = (DM_Forest*) dm->data; 1103 1104 PetscFunctionBegin; 1105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1106 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the grade factor after setup"); 1107 forest->gradeFactor = grade; 1108 PetscFunctionReturn(0); 1109 } 1110 1111 /*@ 1112 DMForestGetGradeFactor - Get the desired amount of grading in the mesh, e.g. give 2 to indicate that the diameter of 1113 neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may only support one particular 1114 choice of grading factor. 1115 1116 Not collective 1117 1118 Input Parameter: 1119 . dm - the forest 1120 1121 Output Parameter: 1122 . grade - the grading factor 1123 1124 Level: advanced 1125 1126 .seealso: DMForestSetGradeFactor() 1127 @*/ 1128 PetscErrorCode DMForestGetGradeFactor(DM dm, PetscInt *grade) 1129 { 1130 DM_Forest *forest = (DM_Forest*) dm->data; 1131 1132 PetscFunctionBegin; 1133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1134 PetscValidIntPointer(grade,2); 1135 *grade = forest->gradeFactor; 1136 PetscFunctionReturn(0); 1137 } 1138 1139 /*@ 1140 DMForestSetCellWeightFactor - During the pre-setup phase, set the factor by which the level of refinement changes 1141 the cell weight (see DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be 1142 (cellWeight) * (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on 1143 its level; a factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the 1144 computation associated with a cell is multiplied by a factor of 2 for each additional level of refinement. 1145 1146 Logically collective on dm 1147 1148 Input Parameters: 1149 + dm - the forest 1150 - weightsFactors - default 1. 1151 1152 Level: advanced 1153 1154 .seealso: DMForestGetCellWeightFactor(), DMForestSetCellWeights() 1155 @*/ 1156 PetscErrorCode DMForestSetCellWeightFactor(DM dm, PetscReal weightsFactor) 1157 { 1158 DM_Forest *forest = (DM_Forest*) dm->data; 1159 1160 PetscFunctionBegin; 1161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1162 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weights factor after setup"); 1163 forest->weightsFactor = weightsFactor; 1164 PetscFunctionReturn(0); 1165 } 1166 1167 /*@ 1168 DMForestGetCellWeightFactor - Get the factor by which the level of refinement changes the cell weight (see 1169 DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be (cellWeight) * 1170 (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on its level; a 1171 factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the computation 1172 associated with a cell is multiplied by a factor of 2 for each additional level of refinement. 1173 1174 Not collective 1175 1176 Input Parameter: 1177 . dm - the forest 1178 1179 Output Parameter: 1180 . weightsFactors - default 1. 1181 1182 Level: advanced 1183 1184 .seealso: DMForestSetCellWeightFactor(), DMForestSetCellWeights() 1185 @*/ 1186 PetscErrorCode DMForestGetCellWeightFactor(DM dm, PetscReal *weightsFactor) 1187 { 1188 DM_Forest *forest = (DM_Forest*) dm->data; 1189 1190 PetscFunctionBegin; 1191 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1192 PetscValidRealPointer(weightsFactor,2); 1193 *weightsFactor = forest->weightsFactor; 1194 PetscFunctionReturn(0); 1195 } 1196 1197 /*@ 1198 DMForestGetCellChart - After the setup phase, get the local half-open interval of the chart of cells on this process 1199 1200 Not collective 1201 1202 Input Parameter: 1203 . dm - the forest 1204 1205 Output Parameters: 1206 + cStart - the first cell on this process 1207 - cEnd - one after the final cell on this process 1208 1209 Level: intermediate 1210 1211 .seealso: DMForestGetCellSF() 1212 @*/ 1213 PetscErrorCode DMForestGetCellChart(DM dm, PetscInt *cStart, PetscInt *cEnd) 1214 { 1215 DM_Forest *forest = (DM_Forest*) dm->data; 1216 PetscErrorCode ierr; 1217 1218 PetscFunctionBegin; 1219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1220 PetscValidIntPointer(cStart,2); 1221 PetscValidIntPointer(cEnd,2); 1222 if (((forest->cStart == PETSC_DETERMINE) || (forest->cEnd == PETSC_DETERMINE)) && forest->createcellchart) { 1223 ierr = forest->createcellchart(dm,&forest->cStart,&forest->cEnd);CHKERRQ(ierr); 1224 } 1225 *cStart = forest->cStart; 1226 *cEnd = forest->cEnd; 1227 PetscFunctionReturn(0); 1228 } 1229 1230 /*@ 1231 DMForestGetCellSF - After the setup phase, get the PetscSF for overlapping cells between processes 1232 1233 Not collective 1234 1235 Input Parameter: 1236 . dm - the forest 1237 1238 Output Parameter: 1239 . cellSF - the PetscSF 1240 1241 Level: intermediate 1242 1243 .seealso: DMForestGetCellChart() 1244 @*/ 1245 PetscErrorCode DMForestGetCellSF(DM dm, PetscSF *cellSF) 1246 { 1247 DM_Forest *forest = (DM_Forest*) dm->data; 1248 PetscErrorCode ierr; 1249 1250 PetscFunctionBegin; 1251 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1252 PetscValidPointer(cellSF,2); 1253 if ((!forest->cellSF) && forest->createcellsf) { 1254 ierr = forest->createcellsf(dm,&forest->cellSF);CHKERRQ(ierr); 1255 } 1256 *cellSF = forest->cellSF; 1257 PetscFunctionReturn(0); 1258 } 1259 1260 /*@C 1261 DMForestSetAdaptivityLabel - During the pre-setup phase, set the label of the pre-adaptation forest (see 1262 DMForestGetAdaptivityForest()) that holds the adaptation flags (refinement, coarsening, or some combination). The 1263 interpretation of the label values is up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, 1264 DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have been reserved as choices that should be accepted by all subtypes. 1265 1266 Logically collective on dm 1267 1268 Input Parameters: 1269 - dm - the forest 1270 + adaptLabel - the label in the pre-adaptation forest 1271 1272 Level: intermediate 1273 1274 .seealso DMForestGetAdaptivityLabel() 1275 @*/ 1276 PetscErrorCode DMForestSetAdaptivityLabel(DM dm, DMLabel adaptLabel) 1277 { 1278 DM_Forest *forest = (DM_Forest*) dm->data; 1279 PetscErrorCode ierr; 1280 1281 PetscFunctionBegin; 1282 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1283 if (adaptLabel) PetscValidHeaderSpecific(adaptLabel,DMLABEL_CLASSID,2); 1284 ierr = PetscObjectReference((PetscObject)adaptLabel);CHKERRQ(ierr); 1285 ierr = DMLabelDestroy(&forest->adaptLabel);CHKERRQ(ierr); 1286 forest->adaptLabel = adaptLabel; 1287 PetscFunctionReturn(0); 1288 } 1289 1290 /*@C 1291 DMForestGetAdaptivityLabel - Get the label of the pre-adaptation forest (see DMForestGetAdaptivityForest()) that 1292 holds the adaptation flags (refinement, coarsening, or some combination). The interpretation of the label values is 1293 up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have 1294 been reserved as choices that should be accepted by all subtypes. 1295 1296 Not collective 1297 1298 Input Parameter: 1299 . dm - the forest 1300 1301 Output Parameter: 1302 . adaptLabel - the name of the label in the pre-adaptation forest 1303 1304 Level: intermediate 1305 1306 .seealso DMForestSetAdaptivityLabel() 1307 @*/ 1308 PetscErrorCode DMForestGetAdaptivityLabel(DM dm, DMLabel *adaptLabel) 1309 { 1310 DM_Forest *forest = (DM_Forest*) dm->data; 1311 1312 PetscFunctionBegin; 1313 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1314 *adaptLabel = forest->adaptLabel; 1315 PetscFunctionReturn(0); 1316 } 1317 1318 /*@ 1319 DMForestSetCellWeights - Set the weights assigned to each of the cells (see DMForestGetCellChart()) of the current 1320 process: weights are used to determine parallel partitioning. Partitions will be created so that each process's 1321 ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight 1322 of 1. 1323 1324 Logically collective on dm 1325 1326 Input Parameters: 1327 + dm - the forest 1328 . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1. 1329 - copyMode - how weights should reference weights 1330 1331 Level: advanced 1332 1333 .seealso: DMForestGetCellWeights(), DMForestSetWeightCapacity() 1334 @*/ 1335 PetscErrorCode DMForestSetCellWeights(DM dm, PetscReal weights[], PetscCopyMode copyMode) 1336 { 1337 DM_Forest *forest = (DM_Forest*) dm->data; 1338 PetscInt cStart, cEnd; 1339 PetscErrorCode ierr; 1340 1341 PetscFunctionBegin; 1342 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1343 ierr = DMForestGetCellChart(dm,&cStart,&cEnd);CHKERRQ(ierr); 1344 if (cEnd < cStart) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"cell chart [%d,%d) is not valid",cStart,cEnd); 1345 if (copyMode == PETSC_COPY_VALUES) { 1346 if (forest->cellWeightsCopyMode != PETSC_OWN_POINTER || forest->cellWeights == weights) { 1347 ierr = PetscMalloc1(cEnd-cStart,&forest->cellWeights);CHKERRQ(ierr); 1348 } 1349 ierr = PetscArraycpy(forest->cellWeights,weights,cEnd-cStart);CHKERRQ(ierr); 1350 forest->cellWeightsCopyMode = PETSC_OWN_POINTER; 1351 PetscFunctionReturn(0); 1352 } 1353 if (forest->cellWeightsCopyMode == PETSC_OWN_POINTER) { 1354 ierr = PetscFree(forest->cellWeights);CHKERRQ(ierr); 1355 } 1356 forest->cellWeights = weights; 1357 forest->cellWeightsCopyMode = copyMode; 1358 PetscFunctionReturn(0); 1359 } 1360 1361 /*@ 1362 DMForestGetCellWeights - Get the weights assigned to each of the cells (see DMForestGetCellChart()) of the current 1363 process: weights are used to determine parallel partitioning. Partitions will be created so that each process's 1364 ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight 1365 of 1. 1366 1367 Not collective 1368 1369 Input Parameter: 1370 . dm - the forest 1371 1372 Output Parameter: 1373 . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1. 1374 1375 Level: advanced 1376 1377 .seealso: DMForestSetCellWeights(), DMForestSetWeightCapacity() 1378 @*/ 1379 PetscErrorCode DMForestGetCellWeights(DM dm, PetscReal **weights) 1380 { 1381 DM_Forest *forest = (DM_Forest*) dm->data; 1382 1383 PetscFunctionBegin; 1384 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1385 PetscValidPointer(weights,2); 1386 *weights = forest->cellWeights; 1387 PetscFunctionReturn(0); 1388 } 1389 1390 /*@ 1391 DMForestSetWeightCapacity - During the pre-setup phase, set the capacity of the current process when repartitioning 1392 a pre-adaptation forest (see DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each 1393 process's cells to the process's capacity will be roughly equal for all processes. A capacity of 0 indicates that 1394 the current process should not have any cells after repartitioning. 1395 1396 Logically Collective on dm 1397 1398 Input parameters: 1399 + dm - the forest 1400 - capacity - this process's capacity 1401 1402 Level: advanced 1403 1404 .seealso DMForestGetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor() 1405 @*/ 1406 PetscErrorCode DMForestSetWeightCapacity(DM dm, PetscReal capacity) 1407 { 1408 DM_Forest *forest = (DM_Forest*) dm->data; 1409 1410 PetscFunctionBegin; 1411 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1412 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weight capacity after setup"); 1413 if (capacity < 0.) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have negative weight capacity; %f",capacity); 1414 forest->weightCapacity = capacity; 1415 PetscFunctionReturn(0); 1416 } 1417 1418 /*@ 1419 DMForestGetWeightCapacity - Set the capacity of the current process when repartitioning a pre-adaptation forest (see 1420 DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each process's cells to the 1421 process's capacity will be roughly equal for all processes. A capacity of 0 indicates that the current process 1422 should not have any cells after repartitioning. 1423 1424 Not collective 1425 1426 Input parameter: 1427 . dm - the forest 1428 1429 Output parameter: 1430 . capacity - this process's capacity 1431 1432 Level: advanced 1433 1434 .seealso DMForestSetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor() 1435 @*/ 1436 PetscErrorCode DMForestGetWeightCapacity(DM dm, PetscReal *capacity) 1437 { 1438 DM_Forest *forest = (DM_Forest*) dm->data; 1439 1440 PetscFunctionBegin; 1441 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1442 PetscValidRealPointer(capacity,2); 1443 *capacity = forest->weightCapacity; 1444 PetscFunctionReturn(0); 1445 } 1446 1447 PETSC_EXTERN PetscErrorCode DMSetFromOptions_Forest(PetscOptionItems *PetscOptionsObject,DM dm) 1448 { 1449 PetscBool flg, flg1, flg2, flg3, flg4; 1450 DMForestTopology oldTopo; 1451 char stringBuffer[256]; 1452 PetscViewer viewer; 1453 PetscViewerFormat format; 1454 PetscInt adjDim, adjCodim, overlap, minRefinement, initRefinement, maxRefinement, grade; 1455 PetscReal weightsFactor; 1456 DMForestAdaptivityStrategy adaptStrategy; 1457 PetscErrorCode ierr; 1458 1459 PetscFunctionBegin; 1460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1461 ierr = DMForestGetTopology(dm, &oldTopo);CHKERRQ(ierr); 1462 ierr = PetscOptionsHead(PetscOptionsObject,"DMForest Options");CHKERRQ(ierr); 1463 ierr = PetscOptionsString("-dm_forest_topology","the topology of the forest's base mesh","DMForestSetTopology",oldTopo,stringBuffer,256,&flg1);CHKERRQ(ierr); 1464 ierr = PetscOptionsViewer("-dm_forest_base_dm","load the base DM from a viewer specification","DMForestSetBaseDM",&viewer,&format,&flg2);CHKERRQ(ierr); 1465 ierr = PetscOptionsViewer("-dm_forest_coarse_forest","load the coarse forest from a viewer specification","DMForestSetCoarseForest",&viewer,&format,&flg3);CHKERRQ(ierr); 1466 ierr = PetscOptionsViewer("-dm_forest_fine_forest","load the fine forest from a viewer specification","DMForestSetFineForest",&viewer,&format,&flg4);CHKERRQ(ierr); 1467 if ((PetscInt) flg1 + (PetscInt) flg2 + (PetscInt) flg3 + (PetscInt) flg4 > 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Specify only one of -dm_forest_{topology,base_dm,coarse_forest,fine_forest}"); 1468 if (flg1) { 1469 ierr = DMForestSetTopology(dm,(DMForestTopology)stringBuffer);CHKERRQ(ierr); 1470 ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr); 1471 ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr); 1472 } 1473 if (flg2) { 1474 DM base; 1475 1476 ierr = DMCreate(PetscObjectComm((PetscObject)dm),&base);CHKERRQ(ierr); 1477 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 1478 ierr = DMLoad(base,viewer);CHKERRQ(ierr); 1479 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 1480 ierr = DMForestSetBaseDM(dm,base);CHKERRQ(ierr); 1481 ierr = DMDestroy(&base);CHKERRQ(ierr); 1482 ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr); 1483 ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr); 1484 } 1485 if (flg3) { 1486 DM coarse; 1487 1488 ierr = DMCreate(PetscObjectComm((PetscObject)dm),&coarse);CHKERRQ(ierr); 1489 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 1490 ierr = DMLoad(coarse,viewer);CHKERRQ(ierr); 1491 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 1492 ierr = DMForestSetAdaptivityForest(dm,coarse);CHKERRQ(ierr); 1493 ierr = DMDestroy(&coarse);CHKERRQ(ierr); 1494 ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr); 1495 ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr); 1496 } 1497 if (flg4) { 1498 DM fine; 1499 1500 ierr = DMCreate(PetscObjectComm((PetscObject)dm),&fine);CHKERRQ(ierr); 1501 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 1502 ierr = DMLoad(fine,viewer);CHKERRQ(ierr); 1503 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 1504 ierr = DMForestSetAdaptivityForest(dm,fine);CHKERRQ(ierr); 1505 ierr = DMDestroy(&fine);CHKERRQ(ierr); 1506 ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr); 1507 ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr); 1508 } 1509 ierr = DMForestGetAdjacencyDimension(dm,&adjDim);CHKERRQ(ierr); 1510 ierr = PetscOptionsBoundedInt("-dm_forest_adjacency_dimension","set the dimension of points that define adjacency in the forest","DMForestSetAdjacencyDimension",adjDim,&adjDim,&flg,0);CHKERRQ(ierr); 1511 if (flg) { 1512 ierr = DMForestSetAdjacencyDimension(dm,adjDim);CHKERRQ(ierr); 1513 } else { 1514 ierr = DMForestGetAdjacencyCodimension(dm,&adjCodim);CHKERRQ(ierr); 1515 ierr = PetscOptionsBoundedInt("-dm_forest_adjacency_codimension","set the codimension of points that define adjacency in the forest","DMForestSetAdjacencyCodimension",adjCodim,&adjCodim,&flg,1);CHKERRQ(ierr); 1516 if (flg) { 1517 ierr = DMForestSetAdjacencyCodimension(dm,adjCodim);CHKERRQ(ierr); 1518 } 1519 } 1520 ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr); 1521 ierr = PetscOptionsBoundedInt("-dm_forest_partition_overlap","set the degree of partition overlap","DMForestSetPartitionOverlap",overlap,&overlap,&flg,0);CHKERRQ(ierr); 1522 if (flg) { 1523 ierr = DMForestSetPartitionOverlap(dm,overlap);CHKERRQ(ierr); 1524 } 1525 #if 0 1526 ierr = PetscOptionsBoundedInt("-dm_refine","equivalent to -dm_forest_set_minimum_refinement and -dm_forest_set_initial_refinement with the same value",NULL,minRefinement,&minRefinement,&flg,0);CHKERRQ(ierr); 1527 if (flg) { 1528 ierr = DMForestSetMinimumRefinement(dm,minRefinement);CHKERRQ(ierr); 1529 ierr = DMForestSetInitialRefinement(dm,minRefinement);CHKERRQ(ierr); 1530 } 1531 ierr = PetscOptionsBoundedInt("-dm_refine_hierarchy","equivalent to -dm_forest_set_minimum_refinement 0 and -dm_forest_set_initial_refinement",NULL,initRefinement,&initRefinement,&flg,0);CHKERRQ(ierr); 1532 if (flg) { 1533 ierr = DMForestSetMinimumRefinement(dm,0);CHKERRQ(ierr); 1534 ierr = DMForestSetInitialRefinement(dm,initRefinement);CHKERRQ(ierr); 1535 } 1536 #endif 1537 ierr = DMForestGetMinimumRefinement(dm,&minRefinement);CHKERRQ(ierr); 1538 ierr = PetscOptionsBoundedInt("-dm_forest_minimum_refinement","set the minimum level of refinement in the forest","DMForestSetMinimumRefinement",minRefinement,&minRefinement,&flg,0);CHKERRQ(ierr); 1539 if (flg) { 1540 ierr = DMForestSetMinimumRefinement(dm,minRefinement);CHKERRQ(ierr); 1541 } 1542 ierr = DMForestGetInitialRefinement(dm,&initRefinement);CHKERRQ(ierr); 1543 ierr = PetscOptionsBoundedInt("-dm_forest_initial_refinement","set the initial level of refinement in the forest","DMForestSetInitialRefinement",initRefinement,&initRefinement,&flg,0);CHKERRQ(ierr); 1544 if (flg) { 1545 ierr = DMForestSetInitialRefinement(dm,initRefinement);CHKERRQ(ierr); 1546 } 1547 ierr = DMForestGetMaximumRefinement(dm,&maxRefinement);CHKERRQ(ierr); 1548 ierr = PetscOptionsBoundedInt("-dm_forest_maximum_refinement","set the maximum level of refinement in the forest","DMForestSetMaximumRefinement",maxRefinement,&maxRefinement,&flg,0);CHKERRQ(ierr); 1549 if (flg) { 1550 ierr = DMForestSetMaximumRefinement(dm,maxRefinement);CHKERRQ(ierr); 1551 } 1552 ierr = DMForestGetAdaptivityStrategy(dm,&adaptStrategy);CHKERRQ(ierr); 1553 ierr = PetscOptionsString("-dm_forest_adaptivity_strategy","the forest's adaptivity-flag resolution strategy","DMForestSetAdaptivityStrategy",adaptStrategy,stringBuffer,256,&flg);CHKERRQ(ierr); 1554 if (flg) { 1555 ierr = DMForestSetAdaptivityStrategy(dm,(DMForestAdaptivityStrategy)stringBuffer);CHKERRQ(ierr); 1556 } 1557 ierr = DMForestGetGradeFactor(dm,&grade);CHKERRQ(ierr); 1558 ierr = PetscOptionsBoundedInt("-dm_forest_grade_factor","grade factor between neighboring cells","DMForestSetGradeFactor",grade,&grade,&flg,0);CHKERRQ(ierr); 1559 if (flg) { 1560 ierr = DMForestSetGradeFactor(dm,grade);CHKERRQ(ierr); 1561 } 1562 ierr = DMForestGetCellWeightFactor(dm,&weightsFactor);CHKERRQ(ierr); 1563 ierr = PetscOptionsReal("-dm_forest_cell_weight_factor","multiplying weight factor for cell refinement","DMForestSetCellWeightFactor",weightsFactor,&weightsFactor,&flg);CHKERRQ(ierr); 1564 if (flg) { 1565 ierr = DMForestSetCellWeightFactor(dm,weightsFactor);CHKERRQ(ierr); 1566 } 1567 ierr = PetscOptionsTail();CHKERRQ(ierr); 1568 PetscFunctionReturn(0); 1569 } 1570 1571 PetscErrorCode DMCreateSubDM_Forest(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 1572 { 1573 PetscErrorCode ierr; 1574 1575 PetscFunctionBegin; 1576 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 1577 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1578 PetscFunctionReturn(0); 1579 } 1580 1581 PetscErrorCode DMRefine_Forest(DM dm, MPI_Comm comm, DM *dmRefined) 1582 { 1583 DMLabel refine; 1584 DM fineDM; 1585 PetscErrorCode ierr; 1586 1587 PetscFunctionBegin; 1588 ierr = DMGetFineDM(dm,&fineDM);CHKERRQ(ierr); 1589 if (fineDM) { 1590 ierr = PetscObjectReference((PetscObject)fineDM);CHKERRQ(ierr); 1591 *dmRefined = fineDM; 1592 PetscFunctionReturn(0); 1593 } 1594 ierr = DMForestTemplate(dm,comm,dmRefined);CHKERRQ(ierr); 1595 ierr = DMGetLabel(dm,"refine",&refine);CHKERRQ(ierr); 1596 if (!refine) { 1597 ierr = DMLabelCreate(PETSC_COMM_SELF, "refine",&refine);CHKERRQ(ierr); 1598 ierr = DMLabelSetDefaultValue(refine,DM_ADAPT_REFINE);CHKERRQ(ierr); 1599 } else { 1600 ierr = PetscObjectReference((PetscObject) refine);CHKERRQ(ierr); 1601 } 1602 ierr = DMForestSetAdaptivityLabel(*dmRefined,refine);CHKERRQ(ierr); 1603 ierr = DMLabelDestroy(&refine);CHKERRQ(ierr); 1604 PetscFunctionReturn(0); 1605 } 1606 1607 PetscErrorCode DMCoarsen_Forest(DM dm, MPI_Comm comm, DM *dmCoarsened) 1608 { 1609 DMLabel coarsen; 1610 DM coarseDM; 1611 PetscErrorCode ierr; 1612 1613 PetscFunctionBegin; 1614 { 1615 PetscMPIInt mpiComparison; 1616 MPI_Comm dmcomm = PetscObjectComm((PetscObject)dm); 1617 1618 ierr = MPI_Comm_compare(comm, dmcomm, &mpiComparison);CHKERRQ(ierr); 1619 if (mpiComparison != MPI_IDENT && mpiComparison != MPI_CONGRUENT) SETERRQ(dmcomm,PETSC_ERR_SUP,"No support for different communicators yet"); 1620 } 1621 ierr = DMGetCoarseDM(dm,&coarseDM);CHKERRQ(ierr); 1622 if (coarseDM) { 1623 ierr = PetscObjectReference((PetscObject)coarseDM);CHKERRQ(ierr); 1624 *dmCoarsened = coarseDM; 1625 PetscFunctionReturn(0); 1626 } 1627 ierr = DMForestTemplate(dm,comm,dmCoarsened);CHKERRQ(ierr); 1628 ierr = DMForestSetAdaptivityPurpose(*dmCoarsened,DM_ADAPT_COARSEN);CHKERRQ(ierr); 1629 ierr = DMGetLabel(dm,"coarsen",&coarsen);CHKERRQ(ierr); 1630 if (!coarsen) { 1631 ierr = DMLabelCreate(PETSC_COMM_SELF, "coarsen",&coarsen);CHKERRQ(ierr); 1632 ierr = DMLabelSetDefaultValue(coarsen,DM_ADAPT_COARSEN);CHKERRQ(ierr); 1633 } else { 1634 ierr = PetscObjectReference((PetscObject) coarsen);CHKERRQ(ierr); 1635 } 1636 ierr = DMForestSetAdaptivityLabel(*dmCoarsened,coarsen);CHKERRQ(ierr); 1637 ierr = DMLabelDestroy(&coarsen);CHKERRQ(ierr); 1638 PetscFunctionReturn(0); 1639 } 1640 1641 static PetscErrorCode DMAdaptLabel_Forest(DM dm, DMLabel label, DM *adaptedDM) 1642 { 1643 PetscBool success; 1644 PetscErrorCode ierr; 1645 1646 PetscFunctionBegin; 1647 ierr = DMForestTemplate(dm,PetscObjectComm((PetscObject)dm),adaptedDM);CHKERRQ(ierr); 1648 ierr = DMForestSetAdaptivityLabel(*adaptedDM,label);CHKERRQ(ierr); 1649 ierr = DMSetUp(*adaptedDM);CHKERRQ(ierr); 1650 ierr = DMForestGetAdaptivitySuccess(*adaptedDM,&success);CHKERRQ(ierr); 1651 if (!success) { 1652 ierr = DMDestroy(adaptedDM);CHKERRQ(ierr); 1653 *adaptedDM = NULL; 1654 } 1655 PetscFunctionReturn(0); 1656 } 1657 1658 static PetscErrorCode DMInitialize_Forest(DM dm) 1659 { 1660 PetscErrorCode ierr; 1661 1662 PetscFunctionBegin; 1663 ierr = PetscMemzero(dm->ops,sizeof(*(dm->ops)));CHKERRQ(ierr); 1664 1665 dm->ops->clone = DMClone_Forest; 1666 dm->ops->setfromoptions = DMSetFromOptions_Forest; 1667 dm->ops->destroy = DMDestroy_Forest; 1668 dm->ops->createsubdm = DMCreateSubDM_Forest; 1669 dm->ops->refine = DMRefine_Forest; 1670 dm->ops->coarsen = DMCoarsen_Forest; 1671 dm->ops->adaptlabel = DMAdaptLabel_Forest; 1672 PetscFunctionReturn(0); 1673 } 1674 1675 /*MC 1676 1677 DMFOREST = "forest" - A DM object that encapsulates a hierarchically refined mesh. Forests usually have a base DM 1678 (see DMForestGetBaseDM()), from which it is refined. The refinement and partitioning of forests is considered 1679 immutable after DMSetUp() is called. To adapt a mesh, one should call DMForestTemplate() to create a new mesh that 1680 will default to being identical to it, specify how that mesh should differ, and then calling DMSetUp() on the new 1681 mesh. 1682 1683 To specify that a mesh should be refined or coarsened from the previous mesh, a label should be defined on the 1684 previous mesh whose values indicate which cells should be refined (DM_ADAPT_REFINE) or coarsened (DM_ADAPT_COARSEN) 1685 and how (subtypes are free to allow additional values for things like anisotropic refinement). The label should be 1686 given to the *new* mesh with DMForestSetAdaptivityLabel(). 1687 1688 Level: advanced 1689 1690 .seealso: DMType, DMCreate(), DMSetType(), DMForestGetBaseDM(), DMForestSetBaseDM(), DMForestTemplate(), DMForestSetAdaptivityLabel() 1691 M*/ 1692 1693 PETSC_EXTERN PetscErrorCode DMCreate_Forest(DM dm) 1694 { 1695 DM_Forest *forest; 1696 PetscErrorCode ierr; 1697 1698 PetscFunctionBegin; 1699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1700 ierr = PetscNewLog(dm,&forest);CHKERRQ(ierr); 1701 dm->dim = 0; 1702 dm->data = forest; 1703 forest->refct = 1; 1704 forest->data = NULL; 1705 forest->topology = NULL; 1706 forest->adapt = NULL; 1707 forest->base = NULL; 1708 forest->adaptPurpose = DM_ADAPT_DETERMINE; 1709 forest->adjDim = PETSC_DEFAULT; 1710 forest->overlap = PETSC_DEFAULT; 1711 forest->minRefinement = PETSC_DEFAULT; 1712 forest->maxRefinement = PETSC_DEFAULT; 1713 forest->initRefinement = PETSC_DEFAULT; 1714 forest->cStart = PETSC_DETERMINE; 1715 forest->cEnd = PETSC_DETERMINE; 1716 forest->cellSF = NULL; 1717 forest->adaptLabel = NULL; 1718 forest->gradeFactor = 2; 1719 forest->cellWeights = NULL; 1720 forest->cellWeightsCopyMode = PETSC_USE_POINTER; 1721 forest->weightsFactor = 1.; 1722 forest->weightCapacity = 1.; 1723 ierr = DMForestSetAdaptivityStrategy(dm,DMFORESTADAPTALL);CHKERRQ(ierr); 1724 ierr = DMInitialize_Forest(dm);CHKERRQ(ierr); 1725 PetscFunctionReturn(0); 1726 } 1727