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