Date: 2022-08-02T03:14:20+00:00

Actual source code: forest.c

      1: #include <petsc/private/dmforestimpl.h>
      2: #include <petsc/private/dmimpl.h>
      3: #include <petsc/private/dmlabelimpl.h>
      4: #include <petscsf.h>

      6: PetscBool DMForestPackageInitialized = PETSC_FALSE;

      8: typedef struct _DMForestTypeLink*DMForestTypeLink;

     10: struct _DMForestTypeLink
     11: {
     12:   char             *name;
     13:   DMForestTypeLink next;
     14: };

     16: DMForestTypeLink DMForestTypeList;

     18: static PetscErrorCode DMForestPackageFinalize(void)
     19: {
     20:   DMForestTypeLink oldLink, link = DMForestTypeList;

     22:   while (link) {
     23:     oldLink = link;
     24:     PetscFree(oldLink->name);
     25:     link    = oldLink->next;
     26:     PetscFree(oldLink);
     27:   }
     28:   return 0;
     29: }

     31: static PetscErrorCode DMForestPackageInitialize(void)
     32: {
     33:   if (DMForestPackageInitialized) return 0;
     34:   DMForestPackageInitialized = PETSC_TRUE;

     36:   DMForestRegisterType(DMFOREST);
     37:   PetscRegisterFinalize(DMForestPackageFinalize);
     38:   return 0;
     39: }

     41: /*@C
     42:   DMForestRegisterType - Registers a DMType as a subtype of DMFOREST (so that DMIsForest() will be correct)

     44:   Not Collective

     46:   Input parameter:
     47: . name - the name of the type

     49:   Level: advanced

     51: .seealso: DMFOREST, DMIsForest()
     52: @*/
     53: PetscErrorCode DMForestRegisterType(DMType name)
     54: {
     55:   DMForestTypeLink link;

     57:   DMForestPackageInitialize();
     58:   PetscNew(&link);
     59:   PetscStrallocpy(name,&link->name);
     60:   link->next       = DMForestTypeList;
     61:   DMForestTypeList = link;
     62:   return 0;
     63: }

     65: /*@
     66:   DMIsForest - Check whether a DM uses the DMFOREST interface for hierarchically-refined meshes

     68:   Not Collective

     70:   Input parameter:
     71: . dm - the DM object

     73:   Output parameter:
     74: . isForest - whether dm is a subtype of DMFOREST

     76:   Level: intermediate

     78: .seealso: DMFOREST, DMForestRegisterType()
     79: @*/
     80: PetscErrorCode DMIsForest(DM dm, PetscBool *isForest)
     81: {
     82:   DMForestTypeLink link = DMForestTypeList;

     84:   while (link) {
     85:     PetscBool sameType;
     86:     PetscObjectTypeCompare((PetscObject)dm,link->name,&sameType);
     87:     if (sameType) {
     88:       *isForest = PETSC_TRUE;
     89:       return 0;
     90:     }
     91:     link = link->next;
     92:   }
     93:   *isForest = PETSC_FALSE;
     94:   return 0;
     95: }

     97: /*@
     98:   DMForestTemplate - Create a new DM that will be adapted from a source DM.  The new DM reproduces the configuration
     99:   of the source, but is not yet setup, so that the user can then define only the ways that the new DM should differ
    100:   (by, e.g., refinement or repartitioning).  The source DM is also set as the adaptivity source DM of the new DM (see
    101:   DMForestSetAdaptivityForest()).

    103:   Collective on dm

    105:   Input Parameters:
    106: + dm - the source DM object
    107: - comm - the communicator for the new DM (this communicator is currently ignored, but is present so that DMForestTemplate() can be used within DMCoarsen())

    109:   Output Parameter:
    110: . tdm - the new DM object

    112:   Level: intermediate

    114: .seealso: DMForestSetAdaptivityForest()
    115: @*/
    116: PetscErrorCode DMForestTemplate(DM dm, MPI_Comm comm, DM *tdm)
    117: {
    118:   DM_Forest                  *forest = (DM_Forest*) dm->data;
    119:   DMType                     type;
    120:   DM                         base;
    121:   DMForestTopology           topology;
    122:   MatType                    mtype;
    123:   PetscInt                   dim, overlap, ref, factor;
    124:   DMForestAdaptivityStrategy strat;
    125:   void                       *ctx;
    126:   PetscErrorCode             (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void*);
    127:   void                       *mapCtx;

    130:   DMCreate(PetscObjectComm((PetscObject)dm),tdm);
    131:   DMGetType(dm,&type);
    132:   DMSetType(*tdm,type);
    133:   DMForestGetBaseDM(dm,&base);
    134:   DMForestSetBaseDM(*tdm,base);
    135:   DMForestGetTopology(dm,&topology);
    136:   DMForestSetTopology(*tdm,topology);
    137:   DMForestGetAdjacencyDimension(dm,&dim);
    138:   DMForestSetAdjacencyDimension(*tdm,dim);
    139:   DMForestGetPartitionOverlap(dm,&overlap);
    140:   DMForestSetPartitionOverlap(*tdm,overlap);
    141:   DMForestGetMinimumRefinement(dm,&ref);
    142:   DMForestSetMinimumRefinement(*tdm,ref);
    143:   DMForestGetMaximumRefinement(dm,&ref);
    144:   DMForestSetMaximumRefinement(*tdm,ref);
    145:   DMForestGetAdaptivityStrategy(dm,&strat);
    146:   DMForestSetAdaptivityStrategy(*tdm,strat);
    147:   DMForestGetGradeFactor(dm,&factor);
    148:   DMForestSetGradeFactor(*tdm,factor);
    149:   DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx);
    150:   DMForestSetBaseCoordinateMapping(*tdm,map,mapCtx);
    151:   if (forest->ftemplate) {
    152:     (*forest->ftemplate)(dm, *tdm);
    153:   }
    154:   DMForestSetAdaptivityForest(*tdm,dm);
    155:   DMCopyDisc(dm,*tdm);
    156:   DMGetApplicationContext(dm,&ctx);
    157:   DMSetApplicationContext(*tdm,&ctx);
    158:   {
    159:     PetscBool            isper;
    160:     const PetscReal      *maxCell, *L;
    161:     const DMBoundaryType *bd;

    163:     DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);
    164:     DMSetPeriodicity(*tdm,isper,maxCell,L,bd);
    165:   }
    166:   DMGetMatType(dm,&mtype);
    167:   DMSetMatType(*tdm,mtype);
    168:   return 0;
    169: }

    171: static PetscErrorCode DMInitialize_Forest(DM dm);

    173: PETSC_EXTERN PetscErrorCode DMClone_Forest(DM dm, DM *newdm)
    174: {
    175:   DM_Forest      *forest = (DM_Forest*) dm->data;
    176:   const char     *type;

    178:   forest->refct++;
    179:   (*newdm)->data = forest;
    180:   PetscObjectGetType((PetscObject) dm, &type);
    181:   PetscObjectChangeTypeName((PetscObject) *newdm, type);
    182:   DMInitialize_Forest(*newdm);
    183:   return 0;
    184: }

    186: static PetscErrorCode DMDestroy_Forest(DM dm)
    187: {
    188:   DM_Forest      *forest = (DM_Forest*) dm->data;

    190:   if (--forest->refct > 0) return 0;
    191:   if (forest->destroy) (*forest->destroy)(dm);
    192:   PetscSFDestroy(&forest->cellSF);
    193:   PetscSFDestroy(&forest->preCoarseToFine);
    194:   PetscSFDestroy(&forest->coarseToPreFine);
    195:   DMLabelDestroy(&forest->adaptLabel);
    196:   PetscFree(forest->adaptStrategy);
    197:   DMDestroy(&forest->base);
    198:   DMDestroy(&forest->adapt);
    199:   PetscFree(forest->topology);
    200:   PetscFree(forest);
    201:   return 0;
    202: }

    204: /*@C
    205:   DMForestSetTopology - Set the topology of a DMForest during the pre-setup phase.  The topology is a string (e.g.
    206:   "cube", "shell") and can be interpreted by subtypes of DMFOREST) to construct the base DM of a forest during
    207:   DMSetUp().

    209:   Logically collective on dm

    211:   Input parameters:
    212: + dm - the forest
    213: - topology - the topology of the forest

    215:   Level: intermediate

    217: .seealso: DMForestGetTopology(), DMForestSetBaseDM()
    218: @*/
    219: PetscErrorCode DMForestSetTopology(DM dm, DMForestTopology topology)
    220: {
    221:   DM_Forest      *forest = (DM_Forest*) dm->data;

    225:   PetscFree(forest->topology);
    226:   PetscStrallocpy((const char*)topology,(char**) &forest->topology);
    227:   return 0;
    228: }

    230: /*@C
    231:   DMForestGetTopology - Get a string describing the topology of a DMForest.

    233:   Not collective

    235:   Input parameter:
    236: . dm - the forest

    238:   Output parameter:
    239: . topology - the topology of the forest (e.g., 'cube', 'shell')

    241:   Level: intermediate

    243: .seealso: DMForestSetTopology()
    244: @*/
    245: PetscErrorCode DMForestGetTopology(DM dm, DMForestTopology *topology)
    246: {
    247:   DM_Forest *forest = (DM_Forest*) dm->data;

    251:   *topology = forest->topology;
    252:   return 0;
    253: }

    255: /*@
    256:   DMForestSetBaseDM - During the pre-setup phase, set the DM that defines the base mesh of a DMForest forest.  The
    257:   forest will be hierarchically refined from the base, and all refinements/coarsenings of the forest will share its
    258:   base.  In general, two forest must share a base to be comparable, to do things like construct interpolators.

    260:   Logically collective on dm

    262:   Input Parameters:
    263: + dm - the forest
    264: - base - the base DM of the forest

    266:   Notes:
    267:     Currently the base DM must be a DMPLEX

    269:   Level: intermediate

    271: .seealso: DMForestGetBaseDM()
    272: @*/
    273: PetscErrorCode DMForestSetBaseDM(DM dm, DM base)
    274: {
    275:   DM_Forest      *forest = (DM_Forest*) dm->data;
    276:   PetscInt       dim, dimEmbed;

    280:   PetscObjectReference((PetscObject)base);
    281:   DMDestroy(&forest->base);
    282:   forest->base = base;
    283:   if (base) {
    284:     PetscBool        isper;
    285:     const PetscReal *maxCell, *L;
    286:     const DMBoundaryType *bd;

    289:     DMGetDimension(base,&dim);
    290:     DMSetDimension(dm,dim);
    291:     DMGetCoordinateDim(base,&dimEmbed);
    292:     DMSetCoordinateDim(dm,dimEmbed);
    293:     DMGetPeriodicity(base,&isper,&maxCell,&L,&bd);
    294:     DMSetPeriodicity(dm,isper,maxCell,L,bd);
    295:   } else {
    296:     DMSetPeriodicity(dm,PETSC_FALSE,NULL,NULL,NULL);
    297:   }
    298:   return 0;
    299: }

    301: /*@
    302:   DMForestGetBaseDM - Get the base DM of a DMForest forest.  The forest will be hierarchically refined from the base,
    303:   and all refinements/coarsenings of the forest will share its base.  In general, two forest must share a base to be
    304:   comparable, to do things like construct interpolators.

    306:   Not collective

    308:   Input Parameter:
    309: . dm - the forest

    311:   Output Parameter:
    312: . base - the base DM of the forest

    314:   Notes:
    315:     After DMSetUp(), the base DM will be redundantly distributed across MPI processes

    317:   Level: intermediate

    319: .seealso: DMForestSetBaseDM()
    320: @*/
    321: PetscErrorCode DMForestGetBaseDM(DM dm, DM *base)
    322: {
    323:   DM_Forest *forest = (DM_Forest*) dm->data;

    327:   *base = forest->base;
    328:   return 0;
    329: }

    331: PetscErrorCode DMForestSetBaseCoordinateMapping(DM dm, PetscErrorCode (*func)(DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx)
    332: {
    333:   DM_Forest *forest = (DM_Forest*) dm->data;

    336:   forest->mapcoordinates    = func;
    337:   forest->mapcoordinatesctx = ctx;
    338:   return 0;
    339: }

    341: PetscErrorCode DMForestGetBaseCoordinateMapping(DM dm, PetscErrorCode (**func) (DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx)
    342: {
    343:   DM_Forest *forest = (DM_Forest*) dm->data;

    346:   if (func) *func = forest->mapcoordinates;
    347:   if (ctx) *((void**) ctx) = forest->mapcoordinatesctx;
    348:   return 0;
    349: }

    351: /*@
    352:   DMForestSetAdaptivityForest - During the pre-setup phase, set the forest from which the current forest will be
    353:   adapted (e.g., the current forest will be refined/coarsened/repartitioned from it) im DMSetUp().  Usually not needed
    354:   by users directly: DMForestTemplate() constructs a new forest to be adapted from an old forest and calls this
    355:   routine.

    357:   Note that this can be called after setup with adapt = NULL, which will clear all internal data related to the
    358:   adaptivity forest from dm.  This way, repeatedly adapting does not leave stale DM objects in memory.

    360:   Logically collective on dm

    362:   Input Parameters:
    363: + dm - the new forest, which will be constructed from adapt
    364: - adapt - the old forest

    366:   Level: intermediate

    368: .seealso: DMForestGetAdaptivityForest(), DMForestSetAdaptivityPurpose()
    369: @*/
    370: PetscErrorCode DMForestSetAdaptivityForest(DM dm,DM adapt)
    371: {
    372:   DM_Forest      *forest, *adaptForest, *oldAdaptForest;
    373:   DM             oldAdapt;
    374:   PetscBool      isForest;

    378:   DMIsForest(dm, &isForest);
    379:   if (!isForest) return 0;
    381:   forest         = (DM_Forest*) dm->data;
    382:   DMForestGetAdaptivityForest(dm,&oldAdapt);
    383:   adaptForest    = (DM_Forest*) (adapt ? adapt->data : NULL);
    384:   oldAdaptForest = (DM_Forest*) (oldAdapt ? oldAdapt->data : NULL);
    385:   if (adaptForest != oldAdaptForest) {
    386:     PetscSFDestroy(&forest->preCoarseToFine);
    387:     PetscSFDestroy(&forest->coarseToPreFine);
    388:     if (forest->clearadaptivityforest) (*forest->clearadaptivityforest)(dm);
    389:   }
    390:   switch (forest->adaptPurpose) {
    391:   case DM_ADAPT_DETERMINE:
    392:     PetscObjectReference((PetscObject)adapt);
    393:     DMDestroy(&(forest->adapt));
    394:     forest->adapt = adapt;
    395:     break;
    396:   case DM_ADAPT_REFINE:
    397:     DMSetCoarseDM(dm,adapt);
    398:     break;
    399:   case DM_ADAPT_COARSEN:
    400:   case DM_ADAPT_COARSEN_LAST:
    401:     DMSetFineDM(dm,adapt);
    402:     break;
    403:   default:
    404:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose");
    405:   }
    406:   return 0;
    407: }

    409: /*@
    410:   DMForestGetAdaptivityForest - Get the forest from which the current forest is adapted.

    412:   Not collective

    414:   Input Parameter:
    415: . dm - the forest

    417:   Output Parameter:
    418: . adapt - the forest from which dm is/was adapted

    420:   Level: intermediate

    422: .seealso: DMForestSetAdaptivityForest(), DMForestSetAdaptivityPurpose()
    423: @*/
    424: PetscErrorCode DMForestGetAdaptivityForest(DM dm, DM *adapt)
    425: {
    426:   DM_Forest      *forest;

    429:   forest = (DM_Forest*) dm->data;
    430:   switch (forest->adaptPurpose) {
    431:   case DM_ADAPT_DETERMINE:
    432:     *adapt = forest->adapt;
    433:     break;
    434:   case DM_ADAPT_REFINE:
    435:     DMGetCoarseDM(dm,adapt);
    436:     break;
    437:   case DM_ADAPT_COARSEN:
    438:   case DM_ADAPT_COARSEN_LAST:
    439:     DMGetFineDM(dm,adapt);
    440:     break;
    441:   default:
    442:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose");
    443:   }
    444:   return 0;
    445: }

    447: /*@
    448:   DMForestSetAdaptivityPurpose - During the pre-setup phase, set whether the current DM is being adapted from its
    449:   source (set with DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening
    450:   (DM_ADAPT_COARSEN), or undefined (DM_ADAPT_DETERMINE).  This only matters for the purposes of reference counting:
    451:   during DMDestroy(), cyclic references can be found between DMs only if the cyclic reference is due to a fine/coarse
    452:   relationship (see DMSetFineDM()/DMSetCoarseDM()).  If the purpose is not refinement or coarsening, and the user does
    453:   not maintain a reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can
    454:   cause a memory leak.  This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.

    456:   Logically collective on dm

    458:   Input Parameters:
    459: + dm - the forest
    460: - purpose - the adaptivity purpose

    462:   Level: advanced

    464: .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest(), DMAdaptFlag
    465: @*/
    466: PetscErrorCode DMForestSetAdaptivityPurpose(DM dm, DMAdaptFlag purpose)
    467: {
    468:   DM_Forest      *forest;

    470:   forest = (DM_Forest*) dm->data;
    472:   if (purpose != forest->adaptPurpose) {
    473:     DM adapt;

    475:     DMForestGetAdaptivityForest(dm,&adapt);
    476:     PetscObjectReference((PetscObject)adapt);
    477:     DMForestSetAdaptivityForest(dm,NULL);

    479:     forest->adaptPurpose = purpose;

    481:     DMForestSetAdaptivityForest(dm,adapt);
    482:     DMDestroy(&adapt);
    483:   }
    484:   return 0;
    485: }

    487: /*@
    488:   DMForestGetAdaptivityPurpose - Get whether the current DM is being adapted from its source (set with
    489:   DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening (DM_ADAPT_COARSEN),
    490:   coarsening only the last level (DM_ADAPT_COARSEN_LAST) or undefined (DM_ADAPT_DETERMINE).
    491:   This only matters for the purposes of reference counting: during DMDestroy(), cyclic
    492:   references can be found between DMs only if the cyclic reference is due to a fine/coarse relationship (see
    493:   DMSetFineDM()/DMSetCoarseDM()).  If the purpose is not refinement or coarsening, and the user does not maintain a
    494:   reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can cause a memory
    495:   leak.  This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.

    497:   Not collective

    499:   Input Parameter:
    500: . dm - the forest

    502:   Output Parameter:
    503: . purpose - the adaptivity purpose

    505:   Level: advanced

    507: .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest(), DMAdaptFlag
    508: @*/
    509: PetscErrorCode DMForestGetAdaptivityPurpose(DM dm, DMAdaptFlag *purpose)
    510: {
    511:   DM_Forest *forest;

    513:   forest   = (DM_Forest*) dm->data;
    514:   *purpose = forest->adaptPurpose;
    515:   return 0;
    516: }

    518: /*@
    519:   DMForestSetAdjacencyDimension - During the pre-setup phase, set the dimension of interface points that determine
    520:   cell adjacency (for the purposes of partitioning and overlap).

    522:   Logically collective on dm

    524:   Input Parameters:
    525: + dm - the forest
    526: - adjDim - default 0 (i.e., vertices determine adjacency)

    528:   Level: intermediate

    530: .seealso: DMForestGetAdjacencyDimension(), DMForestSetAdjacencyCodimension(), DMForestSetPartitionOverlap()
    531: @*/
    532: PetscErrorCode DMForestSetAdjacencyDimension(DM dm, PetscInt adjDim)
    533: {
    534:   PetscInt       dim;
    535:   DM_Forest      *forest = (DM_Forest*) dm->data;

    540:   DMGetDimension(dm,&dim);
    542:   forest->adjDim = adjDim;
    543:   return 0;
    544: }

    546: /*@
    547:   DMForestSetAdjacencyCodimension - Like DMForestSetAdjacencyDimension(), but specified as a co-dimension (so that,
    548:   e.g., adjacency based on facets can be specified by codimension 1 in all cases)

    550:   Logically collective on dm

    552:   Input Parameters:
    553: + dm - the forest
    554: - adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices

    556:   Level: intermediate

    558: .seealso: DMForestGetAdjacencyCodimension(), DMForestSetAdjacencyDimension()
    559: @*/
    560: PetscErrorCode DMForestSetAdjacencyCodimension(DM dm, PetscInt adjCodim)
    561: {
    562:   PetscInt       dim;

    565:   DMGetDimension(dm,&dim);
    566:   DMForestSetAdjacencyDimension(dm,dim-adjCodim);
    567:   return 0;
    568: }

    570: /*@
    571:   DMForestGetAdjacencyDimension - Get the dimension of interface points that determine cell adjacency (for the
    572:   purposes of partitioning and overlap).

    574:   Not collective

    576:   Input Parameter:
    577: . dm - the forest

    579:   Output Parameter:
    580: . adjDim - default 0 (i.e., vertices determine adjacency)

    582:   Level: intermediate

    584: .seealso: DMForestSetAdjacencyDimension(), DMForestGetAdjacencyCodimension(), DMForestSetPartitionOverlap()
    585: @*/
    586: PetscErrorCode DMForestGetAdjacencyDimension(DM dm, PetscInt *adjDim)
    587: {
    588:   DM_Forest *forest = (DM_Forest*) dm->data;

    592:   *adjDim = forest->adjDim;
    593:   return 0;
    594: }

    596: /*@
    597:   DMForestGetAdjacencyCodimension - Like DMForestGetAdjacencyDimension(), but specified as a co-dimension (so that,
    598:   e.g., adjacency based on facets can be specified by codimension 1 in all cases)

    600:   Not collective

    602:   Input Parameter:
    603: . dm - the forest

    605:   Output Parameter:
    606: . adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices

    608:   Level: intermediate

    610: .seealso: DMForestSetAdjacencyCodimension(), DMForestGetAdjacencyDimension()
    611: @*/
    612: PetscErrorCode DMForestGetAdjacencyCodimension(DM dm, PetscInt *adjCodim)
    613: {
    614:   DM_Forest      *forest = (DM_Forest*) dm->data;
    615:   PetscInt       dim;

    619:   DMGetDimension(dm,&dim);
    620:   *adjCodim = dim - forest->adjDim;
    621:   return 0;
    622: }

    624: /*@
    625:   DMForestSetPartitionOverlap - During the pre-setup phase, set the amount of cell-overlap present in parallel
    626:   partitions of a forest, with values > 0 indicating subdomains that are expanded by that many iterations of adding
    627:   adjacent cells

    629:   Logically collective on dm

    631:   Input Parameters:
    632: + dm - the forest
    633: - overlap - default 0

    635:   Level: intermediate

    637: .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension()
    638: @*/
    639: PetscErrorCode DMForestSetPartitionOverlap(DM dm, PetscInt overlap)
    640: {
    641:   DM_Forest *forest = (DM_Forest*) dm->data;

    646:   forest->overlap = overlap;
    647:   return 0;
    648: }

    650: /*@
    651:   DMForestGetPartitionOverlap - Get the amount of cell-overlap present in parallel partitions of a forest, with values
    652:   > 0 indicating subdomains that are expanded by that many iterations of adding adjacent cells

    654:   Not collective

    656:   Input Parameter:
    657: . dm - the forest

    659:   Output Parameter:
    660: . overlap - default 0

    662:   Level: intermediate

    664: .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension()
    665: @*/
    666: PetscErrorCode DMForestGetPartitionOverlap(DM dm, PetscInt *overlap)
    667: {
    668:   DM_Forest *forest = (DM_Forest*) dm->data;

    672:   *overlap = forest->overlap;
    673:   return 0;
    674: }

    676: /*@
    677:   DMForestSetMinimumRefinement - During the pre-setup phase, set the minimum level of refinement (relative to the base
    678:   DM, see DMForestGetBaseDM()) allowed in the forest.  If the forest is being created by coarsening a previous forest
    679:   (see DMForestGetAdaptivityForest()) this limits the amount of coarsening.

    681:   Logically collective on dm

    683:   Input Parameters:
    684: + dm - the forest
    685: - minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)

    687:   Level: intermediate

    689: .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
    690: @*/
    691: PetscErrorCode DMForestSetMinimumRefinement(DM dm, PetscInt minRefinement)
    692: {
    693:   DM_Forest *forest = (DM_Forest*) dm->data;

    697:   forest->minRefinement = minRefinement;
    698:   return 0;
    699: }

    701: /*@
    702:   DMForestGetMinimumRefinement - Get the minimum level of refinement (relative to the base DM, see
    703:   DMForestGetBaseDM()) allowed in the forest.  If the forest is being created by coarsening a previous forest (see
    704:   DMForestGetAdaptivityForest()), this limits the amount of coarsening.

    706:   Not collective

    708:   Input Parameter:
    709: . dm - the forest

    711:   Output Parameter:
    712: . minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)

    714:   Level: intermediate

    716: .seealso: DMForestSetMinimumRefinement(), DMForestGetMaximumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
    717: @*/
    718: PetscErrorCode DMForestGetMinimumRefinement(DM dm, PetscInt *minRefinement)
    719: {
    720:   DM_Forest *forest = (DM_Forest*) dm->data;

    724:   *minRefinement = forest->minRefinement;
    725:   return 0;
    726: }

    728: /*@
    729:   DMForestSetInitialRefinement - During the pre-setup phase, set the initial level of refinement (relative to the base
    730:   DM, see DMForestGetBaseDM()) allowed in the forest.

    732:   Logically collective on dm

    734:   Input Parameters:
    735: + dm - the forest
    736: - initefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)

    738:   Level: intermediate

    740: .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM()
    741: @*/
    742: PetscErrorCode DMForestSetInitialRefinement(DM dm, PetscInt initRefinement)
    743: {
    744:   DM_Forest *forest = (DM_Forest*) dm->data;

    748:   forest->initRefinement = initRefinement;
    749:   return 0;
    750: }

    752: /*@
    753:   DMForestGetInitialRefinement - Get the initial level of refinement (relative to the base DM, see
    754:   DMForestGetBaseDM()) allowed in the forest.

    756:   Not collective

    758:   Input Parameter:
    759: . dm - the forest

    761:   Output Parameter:
    762: . initRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)

    764:   Level: intermediate

    766: .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM()
    767: @*/
    768: PetscErrorCode DMForestGetInitialRefinement(DM dm, PetscInt *initRefinement)
    769: {
    770:   DM_Forest *forest = (DM_Forest*) dm->data;

    774:   *initRefinement = forest->initRefinement;
    775:   return 0;
    776: }

    778: /*@
    779:   DMForestSetMaximumRefinement - During the pre-setup phase, set the maximum level of refinement (relative to the base
    780:   DM, see DMForestGetBaseDM()) allowed in the forest.  If the forest is being created by refining a previous forest
    781:   (see DMForestGetAdaptivityForest()), this limits the amount of refinement.

    783:   Logically collective on dm

    785:   Input Parameters:
    786: + dm - the forest
    787: - maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)

    789:   Level: intermediate

    791: .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityDM()
    792: @*/
    793: PetscErrorCode DMForestSetMaximumRefinement(DM dm, PetscInt maxRefinement)
    794: {
    795:   DM_Forest *forest = (DM_Forest*) dm->data;

    799:   forest->maxRefinement = maxRefinement;
    800:   return 0;
    801: }

    803: /*@
    804:   DMForestGetMaximumRefinement - Get the maximum level of refinement (relative to the base DM, see
    805:   DMForestGetBaseDM()) allowed in the forest.  If the forest is being created by refining a previous forest (see
    806:   DMForestGetAdaptivityForest()), this limits the amount of refinement.

    808:   Not collective

    810:   Input Parameter:
    811: . dm - the forest

    813:   Output Parameter:
    814: . maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)

    816:   Level: intermediate

    818: .seealso: DMForestSetMaximumRefinement(), DMForestGetMinimumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
    819: @*/
    820: PetscErrorCode DMForestGetMaximumRefinement(DM dm, PetscInt *maxRefinement)
    821: {
    822:   DM_Forest *forest = (DM_Forest*) dm->data;

    826:   *maxRefinement = forest->maxRefinement;
    827:   return 0;
    828: }

    830: /*@C
    831:   DMForestSetAdaptivityStrategy - During the pre-setup phase, set the strategy for combining adaptivity labels from multiple processes.
    832:   Subtypes of DMForest may define their own strategies.  Two default strategies are DMFORESTADAPTALL, which indicates that all processes must agree
    833:   for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only one process needs to
    834:   specify refinement/coarsening.

    836:   Logically collective on dm

    838:   Input Parameters:
    839: + dm - the forest
    840: - adaptStrategy - default DMFORESTADAPTALL

    842:   Level: advanced

    844: .seealso: DMForestGetAdaptivityStrategy()
    845: @*/
    846: PetscErrorCode DMForestSetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy adaptStrategy)
    847: {
    848:   DM_Forest      *forest = (DM_Forest*) dm->data;

    851:   PetscFree(forest->adaptStrategy);
    852:   PetscStrallocpy((const char*) adaptStrategy,(char**)&forest->adaptStrategy);
    853:   return 0;
    854: }

    856: /*@C
    857:   DMForestSetAdaptivityStrategy - Get the strategy for combining adaptivity labels from multiple processes.  Subtypes
    858:   of DMForest may define their own strategies.  Two default strategies are DMFORESTADAPTALL, which indicates that all
    859:   processes must agree for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only
    860:   one process needs to specify refinement/coarsening.

    862:   Not collective

    864:   Input Parameter:
    865: . dm - the forest

    867:   Output Parameter:
    868: . adaptStrategy - the adaptivity strategy (default DMFORESTADAPTALL)

    870:   Level: advanced

    872: .seealso: DMForestSetAdaptivityStrategy()
    873: @*/
    874: PetscErrorCode DMForestGetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy *adaptStrategy)
    875: {
    876:   DM_Forest *forest = (DM_Forest*) dm->data;

    880:   *adaptStrategy = forest->adaptStrategy;
    881:   return 0;
    882: }

    884: /*@
    885:   DMForestGetAdaptivitySuccess - Return whether the requested adaptation (refinement, coarsening, repartitioning,
    886:   etc.) was successful.  PETSC_FALSE indicates that the post-adaptation forest is the same as the pre-adpatation
    887:   forest.  A requested adaptation may have been unsuccessful if, for example, the requested refinement would have
    888:   exceeded the maximum refinement level.

    890:   Collective on dm

    892:   Input Parameter:

    894: . dm - the post-adaptation forest

    896:   Output Parameter:

    898: . success - PETSC_TRUE if the post-adaptation forest is different from the pre-adaptation forest.

    900:   Level: intermediate

    902: .see
    903: @*/
    904: PetscErrorCode DMForestGetAdaptivitySuccess(DM dm, PetscBool *success)
    905: {
    906:   DM_Forest      *forest;

    910:   forest = (DM_Forest *) dm->data;
    911:   (forest->getadaptivitysuccess)(dm,success);
    912:   return 0;
    913: }

    915: /*@
    916:   DMForestSetComputeAdaptivitySF - During the pre-setup phase, set whether transfer PetscSFs should be computed
    917:   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().

    919:   Logically collective on dm

    921:   Input Parameters:
    922: + dm - the post-adaptation forest
    923: - computeSF - default PETSC_TRUE

    925:   Level: advanced

    927: .seealso: DMForestGetComputeAdaptivitySF(), DMForestGetAdaptivitySF()
    928: @*/
    929: PetscErrorCode DMForestSetComputeAdaptivitySF(DM dm, PetscBool computeSF)
    930: {
    931:   DM_Forest *forest;

    935:   forest                 = (DM_Forest*) dm->data;
    936:   forest->computeAdaptSF = computeSF;
    937:   return 0;
    938: }

    940: PetscErrorCode DMForestTransferVec(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time)
    941: {
    942:   DM_Forest      *forest;

    948:   forest = (DM_Forest *) dmIn->data;
    950:   (forest->transfervec)(dmIn,vecIn,dmOut,vecOut,useBCs,time);
    951:   return 0;
    952: }

    954: PetscErrorCode DMForestTransferVecFromBase(DM dm, Vec vecIn, Vec vecOut)
    955: {
    956:   DM_Forest      *forest;

    961:   forest = (DM_Forest *) dm->data;
    963:   (forest->transfervecfrombase)(dm,vecIn,vecOut);
    964:   return 0;
    965: }

    967: /*@
    968:   DMForestGetComputeAdaptivitySF - Get whether transfer PetscSFs should be computed relating the cells of the
    969:   pre-adaptation forest to the post-adaptiation forest.  After DMSetUp() is called, these transfer PetscSFs can be
    970:   accessed with DMForestGetAdaptivitySF().

    972:   Not collective

    974:   Input Parameter:
    975: . dm - the post-adaptation forest

    977:   Output Parameter:
    978: . computeSF - default PETSC_TRUE

    980:   Level: advanced

    982: .seealso: DMForestSetComputeAdaptivitySF(), DMForestGetAdaptivitySF()
    983: @*/
    984: PetscErrorCode DMForestGetComputeAdaptivitySF(DM dm, PetscBool *computeSF)
    985: {
    986:   DM_Forest *forest;

    989:   forest     = (DM_Forest*) dm->data;
    990:   *computeSF = forest->computeAdaptSF;
    991:   return 0;
    992: }

    994: /*@
    995:   DMForestGetAdaptivitySF - Get PetscSFs that relate the pre-adaptation forest to the post-adaptation forest.
    996:   Adaptation can be any combination of refinement, coarsening, repartition, and change of overlap, so there may be
    997:   some cells of the pre-adaptation that are parents of post-adaptation cells, and vice versa.  Therefore there are two
    998:   PetscSFs: one that relates pre-adaptation coarse cells to post-adaptation fine cells, and one that relates
    999:   pre-adaptation fine cells to post-adaptation coarse cells.

    1001:   Not collective

    1003:   Input Parameter:
    1004:   dm - the post-adaptation forest

    1006:   Output Parameter:
    1007:   preCoarseToFine - pre-adaptation coarse cells to post-adaptation fine cells: BCast goes from pre- to post-
    1008:   coarseToPreFine - post-adaptation coarse cells to pre-adaptation fine cells: BCast goes from post- to pre-

    1010:   Level: advanced

    1012: .seealso: DMForestGetComputeAdaptivitySF(), DMForestSetComputeAdaptivitySF()
    1013: @*/
    1014: PetscErrorCode DMForestGetAdaptivitySF(DM dm, PetscSF *preCoarseToFine, PetscSF *coarseToPreFine)
    1015: {
    1016:   DM_Forest      *forest;

    1019:   DMSetUp(dm);
    1020:   forest = (DM_Forest*) dm->data;
    1021:   if (preCoarseToFine) *preCoarseToFine = forest->preCoarseToFine;
    1022:   if (coarseToPreFine) *coarseToPreFine = forest->coarseToPreFine;
    1023:   return 0;
    1024: }

    1026: /*@
    1027:   DMForestSetGradeFactor - During the pre-setup phase, set the desired amount of grading in the mesh, e.g. give 2 to
    1028:   indicate that the diameter of neighboring cells should differ by at most a factor of 2.  Subtypes of DMForest may
    1029:   only support one particular choice of grading factor.

    1031:   Logically collective on dm

    1033:   Input Parameters:
    1034: + dm - the forest
    1035: - grade - the grading factor

    1037:   Level: advanced

    1039: .seealso: DMForestGetGradeFactor()
    1040: @*/
    1041: PetscErrorCode DMForestSetGradeFactor(DM dm, PetscInt grade)
    1042: {
    1043:   DM_Forest *forest = (DM_Forest*) dm->data;

    1047:   forest->gradeFactor = grade;
    1048:   return 0;
    1049: }

    1051: /*@
    1052:   DMForestGetGradeFactor - Get the desired amount of grading in the mesh, e.g. give 2 to indicate that the diameter of
    1053:   neighboring cells should differ by at most a factor of 2.  Subtypes of DMForest may only support one particular
    1054:   choice of grading factor.

    1056:   Not collective

    1058:   Input Parameter:
    1059: . dm - the forest

    1061:   Output Parameter:
    1062: . grade - the grading factor

    1064:   Level: advanced

    1066: .seealso: DMForestSetGradeFactor()
    1067: @*/
    1068: PetscErrorCode DMForestGetGradeFactor(DM dm, PetscInt *grade)
    1069: {
    1070:   DM_Forest *forest = (DM_Forest*) dm->data;

    1074:   *grade = forest->gradeFactor;
    1075:   return 0;
    1076: }

    1078: /*@
    1079:   DMForestSetCellWeightFactor - During the pre-setup phase, set the factor by which the level of refinement changes
    1080:   the cell weight (see DMForestSetCellWeights()) when calculating partitions.  The final weight of a cell will be
    1081:   (cellWeight) * (weightFactor^refinementLevel).  A factor of 1 indicates that the weight of a cell does not depend on
    1082:   its level; a factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the
    1083:   computation associated with a cell is multiplied by a factor of 2 for each additional level of refinement.

    1085:   Logically collective on dm

    1087:   Input Parameters:
    1088: + dm - the forest
    1089: - weightsFactors - default 1.

    1091:   Level: advanced

    1093: .seealso: DMForestGetCellWeightFactor(), DMForestSetCellWeights()
    1094: @*/
    1095: PetscErrorCode DMForestSetCellWeightFactor(DM dm, PetscReal weightsFactor)
    1096: {
    1097:   DM_Forest *forest = (DM_Forest*) dm->data;

    1101:   forest->weightsFactor = weightsFactor;
    1102:   return 0;
    1103: }

    1105: /*@
    1106:   DMForestGetCellWeightFactor - Get the factor by which the level of refinement changes the cell weight (see
    1107:   DMForestSetCellWeights()) when calculating partitions.  The final weight of a cell will be (cellWeight) *
    1108:   (weightFactor^refinementLevel).  A factor of 1 indicates that the weight of a cell does not depend on its level; a
    1109:   factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the computation
    1110:   associated with a cell is multiplied by a factor of 2 for each additional level of refinement.

    1112:   Not collective

    1114:   Input Parameter:
    1115: . dm - the forest

    1117:   Output Parameter:
    1118: . weightsFactors - default 1.

    1120:   Level: advanced

    1122: .seealso: DMForestSetCellWeightFactor(), DMForestSetCellWeights()
    1123: @*/
    1124: PetscErrorCode DMForestGetCellWeightFactor(DM dm, PetscReal *weightsFactor)
    1125: {
    1126:   DM_Forest *forest = (DM_Forest*) dm->data;

    1130:   *weightsFactor = forest->weightsFactor;
    1131:   return 0;
    1132: }

    1134: /*@
    1135:   DMForestGetCellChart - After the setup phase, get the local half-open interval of the chart of cells on this process

    1137:   Not collective

    1139:   Input Parameter:
    1140: . dm - the forest

    1142:   Output Parameters:
    1143: + cStart - the first cell on this process
    1144: - cEnd - one after the final cell on this process

    1146:   Level: intermediate

    1148: .seealso: DMForestGetCellSF()
    1149: @*/
    1150: PetscErrorCode DMForestGetCellChart(DM dm, PetscInt *cStart, PetscInt *cEnd)
    1151: {
    1152:   DM_Forest      *forest = (DM_Forest*) dm->data;

    1157:   if (((forest->cStart == PETSC_DETERMINE) || (forest->cEnd == PETSC_DETERMINE)) && forest->createcellchart) {
    1158:     forest->createcellchart(dm,&forest->cStart,&forest->cEnd);
    1159:   }
    1160:   *cStart =  forest->cStart;
    1161:   *cEnd   =  forest->cEnd;
    1162:   return 0;
    1163: }

    1165: /*@
    1166:   DMForestGetCellSF - After the setup phase, get the PetscSF for overlapping cells between processes

    1168:   Not collective

    1170:   Input Parameter:
    1171: . dm - the forest

    1173:   Output Parameter:
    1174: . cellSF - the PetscSF

    1176:   Level: intermediate

    1178: .seealso: DMForestGetCellChart()
    1179: @*/
    1180: PetscErrorCode DMForestGetCellSF(DM dm, PetscSF *cellSF)
    1181: {
    1182:   DM_Forest      *forest = (DM_Forest*) dm->data;

    1186:   if ((!forest->cellSF) && forest->createcellsf) {
    1187:     forest->createcellsf(dm,&forest->cellSF);
    1188:   }
    1189:   *cellSF = forest->cellSF;
    1190:   return 0;
    1191: }

    1193: /*@C
    1194:   DMForestSetAdaptivityLabel - During the pre-setup phase, set the label of the pre-adaptation forest (see
    1195:   DMForestGetAdaptivityForest()) that holds the adaptation flags (refinement, coarsening, or some combination).  The
    1196:   interpretation of the label values is up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP,
    1197:   DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have been reserved as choices that should be accepted by all subtypes.

    1199:   Logically collective on dm

    1201:   Input Parameters:
    1202: - dm - the forest
    1203: + adaptLabel - the label in the pre-adaptation forest

    1205:   Level: intermediate

    1207: .seealso DMForestGetAdaptivityLabel()
    1208: @*/
    1209: PetscErrorCode DMForestSetAdaptivityLabel(DM dm, DMLabel adaptLabel)
    1210: {
    1211:   DM_Forest      *forest = (DM_Forest*) dm->data;

    1215:   PetscObjectReference((PetscObject)adaptLabel);
    1216:   DMLabelDestroy(&forest->adaptLabel);
    1217:   forest->adaptLabel = adaptLabel;
    1218:   return 0;
    1219: }

    1221: /*@C
    1222:   DMForestGetAdaptivityLabel - Get the label of the pre-adaptation forest (see DMForestGetAdaptivityForest()) that
    1223:   holds the adaptation flags (refinement, coarsening, or some combination).  The interpretation of the label values is
    1224:   up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have
    1225:   been reserved as choices that should be accepted by all subtypes.

    1227:   Not collective

    1229:   Input Parameter:
    1230: . dm - the forest

    1232:   Output Parameter:
    1233: . adaptLabel - the name of the label in the pre-adaptation forest

    1235:   Level: intermediate

    1237: .seealso DMForestSetAdaptivityLabel()
    1238: @*/
    1239: PetscErrorCode DMForestGetAdaptivityLabel(DM dm, DMLabel *adaptLabel)
    1240: {
    1241:   DM_Forest *forest = (DM_Forest*) dm->data;

    1244:   *adaptLabel = forest->adaptLabel;
    1245:   return 0;
    1246: }

    1248: /*@
    1249:   DMForestSetCellWeights - Set the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
    1250:   process: weights are used to determine parallel partitioning.  Partitions will be created so that each process's
    1251:   ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
    1252:   of 1.

    1254:   Logically collective on dm

    1256:   Input Parameters:
    1257: + dm - the forest
    1258: . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.
    1259: - copyMode - how weights should reference weights

    1261:   Level: advanced

    1263: .seealso: DMForestGetCellWeights(), DMForestSetWeightCapacity()
    1264: @*/
    1265: PetscErrorCode DMForestSetCellWeights(DM dm, PetscReal weights[], PetscCopyMode copyMode)
    1266: {
    1267:   DM_Forest      *forest = (DM_Forest*) dm->data;
    1268:   PetscInt       cStart, cEnd;

    1271:   DMForestGetCellChart(dm,&cStart,&cEnd);
    1273:   if (copyMode == PETSC_COPY_VALUES) {
    1274:     if (forest->cellWeightsCopyMode != PETSC_OWN_POINTER || forest->cellWeights == weights) {
    1275:       PetscMalloc1(cEnd-cStart,&forest->cellWeights);
    1276:     }
    1277:     PetscArraycpy(forest->cellWeights,weights,cEnd-cStart);
    1278:     forest->cellWeightsCopyMode = PETSC_OWN_POINTER;
    1279:     return 0;
    1280:   }
    1281:   if (forest->cellWeightsCopyMode == PETSC_OWN_POINTER) {
    1282:     PetscFree(forest->cellWeights);
    1283:   }
    1284:   forest->cellWeights         = weights;
    1285:   forest->cellWeightsCopyMode = copyMode;
    1286:   return 0;
    1287: }

    1289: /*@
    1290:   DMForestGetCellWeights - Get the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
    1291:   process: weights are used to determine parallel partitioning.  Partitions will be created so that each process's
    1292:   ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
    1293:   of 1.

    1295:   Not collective

    1297:   Input Parameter:
    1298: . dm - the forest

    1300:   Output Parameter:
    1301: . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.

    1303:   Level: advanced

    1305: .seealso: DMForestSetCellWeights(), DMForestSetWeightCapacity()
    1306: @*/
    1307: PetscErrorCode DMForestGetCellWeights(DM dm, PetscReal **weights)
    1308: {
    1309:   DM_Forest *forest = (DM_Forest*) dm->data;

    1313:   *weights = forest->cellWeights;
    1314:   return 0;
    1315: }

    1317: /*@
    1318:   DMForestSetWeightCapacity - During the pre-setup phase, set the capacity of the current process when repartitioning
    1319:   a pre-adaptation forest (see DMForestGetAdaptivityForest()).  After partitioning, the ratio of the weight of each
    1320:   process's cells to the process's capacity will be roughly equal for all processes.  A capacity of 0 indicates that
    1321:   the current process should not have any cells after repartitioning.

    1323:   Logically Collective on dm

    1325:   Input parameters:
    1326: + dm - the forest
    1327: - capacity - this process's capacity

    1329:   Level: advanced

    1331: .seealso DMForestGetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor()
    1332: @*/
    1333: PetscErrorCode DMForestSetWeightCapacity(DM dm, PetscReal capacity)
    1334: {
    1335:   DM_Forest *forest = (DM_Forest*) dm->data;

    1340:   forest->weightCapacity = capacity;
    1341:   return 0;
    1342: }

    1344: /*@
    1345:   DMForestGetWeightCapacity - Set the capacity of the current process when repartitioning a pre-adaptation forest (see
    1346:   DMForestGetAdaptivityForest()).  After partitioning, the ratio of the weight of each process's cells to the
    1347:   process's capacity will be roughly equal for all processes.  A capacity of 0 indicates that the current process
    1348:   should not have any cells after repartitioning.

    1350:   Not collective

    1352:   Input parameter:
    1353: . dm - the forest

    1355:   Output parameter:
    1356: . capacity - this process's capacity

    1358:   Level: advanced

    1360: .seealso DMForestSetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor()
    1361: @*/
    1362: PetscErrorCode DMForestGetWeightCapacity(DM dm, PetscReal *capacity)
    1363: {
    1364:   DM_Forest *forest = (DM_Forest*) dm->data;

    1368:   *capacity = forest->weightCapacity;
    1369:   return 0;
    1370: }

    1372: PETSC_EXTERN PetscErrorCode DMSetFromOptions_Forest(PetscOptionItems *PetscOptionsObject,DM dm)
    1373: {
    1374:   PetscBool                  flg, flg1, flg2, flg3, flg4;
    1375:   DMForestTopology           oldTopo;
    1376:   char                       stringBuffer[256];
    1377:   PetscViewer                viewer;
    1378:   PetscViewerFormat          format;
    1379:   PetscInt                   adjDim, adjCodim, overlap, minRefinement, initRefinement, maxRefinement, grade;
    1380:   PetscReal                  weightsFactor;
    1381:   DMForestAdaptivityStrategy adaptStrategy;

    1384:   DMForestGetTopology(dm, &oldTopo);
    1385:   PetscOptionsHead(PetscOptionsObject,"DMForest Options");
    1386:   PetscOptionsString("-dm_forest_topology","the topology of the forest's base mesh","DMForestSetTopology",oldTopo,stringBuffer,sizeof(stringBuffer),&flg1);
    1387:   PetscOptionsViewer("-dm_forest_base_dm","load the base DM from a viewer specification","DMForestSetBaseDM",&viewer,&format,&flg2);
    1388:   PetscOptionsViewer("-dm_forest_coarse_forest","load the coarse forest from a viewer specification","DMForestSetCoarseForest",&viewer,&format,&flg3);
    1389:   PetscOptionsViewer("-dm_forest_fine_forest","load the fine forest from a viewer specification","DMForestSetFineForest",&viewer,&format,&flg4);
    1391:   if (flg1) {
    1392:     DMForestSetTopology(dm,(DMForestTopology)stringBuffer);
    1393:     DMForestSetBaseDM(dm,NULL);
    1394:     DMForestSetAdaptivityForest(dm,NULL);
    1395:   }
    1396:   if (flg2) {
    1397:     DM base;

    1399:     DMCreate(PetscObjectComm((PetscObject)dm),&base);
    1400:     PetscViewerPushFormat(viewer,format);
    1401:     DMLoad(base,viewer);
    1402:     PetscViewerDestroy(&viewer);
    1403:     DMForestSetBaseDM(dm,base);
    1404:     DMDestroy(&base);
    1405:     DMForestSetTopology(dm,NULL);
    1406:     DMForestSetAdaptivityForest(dm,NULL);
    1407:   }
    1408:   if (flg3) {
    1409:     DM coarse;

    1411:     DMCreate(PetscObjectComm((PetscObject)dm),&coarse);
    1412:     PetscViewerPushFormat(viewer,format);
    1413:     DMLoad(coarse,viewer);
    1414:     PetscViewerDestroy(&viewer);
    1415:     DMForestSetAdaptivityForest(dm,coarse);
    1416:     DMDestroy(&coarse);
    1417:     DMForestSetTopology(dm,NULL);
    1418:     DMForestSetBaseDM(dm,NULL);
    1419:   }
    1420:   if (flg4) {
    1421:     DM fine;

    1423:     DMCreate(PetscObjectComm((PetscObject)dm),&fine);
    1424:     PetscViewerPushFormat(viewer,format);
    1425:     DMLoad(fine,viewer);
    1426:     PetscViewerDestroy(&viewer);
    1427:     DMForestSetAdaptivityForest(dm,fine);
    1428:     DMDestroy(&fine);
    1429:     DMForestSetTopology(dm,NULL);
    1430:     DMForestSetBaseDM(dm,NULL);
    1431:   }
    1432:   DMForestGetAdjacencyDimension(dm,&adjDim);
    1433:   PetscOptionsBoundedInt("-dm_forest_adjacency_dimension","set the dimension of points that define adjacency in the forest","DMForestSetAdjacencyDimension",adjDim,&adjDim,&flg,0);
    1434:   if (flg) {
    1435:     DMForestSetAdjacencyDimension(dm,adjDim);
    1436:   } else {
    1437:     DMForestGetAdjacencyCodimension(dm,&adjCodim);
    1438:     PetscOptionsBoundedInt("-dm_forest_adjacency_codimension","set the codimension of points that define adjacency in the forest","DMForestSetAdjacencyCodimension",adjCodim,&adjCodim,&flg,1);
    1439:     if (flg) {
    1440:       DMForestSetAdjacencyCodimension(dm,adjCodim);
    1441:     }
    1442:   }
    1443:   DMForestGetPartitionOverlap(dm,&overlap);
    1444:   PetscOptionsBoundedInt("-dm_forest_partition_overlap","set the degree of partition overlap","DMForestSetPartitionOverlap",overlap,&overlap,&flg,0);
    1445:   if (flg) {
    1446:     DMForestSetPartitionOverlap(dm,overlap);
    1447:   }
    1448: #if 0
    1449:   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);
    1450:   if (flg) {
    1451:     DMForestSetMinimumRefinement(dm,minRefinement);
    1452:     DMForestSetInitialRefinement(dm,minRefinement);
    1453:   }
    1454:   PetscOptionsBoundedInt("-dm_refine_hierarchy","equivalent to -dm_forest_set_minimum_refinement 0 and -dm_forest_set_initial_refinement",NULL,initRefinement,&initRefinement,&flg,0);
    1455:   if (flg) {
    1456:     DMForestSetMinimumRefinement(dm,0);
    1457:     DMForestSetInitialRefinement(dm,initRefinement);
    1458:   }
    1459: #endif
    1460:   DMForestGetMinimumRefinement(dm,&minRefinement);
    1461:   PetscOptionsBoundedInt("-dm_forest_minimum_refinement","set the minimum level of refinement in the forest","DMForestSetMinimumRefinement",minRefinement,&minRefinement,&flg,0);
    1462:   if (flg) {
    1463:     DMForestSetMinimumRefinement(dm,minRefinement);
    1464:   }
    1465:   DMForestGetInitialRefinement(dm,&initRefinement);
    1466:   PetscOptionsBoundedInt("-dm_forest_initial_refinement","set the initial level of refinement in the forest","DMForestSetInitialRefinement",initRefinement,&initRefinement,&flg,0);
    1467:   if (flg) {
    1468:     DMForestSetInitialRefinement(dm,initRefinement);
    1469:   }
    1470:   DMForestGetMaximumRefinement(dm,&maxRefinement);
    1471:   PetscOptionsBoundedInt("-dm_forest_maximum_refinement","set the maximum level of refinement in the forest","DMForestSetMaximumRefinement",maxRefinement,&maxRefinement,&flg,0);
    1472:   if (flg) {
    1473:     DMForestSetMaximumRefinement(dm,maxRefinement);
    1474:   }
    1475:   DMForestGetAdaptivityStrategy(dm,&adaptStrategy);
    1476:   PetscOptionsString("-dm_forest_adaptivity_strategy","the forest's adaptivity-flag resolution strategy","DMForestSetAdaptivityStrategy",adaptStrategy,stringBuffer,sizeof(stringBuffer),&flg);
    1477:   if (flg) {
    1478:     DMForestSetAdaptivityStrategy(dm,(DMForestAdaptivityStrategy)stringBuffer);
    1479:   }
    1480:   DMForestGetGradeFactor(dm,&grade);
    1481:   PetscOptionsBoundedInt("-dm_forest_grade_factor","grade factor between neighboring cells","DMForestSetGradeFactor",grade,&grade,&flg,0);
    1482:   if (flg) {
    1483:     DMForestSetGradeFactor(dm,grade);
    1484:   }
    1485:   DMForestGetCellWeightFactor(dm,&weightsFactor);
    1486:   PetscOptionsReal("-dm_forest_cell_weight_factor","multiplying weight factor for cell refinement","DMForestSetCellWeightFactor",weightsFactor,&weightsFactor,&flg);
    1487:   if (flg) {
    1488:     DMForestSetCellWeightFactor(dm,weightsFactor);
    1489:   }
    1490:   PetscOptionsTail();
    1491:   return 0;
    1492: }

    1494: PetscErrorCode DMCreateSubDM_Forest(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
    1495: {
    1496:   if (subdm) DMClone(dm, subdm);
    1497:   DMCreateSectionSubDM(dm, numFields, fields, is, subdm);
    1498:   return 0;
    1499: }

    1501: PetscErrorCode DMRefine_Forest(DM dm, MPI_Comm comm, DM *dmRefined)
    1502: {
    1503:   DMLabel        refine;
    1504:   DM             fineDM;

    1506:   DMGetFineDM(dm,&fineDM);
    1507:   if (fineDM) {
    1508:     PetscObjectReference((PetscObject)fineDM);
    1509:     *dmRefined = fineDM;
    1510:     return 0;
    1511:   }
    1512:   DMForestTemplate(dm,comm,dmRefined);
    1513:   DMGetLabel(dm,"refine",&refine);
    1514:   if (!refine) {
    1515:     DMLabelCreate(PETSC_COMM_SELF, "refine",&refine);
    1516:     DMLabelSetDefaultValue(refine,DM_ADAPT_REFINE);
    1517:   } else {
    1518:     PetscObjectReference((PetscObject) refine);
    1519:   }
    1520:   DMForestSetAdaptivityLabel(*dmRefined,refine);
    1521:   DMLabelDestroy(&refine);
    1522:   return 0;
    1523: }

    1525: PetscErrorCode DMCoarsen_Forest(DM dm, MPI_Comm comm, DM *dmCoarsened)
    1526: {
    1527:   DMLabel        coarsen;
    1528:   DM             coarseDM;

    1530:   {
    1531:     PetscMPIInt mpiComparison;
    1532:     MPI_Comm    dmcomm = PetscObjectComm((PetscObject)dm);

    1534:     MPI_Comm_compare(comm, dmcomm, &mpiComparison);
    1536:   }
    1537:   DMGetCoarseDM(dm,&coarseDM);
    1538:   if (coarseDM) {
    1539:     PetscObjectReference((PetscObject)coarseDM);
    1540:     *dmCoarsened = coarseDM;
    1541:     return 0;
    1542:   }
    1543:   DMForestTemplate(dm,comm,dmCoarsened);
    1544:   DMForestSetAdaptivityPurpose(*dmCoarsened,DM_ADAPT_COARSEN);
    1545:   DMGetLabel(dm,"coarsen",&coarsen);
    1546:   if (!coarsen) {
    1547:     DMLabelCreate(PETSC_COMM_SELF, "coarsen",&coarsen);
    1548:     DMLabelSetDefaultValue(coarsen,DM_ADAPT_COARSEN);
    1549:   } else {
    1550:     PetscObjectReference((PetscObject) coarsen);
    1551:   }
    1552:   DMForestSetAdaptivityLabel(*dmCoarsened,coarsen);
    1553:   DMLabelDestroy(&coarsen);
    1554:   return 0;
    1555: }

    1557: PetscErrorCode DMAdaptLabel_Forest(DM dm, PETSC_UNUSED Vec metric, DMLabel label, PETSC_UNUSED DMLabel rgLabel, DM *adaptedDM)
    1558: {
    1559:   PetscBool      success;

    1561:   DMForestTemplate(dm,PetscObjectComm((PetscObject)dm),adaptedDM);
    1562:   DMForestSetAdaptivityLabel(*adaptedDM,label);
    1563:   DMSetUp(*adaptedDM);
    1564:   DMForestGetAdaptivitySuccess(*adaptedDM,&success);
    1565:   if (!success) {
    1566:     DMDestroy(adaptedDM);
    1567:     *adaptedDM = NULL;
    1568:   }
    1569:   return 0;
    1570: }

    1572: static PetscErrorCode DMInitialize_Forest(DM dm)
    1573: {
    1574:   PetscMemzero(dm->ops,sizeof(*(dm->ops)));

    1576:   dm->ops->clone          = DMClone_Forest;
    1577:   dm->ops->setfromoptions = DMSetFromOptions_Forest;
    1578:   dm->ops->destroy        = DMDestroy_Forest;
    1579:   dm->ops->createsubdm    = DMCreateSubDM_Forest;
    1580:   dm->ops->refine         = DMRefine_Forest;
    1581:   dm->ops->coarsen        = DMCoarsen_Forest;
    1582:   return 0;
    1583: }

    1585: /*MC

    1587:      DMFOREST = "forest" - A DM object that encapsulates a hierarchically refined mesh.  Forests usually have a base DM
    1588:   (see DMForestGetBaseDM()), from which it is refined.  The refinement and partitioning of forests is considered
    1589:   immutable after DMSetUp() is called.  To adapt a mesh, one should call DMForestTemplate() to create a new mesh that
    1590:   will default to being identical to it, specify how that mesh should differ, and then calling DMSetUp() on the new
    1591:   mesh.

    1593:   To specify that a mesh should be refined or coarsened from the previous mesh, a label should be defined on the
    1594:   previous mesh whose values indicate which cells should be refined (DM_ADAPT_REFINE) or coarsened (DM_ADAPT_COARSEN)
    1595:   and how (subtypes are free to allow additional values for things like anisotropic refinement).  The label should be
    1596:   given to the *new* mesh with DMForestSetAdaptivityLabel().

    1598:   Level: advanced

    1600: .seealso: DMType, DMCreate(), DMSetType(), DMForestGetBaseDM(), DMForestSetBaseDM(), DMForestTemplate(), DMForestSetAdaptivityLabel()
    1601: M*/

    1603: PETSC_EXTERN PetscErrorCode DMCreate_Forest(DM dm)
    1604: {
    1605:   DM_Forest      *forest;

    1608:   PetscNewLog(dm,&forest);
    1609:   dm->dim                      = 0;
    1610:   dm->data                     = forest;
    1611:   forest->refct                = 1;
    1612:   forest->data                 = NULL;
    1613:   forest->topology             = NULL;
    1614:   forest->adapt                = NULL;
    1615:   forest->base                 = NULL;
    1616:   forest->adaptPurpose         = DM_ADAPT_DETERMINE;
    1617:   forest->adjDim               = PETSC_DEFAULT;
    1618:   forest->overlap              = PETSC_DEFAULT;
    1619:   forest->minRefinement        = PETSC_DEFAULT;
    1620:   forest->maxRefinement        = PETSC_DEFAULT;
    1621:   forest->initRefinement       = PETSC_DEFAULT;
    1622:   forest->cStart               = PETSC_DETERMINE;
    1623:   forest->cEnd                 = PETSC_DETERMINE;
    1624:   forest->cellSF               = NULL;
    1625:   forest->adaptLabel           = NULL;
    1626:   forest->gradeFactor          = 2;
    1627:   forest->cellWeights          = NULL;
    1628:   forest->cellWeightsCopyMode  = PETSC_USE_POINTER;
    1629:   forest->weightsFactor        = 1.;
    1630:   forest->weightCapacity       = 1.;
    1631:   DMForestSetAdaptivityStrategy(dm,DMFORESTADAPTALL);
    1632:   DMInitialize_Forest(dm);
    1633:   return 0;
    1634: }