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: char *name;
12: DMForestTypeLink next;
13: };
15: DMForestTypeLink DMForestTypeList;
17: static PetscErrorCode DMForestPackageFinalize(void)
18: {
19: DMForestTypeLink oldLink, link = DMForestTypeList;
21: PetscFunctionBegin;
22: while (link) {
23: oldLink = link;
24: PetscCall(PetscFree(oldLink->name));
25: link = oldLink->next;
26: PetscCall(PetscFree(oldLink));
27: }
28: PetscFunctionReturn(PETSC_SUCCESS);
29: }
31: static PetscErrorCode DMForestPackageInitialize(void)
32: {
33: PetscFunctionBegin;
34: if (DMForestPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
35: DMForestPackageInitialized = PETSC_TRUE;
37: PetscCall(DMForestRegisterType(DMFOREST));
38: PetscCall(PetscRegisterFinalize(DMForestPackageFinalize));
39: PetscFunctionReturn(PETSC_SUCCESS);
40: }
42: /*@C
43: DMForestRegisterType - Registers a `DMType` as a subtype of `DMFOREST` (so that `DMIsForest()` will be correct)
45: Not Collective
47: Input parameter:
48: . name - the name of the type
50: Level: advanced
52: .seealso: `DMFOREST`, `DMIsForest()`
53: @*/
54: PetscErrorCode DMForestRegisterType(DMType name)
55: {
56: DMForestTypeLink link;
58: PetscFunctionBegin;
59: PetscCall(DMForestPackageInitialize());
60: PetscCall(PetscNew(&link));
61: PetscCall(PetscStrallocpy(name, &link->name));
62: link->next = DMForestTypeList;
63: DMForestTypeList = link;
64: PetscFunctionReturn(PETSC_SUCCESS);
65: }
67: /*@
68: DMIsForest - Check whether a DM uses the DMFOREST interface for hierarchically-refined meshes
70: Not Collective
72: Input parameter:
73: . dm - the DM object
75: Output parameter:
76: . isForest - whether dm is a subtype of DMFOREST
78: Level: intermediate
80: .seealso: `DMFOREST`, `DMForestRegisterType()`
81: @*/
82: PetscErrorCode DMIsForest(DM dm, PetscBool *isForest)
83: {
84: DMForestTypeLink link = DMForestTypeList;
86: PetscFunctionBegin;
87: while (link) {
88: PetscBool sameType;
89: PetscCall(PetscObjectTypeCompare((PetscObject)dm, link->name, &sameType));
90: if (sameType) {
91: *isForest = PETSC_TRUE;
92: PetscFunctionReturn(PETSC_SUCCESS);
93: }
94: link = link->next;
95: }
96: *isForest = PETSC_FALSE;
97: PetscFunctionReturn(PETSC_SUCCESS);
98: }
100: /*@
101: DMForestTemplate - Create a new `DM` that will be adapted from a source `DM`. The new `DM` reproduces the configuration
102: of the source, but is not yet setup, so that the user can then define only the ways that the new `DM` should differ
103: (by, e.g., refinement or repartitioning). The source `DM` is also set as the adaptivity source `DM` of the new `DM` (see
104: `DMForestSetAdaptivityForest()`).
106: Collective
108: Input Parameters:
109: + dm - the source `DM` object
110: - comm - the communicator for the new `DM` (this communicator is currently ignored, but is present so that `DMForestTemplate()` can be used within `DMCoarsen()`)
112: Output Parameter:
113: . tdm - the new `DM` object
115: Level: intermediate
117: .seealso: `DM`, `DMFOREST`, `DMForestSetAdaptivityForest()`
118: @*/
119: PetscErrorCode DMForestTemplate(DM dm, MPI_Comm comm, DM *tdm)
120: {
121: DM_Forest *forest = (DM_Forest *)dm->data;
122: DMType type;
123: DM base;
124: DMForestTopology topology;
125: MatType mtype;
126: PetscInt dim, overlap, ref, factor;
127: DMForestAdaptivityStrategy strat;
128: void *ctx;
129: PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *);
130: void *mapCtx;
132: PetscFunctionBegin;
134: PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), tdm));
135: PetscCall(DMGetType(dm, &type));
136: PetscCall(DMSetType(*tdm, type));
137: PetscCall(DMForestGetBaseDM(dm, &base));
138: PetscCall(DMForestSetBaseDM(*tdm, base));
139: PetscCall(DMForestGetTopology(dm, &topology));
140: PetscCall(DMForestSetTopology(*tdm, topology));
141: PetscCall(DMForestGetAdjacencyDimension(dm, &dim));
142: PetscCall(DMForestSetAdjacencyDimension(*tdm, dim));
143: PetscCall(DMForestGetPartitionOverlap(dm, &overlap));
144: PetscCall(DMForestSetPartitionOverlap(*tdm, overlap));
145: PetscCall(DMForestGetMinimumRefinement(dm, &ref));
146: PetscCall(DMForestSetMinimumRefinement(*tdm, ref));
147: PetscCall(DMForestGetMaximumRefinement(dm, &ref));
148: PetscCall(DMForestSetMaximumRefinement(*tdm, ref));
149: PetscCall(DMForestGetAdaptivityStrategy(dm, &strat));
150: PetscCall(DMForestSetAdaptivityStrategy(*tdm, strat));
151: PetscCall(DMForestGetGradeFactor(dm, &factor));
152: PetscCall(DMForestSetGradeFactor(*tdm, factor));
153: PetscCall(DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx));
154: PetscCall(DMForestSetBaseCoordinateMapping(*tdm, map, mapCtx));
155: if (forest->ftemplate) PetscCall((*forest->ftemplate)(dm, *tdm));
156: PetscCall(DMForestSetAdaptivityForest(*tdm, dm));
157: PetscCall(DMCopyDisc(dm, *tdm));
158: PetscCall(DMGetApplicationContext(dm, &ctx));
159: PetscCall(DMSetApplicationContext(*tdm, &ctx));
160: {
161: const PetscReal *maxCell, *L, *Lstart;
163: PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
164: PetscCall(DMSetPeriodicity(*tdm, maxCell, Lstart, L));
165: }
166: PetscCall(DMGetMatType(dm, &mtype));
167: PetscCall(DMSetMatType(*tdm, mtype));
168: PetscFunctionReturn(PETSC_SUCCESS);
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: PetscFunctionBegin;
179: forest->refct++;
180: (*newdm)->data = forest;
181: PetscCall(PetscObjectGetType((PetscObject)dm, &type));
182: PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, type));
183: PetscCall(DMInitialize_Forest(*newdm));
184: PetscFunctionReturn(PETSC_SUCCESS);
185: }
187: static PetscErrorCode DMDestroy_Forest(DM dm)
188: {
189: DM_Forest *forest = (DM_Forest *)dm->data;
191: PetscFunctionBegin;
192: if (--forest->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
193: if (forest->destroy) PetscCall((*forest->destroy)(dm));
194: PetscCall(PetscSFDestroy(&forest->cellSF));
195: PetscCall(PetscSFDestroy(&forest->preCoarseToFine));
196: PetscCall(PetscSFDestroy(&forest->coarseToPreFine));
197: PetscCall(DMLabelDestroy(&forest->adaptLabel));
198: PetscCall(PetscFree(forest->adaptStrategy));
199: PetscCall(DMDestroy(&forest->base));
200: PetscCall(DMDestroy(&forest->adapt));
201: PetscCall(PetscFree(forest->topology));
202: PetscCall(PetscFree(forest));
203: PetscFunctionReturn(PETSC_SUCCESS);
204: }
206: /*@C
207: DMForestSetTopology - Set the topology of a `DMFOREST` during the pre-setup phase. The topology is a string (e.g.
208: "cube", "shell") and can be interpreted by subtypes of `DMFOREST`) to construct the base DM of a forest during
209: `DMSetUp()`.
211: Logically collectiv
213: Input parameters:
214: + dm - the forest
215: - topology - the topology of the forest
217: Level: intermediate
219: .seealso: `DM`, `DMFOREST`, `DMForestGetTopology()`, `DMForestSetBaseDM()`
220: @*/
221: PetscErrorCode DMForestSetTopology(DM dm, DMForestTopology topology)
222: {
223: DM_Forest *forest = (DM_Forest *)dm->data;
225: PetscFunctionBegin;
227: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the topology after setup");
228: PetscCall(PetscFree(forest->topology));
229: PetscCall(PetscStrallocpy((const char *)topology, (char **)&forest->topology));
230: PetscFunctionReturn(PETSC_SUCCESS);
231: }
233: /*@C
234: DMForestGetTopology - Get a string describing the topology of a `DMFOREST`.
236: Not Collective
238: Input parameter:
239: . dm - the forest
241: Output parameter:
242: . topology - the topology of the forest (e.g., 'cube', 'shell')
244: Level: intermediate
246: .seealso: `DM`, `DMFOREST`, `DMForestSetTopology()`
247: @*/
248: PetscErrorCode DMForestGetTopology(DM dm, DMForestTopology *topology)
249: {
250: DM_Forest *forest = (DM_Forest *)dm->data;
252: PetscFunctionBegin;
255: *topology = forest->topology;
256: PetscFunctionReturn(PETSC_SUCCESS);
257: }
259: /*@
260: DMForestSetBaseDM - During the pre-setup phase, set the `DM` that defines the base mesh of a `DMFOREST` forest. The
261: forest will be hierarchically refined from the base, and all refinements/coarsenings of the forest will share its
262: base. In general, two forest must share a base to be comparable, to do things like construct interpolators.
264: Logically Collective
266: Input Parameters:
267: + dm - the forest
268: - base - the base `DM` of the forest
270: Level: intermediate
272: Note:
273: Currently the base `DM` must be a `DMPLEX`
275: .seealso: `DM`, `DMFOREST`, `DMForestGetBaseDM()`
276: @*/
277: PetscErrorCode DMForestSetBaseDM(DM dm, DM base)
278: {
279: DM_Forest *forest = (DM_Forest *)dm->data;
280: PetscInt dim, dimEmbed;
282: PetscFunctionBegin;
284: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the base after setup");
285: PetscCall(PetscObjectReference((PetscObject)base));
286: PetscCall(DMDestroy(&forest->base));
287: forest->base = base;
288: if (base) {
289: const PetscReal *maxCell, *Lstart, *L;
292: PetscCall(DMGetDimension(base, &dim));
293: PetscCall(DMSetDimension(dm, dim));
294: PetscCall(DMGetCoordinateDim(base, &dimEmbed));
295: PetscCall(DMSetCoordinateDim(dm, dimEmbed));
296: PetscCall(DMGetPeriodicity(base, &maxCell, &Lstart, &L));
297: PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
298: } else PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
302: /*@
303: DMForestGetBaseDM - Get the base DM of a DMForest forest. The forest will be hierarchically refined from the base,
304: and all refinements/coarsenings of the forest will share its base. In general, two forest must share a base to be
305: comparable, to do things like construct interpolators.
307: Not Collective
309: Input Parameter:
310: . dm - the forest
312: Output Parameter:
313: . base - the base DM of the forest
315: Notes:
316: After DMSetUp(), the base DM will be redundantly distributed across MPI processes
318: Level: intermediate
320: .seealso: `DM`, `DMFOREST`, `DMForestSetBaseDM()`
321: @*/
322: PetscErrorCode DMForestGetBaseDM(DM dm, DM *base)
323: {
324: DM_Forest *forest = (DM_Forest *)dm->data;
326: PetscFunctionBegin;
329: *base = forest->base;
330: PetscFunctionReturn(PETSC_SUCCESS);
331: }
333: PetscErrorCode DMForestSetBaseCoordinateMapping(DM dm, PetscErrorCode (*func)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *), void *ctx)
334: {
335: DM_Forest *forest = (DM_Forest *)dm->data;
337: PetscFunctionBegin;
339: forest->mapcoordinates = func;
340: forest->mapcoordinatesctx = ctx;
341: PetscFunctionReturn(PETSC_SUCCESS);
342: }
344: PetscErrorCode DMForestGetBaseCoordinateMapping(DM dm, PetscErrorCode (**func)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *), void *ctx)
345: {
346: DM_Forest *forest = (DM_Forest *)dm->data;
348: PetscFunctionBegin;
350: if (func) *func = forest->mapcoordinates;
351: if (ctx) *((void **)ctx) = forest->mapcoordinatesctx;
352: PetscFunctionReturn(PETSC_SUCCESS);
353: }
355: /*@
356: DMForestSetAdaptivityForest - During the pre-setup phase, set the forest from which the current forest will be
357: adapted (e.g., the current forest will be refined/coarsened/repartitioned from it) in `DMSetUp()`. Usually not needed
358: by users directly: `DMForestTemplate()` constructs a new forest to be adapted from an old forest and calls this
359: routine.
361: Logically Collective
363: Input Parameters:
364: + dm - the new forest, which will be constructed from adapt
365: - adapt - the old forest
367: Level: intermediate
369: Note:
370: This can be called after setup with `adapt` = `NULL`, which will clear all internal data related to the
371: adaptivity forest from `dm`. This way, repeatedly adapting does not leave stale `DM` objects in memory.
373: .seealso: `DM`, `DMFOREST`, `DMForestGetAdaptivityForest()`, `DMForestSetAdaptivityPurpose()`
374: @*/
375: PetscErrorCode DMForestSetAdaptivityForest(DM dm, DM adapt)
376: {
377: DM_Forest *forest, *adaptForest, *oldAdaptForest;
378: DM oldAdapt;
379: PetscBool isForest;
381: PetscFunctionBegin;
384: PetscCall(DMIsForest(dm, &isForest));
385: if (!isForest) PetscFunctionReturn(PETSC_SUCCESS);
386: PetscCheck(adapt == NULL || !dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the adaptation forest after setup");
387: forest = (DM_Forest *)dm->data;
388: PetscCall(DMForestGetAdaptivityForest(dm, &oldAdapt));
389: adaptForest = (DM_Forest *)(adapt ? adapt->data : NULL);
390: oldAdaptForest = (DM_Forest *)(oldAdapt ? oldAdapt->data : NULL);
391: if (adaptForest != oldAdaptForest) {
392: PetscCall(PetscSFDestroy(&forest->preCoarseToFine));
393: PetscCall(PetscSFDestroy(&forest->coarseToPreFine));
394: if (forest->clearadaptivityforest) PetscCall((*forest->clearadaptivityforest)(dm));
395: }
396: switch (forest->adaptPurpose) {
397: case DM_ADAPT_DETERMINE:
398: PetscCall(PetscObjectReference((PetscObject)adapt));
399: PetscCall(DMDestroy(&(forest->adapt)));
400: forest->adapt = adapt;
401: break;
402: case DM_ADAPT_REFINE:
403: PetscCall(DMSetCoarseDM(dm, adapt));
404: break;
405: case DM_ADAPT_COARSEN:
406: case DM_ADAPT_COARSEN_LAST:
407: PetscCall(DMSetFineDM(dm, adapt));
408: break;
409: default:
410: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid adaptivity purpose");
411: }
412: PetscFunctionReturn(PETSC_SUCCESS);
413: }
415: /*@
416: DMForestGetAdaptivityForest - Get the forest from which the current forest is adapted.
418: Not Collective
420: Input Parameter:
421: . dm - the forest
423: Output Parameter:
424: . adapt - the forest from which `dm` is/was adapted
426: Level: intermediate
428: .seealso: `DM`, `DMFOREST`, `DMForestSetAdaptivityForest()`, `DMForestSetAdaptivityPurpose()`
429: @*/
430: PetscErrorCode DMForestGetAdaptivityForest(DM dm, DM *adapt)
431: {
432: DM_Forest *forest;
434: PetscFunctionBegin;
436: forest = (DM_Forest *)dm->data;
437: switch (forest->adaptPurpose) {
438: case DM_ADAPT_DETERMINE:
439: *adapt = forest->adapt;
440: break;
441: case DM_ADAPT_REFINE:
442: PetscCall(DMGetCoarseDM(dm, adapt));
443: break;
444: case DM_ADAPT_COARSEN:
445: case DM_ADAPT_COARSEN_LAST:
446: PetscCall(DMGetFineDM(dm, adapt));
447: break;
448: default:
449: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid adaptivity purpose");
450: }
451: PetscFunctionReturn(PETSC_SUCCESS);
452: }
454: /*@
455: DMForestSetAdaptivityPurpose - During the pre-setup phase, set whether the current `DM` is being adapted from its
456: source (set with `DMForestSetAdaptivityForest()`) for the purpose of refinement (`DM_ADAPT_REFINE`), coarsening
457: (`DM_ADAPT_COARSEN`), or undefined (`DM_ADAPT_DETERMINE`). This only matters for the purposes of reference counting:
458: during `DMDestroy()`, cyclic references can be found between `DM`s only if the cyclic reference is due to a fine/coarse
459: relationship (see `DMSetFineDM()`/`DMSetCoarseDM()`). If the purpose is not refinement or coarsening, and the user does
460: not maintain a reference to the post-adaptation forest (i.e., the one created by `DMForestTemplate()`), then this can
461: cause a memory leak. This method is used by subtypes of `DMFOREST` when automatically constructing mesh hierarchies.
463: Logically Collective
465: Input Parameters:
466: + dm - the forest
467: - purpose - the adaptivity purpose
469: Level: advanced
471: .seealso: `DM`, `DMFOREST`, `DMForestTemplate()`, `DMForestSetAdaptivityForest()`, `DMForestGetAdaptivityForest()`, `DMAdaptFlag`
472: @*/
473: PetscErrorCode DMForestSetAdaptivityPurpose(DM dm, DMAdaptFlag purpose)
474: {
475: DM_Forest *forest;
477: PetscFunctionBegin;
478: forest = (DM_Forest *)dm->data;
479: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the adaptation forest after setup");
480: if (purpose != forest->adaptPurpose) {
481: DM adapt;
483: PetscCall(DMForestGetAdaptivityForest(dm, &adapt));
484: PetscCall(PetscObjectReference((PetscObject)adapt));
485: PetscCall(DMForestSetAdaptivityForest(dm, NULL));
487: forest->adaptPurpose = purpose;
489: PetscCall(DMForestSetAdaptivityForest(dm, adapt));
490: PetscCall(DMDestroy(&adapt));
491: }
492: PetscFunctionReturn(PETSC_SUCCESS);
493: }
495: /*@
496: DMForestGetAdaptivityPurpose - Get whether the current `DM` is being adapted from its source (set with
497: `DMForestSetAdaptivityForest()`) for the purpose of refinement (`DM_ADAPT_REFINE`), coarsening (`DM_ADAPT_COARSEN`),
498: coarsening only the last level (`DM_ADAPT_COARSEN_LAST`) or undefined (`DM_ADAPT_DETERMINE`).
499: This only matters for the purposes of reference counting: during `DMDestroy()`, cyclic
500: references can be found between `DM`s only if the cyclic reference is due to a fine/coarse relationship (see
501: `DMSetFineDM()`/`DMSetCoarseDM()`). If the purpose is not refinement or coarsening, and the user does not maintain a
502: reference to the post-adaptation forest (i.e., the one created by `DMForestTemplate()`), then this can cause a memory
503: leak. This method is used by subtypes of `DMFOREST` when automatically constructing mesh hierarchies.
505: Not Collective
507: Input Parameter:
508: . dm - the forest
510: Output Parameter:
511: . purpose - the adaptivity purpose
513: Level: advanced
515: .seealso: `DM`, `DMFOREST`, `DMForestTemplate()`, `DMForestSetAdaptivityForest()`, `DMForestGetAdaptivityForest()`, `DMAdaptFlag`
516: @*/
517: PetscErrorCode DMForestGetAdaptivityPurpose(DM dm, DMAdaptFlag *purpose)
518: {
519: DM_Forest *forest;
521: PetscFunctionBegin;
522: forest = (DM_Forest *)dm->data;
523: *purpose = forest->adaptPurpose;
524: PetscFunctionReturn(PETSC_SUCCESS);
525: }
527: /*@
528: DMForestSetAdjacencyDimension - During the pre-setup phase, set the dimension of interface points that determine
529: cell adjacency (for the purposes of partitioning and overlap).
531: Logically Collective
533: Input Parameters:
534: + dm - the forest
535: - adjDim - default 0 (i.e., vertices determine adjacency)
537: Level: intermediate
539: .seealso: `DM`, `DMFOREST`, `DMForestGetAdjacencyDimension()`, `DMForestSetAdjacencyCodimension()`, `DMForestSetPartitionOverlap()`
540: @*/
541: PetscErrorCode DMForestSetAdjacencyDimension(DM dm, PetscInt adjDim)
542: {
543: PetscInt dim;
544: DM_Forest *forest = (DM_Forest *)dm->data;
546: PetscFunctionBegin;
548: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the adjacency dimension after setup");
549: PetscCheck(adjDim >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "adjacency dim cannot be < 0: %" PetscInt_FMT, adjDim);
550: PetscCall(DMGetDimension(dm, &dim));
551: PetscCheck(adjDim <= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "adjacency dim cannot be > %" PetscInt_FMT ": %" PetscInt_FMT, dim, adjDim);
552: forest->adjDim = adjDim;
553: PetscFunctionReturn(PETSC_SUCCESS);
554: }
556: /*@
557: DMForestSetAdjacencyCodimension - Like `DMForestSetAdjacencyDimension()`, but specified as a co-dimension (so that,
558: e.g., adjacency based on facets can be specified by codimension 1 in all cases)
560: Logically Collective
562: Input Parameters:
563: + dm - the forest
564: - adjCodim - default is the dimension of the forest (see `DMGetDimension()`), since this is the codimension of vertices
566: Level: intermediate
568: .seealso: `DM`, `DMFOREST`, `DMForestGetAdjacencyCodimension()`, `DMForestSetAdjacencyDimension()`
569: @*/
570: PetscErrorCode DMForestSetAdjacencyCodimension(DM dm, PetscInt adjCodim)
571: {
572: PetscInt dim;
574: PetscFunctionBegin;
576: PetscCall(DMGetDimension(dm, &dim));
577: PetscCall(DMForestSetAdjacencyDimension(dm, dim - adjCodim));
578: PetscFunctionReturn(PETSC_SUCCESS);
579: }
581: /*@
582: DMForestGetAdjacencyDimension - Get the dimension of interface points that determine cell adjacency (for the
583: purposes of partitioning and overlap).
585: Not Collective
587: Input Parameter:
588: . dm - the forest
590: Output Parameter:
591: . adjDim - default 0 (i.e., vertices determine adjacency)
593: Level: intermediate
595: .seealso: `DM`, `DMFOREST`, `DMForestSetAdjacencyDimension()`, `DMForestGetAdjacencyCodimension()`, `DMForestSetPartitionOverlap()`
596: @*/
597: PetscErrorCode DMForestGetAdjacencyDimension(DM dm, PetscInt *adjDim)
598: {
599: DM_Forest *forest = (DM_Forest *)dm->data;
601: PetscFunctionBegin;
604: *adjDim = forest->adjDim;
605: PetscFunctionReturn(PETSC_SUCCESS);
606: }
608: /*@
609: DMForestGetAdjacencyCodimension - Like `DMForestGetAdjacencyDimension()`, but specified as a co-dimension (so that,
610: e.g., adjacency based on facets can be specified by codimension 1 in all cases)
612: Not Collective
614: Input Parameter:
615: . dm - the forest
617: Output Parameter:
618: . adjCodim - default isthe dimension of the forest (see `DMGetDimension()`), since this is the codimension of vertices
620: Level: intermediate
622: .seealso: `DM`, `DMFOREST`, `DMForestSetAdjacencyCodimension()`, `DMForestGetAdjacencyDimension()`
623: @*/
624: PetscErrorCode DMForestGetAdjacencyCodimension(DM dm, PetscInt *adjCodim)
625: {
626: DM_Forest *forest = (DM_Forest *)dm->data;
627: PetscInt dim;
629: PetscFunctionBegin;
632: PetscCall(DMGetDimension(dm, &dim));
633: *adjCodim = dim - forest->adjDim;
634: PetscFunctionReturn(PETSC_SUCCESS);
635: }
637: /*@
638: DMForestSetPartitionOverlap - During the pre-setup phase, set the amount of cell-overlap present in parallel
639: partitions of a forest, with values > 0 indicating subdomains that are expanded by that many iterations of adding
640: adjacent cells
642: Logically Collective
644: Input Parameters:
645: + dm - the forest
646: - overlap - default 0
648: Level: intermediate
650: .seealso: `DM`, `DMFOREST`, `DMForestGetPartitionOverlap()`, `DMForestSetAdjacencyDimension()`, `DMForestSetAdjacencyCodimension()`
651: @*/
652: PetscErrorCode DMForestSetPartitionOverlap(DM dm, PetscInt overlap)
653: {
654: DM_Forest *forest = (DM_Forest *)dm->data;
656: PetscFunctionBegin;
658: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the overlap after setup");
659: PetscCheck(overlap >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "overlap cannot be < 0: %" PetscInt_FMT, overlap);
660: forest->overlap = overlap;
661: PetscFunctionReturn(PETSC_SUCCESS);
662: }
664: /*@
665: DMForestGetPartitionOverlap - Get the amount of cell-overlap present in parallel partitions of a forest, with values
666: > 0 indicating subdomains that are expanded by that many iterations of adding adjacent cells
668: Not Collective
670: Input Parameter:
671: . dm - the forest
673: Output Parameter:
674: . overlap - default 0
676: Level: intermediate
678: .seealso: `DM`, `DMFOREST`, `DMForestGetPartitionOverlap()`, `DMForestSetAdjacencyDimension()`, `DMForestSetAdjacencyCodimension()`
679: @*/
680: PetscErrorCode DMForestGetPartitionOverlap(DM dm, PetscInt *overlap)
681: {
682: DM_Forest *forest = (DM_Forest *)dm->data;
684: PetscFunctionBegin;
687: *overlap = forest->overlap;
688: PetscFunctionReturn(PETSC_SUCCESS);
689: }
691: /*@
692: DMForestSetMinimumRefinement - During the pre-setup phase, set the minimum level of refinement (relative to the base
693: `DM`, see `DMForestGetBaseDM()`) allowed in the forest. If the forest is being created by coarsening a previous forest
694: (see `DMForestGetAdaptivityForest()`) this limits the amount of coarsening.
696: Logically Collective
698: Input Parameters:
699: + dm - the forest
700: - minRefinement - default `PETSC_DEFAULT` (interpreted by the subtype of `DMFOREST`)
702: Level: intermediate
704: .seealso: `DM`, `DMFOREST`, `DMForestGetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestSetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityForest()`
705: @*/
706: PetscErrorCode DMForestSetMinimumRefinement(DM dm, PetscInt minRefinement)
707: {
708: DM_Forest *forest = (DM_Forest *)dm->data;
710: PetscFunctionBegin;
712: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the minimum refinement after setup");
713: forest->minRefinement = minRefinement;
714: PetscFunctionReturn(PETSC_SUCCESS);
715: }
717: /*@
718: DMForestGetMinimumRefinement - Get the minimum level of refinement (relative to the base `DM`, see
719: `DMForestGetBaseDM()`) allowed in the forest. If the forest is being created by coarsening a previous forest (see
720: `DMForestGetAdaptivityForest()`), this limits the amount of coarsening.
722: Not Collective
724: Input Parameter:
725: . dm - the forest
727: Output Parameter:
728: . minRefinement - default `PETSC_DEFAULT` (interpreted by the subtype of `DMFOREST`)
730: Level: intermediate
732: .seealso: `DM`, `DMFOREST`, `DMForestSetMinimumRefinement()`, `DMForestGetMaximumRefinement()`, `DMForestGetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityForest()`
733: @*/
734: PetscErrorCode DMForestGetMinimumRefinement(DM dm, PetscInt *minRefinement)
735: {
736: DM_Forest *forest = (DM_Forest *)dm->data;
738: PetscFunctionBegin;
741: *minRefinement = forest->minRefinement;
742: PetscFunctionReturn(PETSC_SUCCESS);
743: }
745: /*@
746: DMForestSetInitialRefinement - During the pre-setup phase, set the initial level of refinement (relative to the base
747: `DM`, see `DMForestGetBaseDM()`) allowed in the forest.
749: Logically Collective
751: Input Parameters:
752: + dm - the forest
753: - initefinement - default `PETSC_DEFAULT` (interpreted by the subtype of `DMFOREST`)
755: Level: intermediate
757: .seealso: `DM`, `DMFOREST`, `DMForestSetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestGetBaseDM()`
758: @*/
759: PetscErrorCode DMForestSetInitialRefinement(DM dm, PetscInt initRefinement)
760: {
761: DM_Forest *forest = (DM_Forest *)dm->data;
763: PetscFunctionBegin;
765: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the initial refinement after setup");
766: forest->initRefinement = initRefinement;
767: PetscFunctionReturn(PETSC_SUCCESS);
768: }
770: /*@
771: DMForestGetInitialRefinement - Get the initial level of refinement (relative to the base `DM`, see
772: `DMForestGetBaseDM()`) allowed in the forest.
774: Not Collective
776: Input Parameter:
777: . dm - the forest
779: Output Parameter:
780: . initRefinement - default `PETSC_DEFAULT` (interpreted by the subtype of `DMFOREST`)
782: Level: intermediate
784: .seealso: `DM`, `DMFOREST`, `DMForestSetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestGetBaseDM()`
785: @*/
786: PetscErrorCode DMForestGetInitialRefinement(DM dm, PetscInt *initRefinement)
787: {
788: DM_Forest *forest = (DM_Forest *)dm->data;
790: PetscFunctionBegin;
793: *initRefinement = forest->initRefinement;
794: PetscFunctionReturn(PETSC_SUCCESS);
795: }
797: /*@
798: DMForestSetMaximumRefinement - During the pre-setup phase, set the maximum level of refinement (relative to the base
799: `DM`, see `DMForestGetBaseDM()`) allowed in the forest. If the forest is being created by refining a previous forest
800: (see `DMForestGetAdaptivityForest()`), this limits the amount of refinement.
802: Logically Collective
804: Input Parameters:
805: + dm - the forest
806: - maxRefinement - default `PETSC_DEFAULT` (interpreted by the subtype of `DMFOREST`)
808: Level: intermediate
810: .seealso: `DM`, `DMFOREST`, `DMForestGetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestSetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityDM()`
811: @*/
812: PetscErrorCode DMForestSetMaximumRefinement(DM dm, PetscInt maxRefinement)
813: {
814: DM_Forest *forest = (DM_Forest *)dm->data;
816: PetscFunctionBegin;
818: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the maximum refinement after setup");
819: forest->maxRefinement = maxRefinement;
820: PetscFunctionReturn(PETSC_SUCCESS);
821: }
823: /*@
824: DMForestGetMaximumRefinement - Get the maximum level of refinement (relative to the base `DM`, see
825: `DMForestGetBaseDM()`) allowed in the forest. If the forest is being created by refining a previous forest (see
826: `DMForestGetAdaptivityForest()`), this limits the amount of refinement.
828: Not Collective
830: Input Parameter:
831: . dm - the forest
833: Output Parameter:
834: . maxRefinement - default `PETSC_DEFAULT` (interpreted by the subtype of `DMFOREST`)
836: Level: intermediate
838: .seealso: `DM`, `DMFOREST`, `DMForestSetMaximumRefinement()`, `DMForestGetMinimumRefinement()`, `DMForestGetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityForest()`
839: @*/
840: PetscErrorCode DMForestGetMaximumRefinement(DM dm, PetscInt *maxRefinement)
841: {
842: DM_Forest *forest = (DM_Forest *)dm->data;
844: PetscFunctionBegin;
847: *maxRefinement = forest->maxRefinement;
848: PetscFunctionReturn(PETSC_SUCCESS);
849: }
851: /*@C
852: DMForestSetAdaptivityStrategy - During the pre-setup phase, set the strategy for combining adaptivity labels from multiple processes.
854: Logically Collective
856: Input Parameters:
857: + dm - the forest
858: - adaptStrategy - default `DMFORESTADAPTALL`
860: Level: advanced
862: Notes:
863: Subtypes of `DMFOREST` may define their own strategies. Two default strategies are `DMFORESTADAPTALL`, which indicates that all processes must agree
864: for a refinement/coarsening flag to be valid, and `DMFORESTADAPTANY`, which indicates that only one process needs to
865: specify refinement/coarsening.
867: .seealso: `DM`, `DMFOREST`, `DMForestGetAdaptivityStrategy()`, `DMFORESTADAPTALL`, `DMFORESTADAPTANY`
868: @*/
869: PetscErrorCode DMForestSetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy adaptStrategy)
870: {
871: DM_Forest *forest = (DM_Forest *)dm->data;
873: PetscFunctionBegin;
875: PetscCall(PetscFree(forest->adaptStrategy));
876: PetscCall(PetscStrallocpy((const char *)adaptStrategy, (char **)&forest->adaptStrategy));
877: PetscFunctionReturn(PETSC_SUCCESS);
878: }
880: /*@C
881: DMForestSetAdaptivityStrategy - Get the strategy for combining adaptivity labels from multiple processes.
883: Not Collective
885: Input Parameter:
886: . dm - the forest
888: Output Parameter:
889: . adaptStrategy - the adaptivity strategy (default `DMFORESTADAPTALL`)
891: Level: advanced
893: Note:
894: Subtypes
895: of `DMFOREST` may define their own strategies. Two default strategies are `DMFORESTADAPTALL`, which indicates that all
896: processes must agree for a refinement/coarsening flag to be valid, and `DMFORESTADAPTANY`, which indicates that only
897: one process needs to specify refinement/coarsening.
899: .seealso: `DM`, `DMFOREST`, `DMFORESTADAPTALL`, `DMFORESTADAPTANY`, `DMForestSetAdaptivityStrategy()`
900: @*/
901: PetscErrorCode DMForestGetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy *adaptStrategy)
902: {
903: DM_Forest *forest = (DM_Forest *)dm->data;
905: PetscFunctionBegin;
908: *adaptStrategy = forest->adaptStrategy;
909: PetscFunctionReturn(PETSC_SUCCESS);
910: }
912: /*@
913: DMForestGetAdaptivitySuccess - Return whether the requested adaptation (refinement, coarsening, repartitioning,
914: etc.) was successful.
916: Collective
918: Input Parameter:
919: . dm - the post-adaptation forest
921: Output Parameter:
922: . success - `PETSC_TRUE` if the post-adaptation forest is different from the pre-adaptation forest.
924: Level: intermediate
926: Notes:
927: `PETSC_FALSE` indicates that the post-adaptation forest is the same as the pre-adpatation
928: forest. A requested adaptation may have been unsuccessful if, for example, the requested refinement would have
929: exceeded the maximum refinement level.
931: .seealso: `DM`, `DMFOREST`
932: @*/
933: PetscErrorCode DMForestGetAdaptivitySuccess(DM dm, PetscBool *success)
934: {
935: DM_Forest *forest;
937: PetscFunctionBegin;
939: PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMSetUp() has not been called yet.");
940: forest = (DM_Forest *)dm->data;
941: PetscCall((forest->getadaptivitysuccess)(dm, success));
942: PetscFunctionReturn(PETSC_SUCCESS);
943: }
945: /*@
946: DMForestSetComputeAdaptivitySF - During the pre-setup phase, set whether transfer `PetscSF`s should be computed
947: relating the cells of the pre-adaptation forest to the post-adaptiation forest.
949: Logically Collective
951: Input Parameters:
952: + dm - the post-adaptation forest
953: - computeSF - default `PETSC_TRUE`
955: Level: advanced
957: Note:
958: After `DMSetUp()` is called, the transfer `PetscSF`s can be accessed with `DMForestGetAdaptivitySF()`.
960: .seealso: `DM`, `DMFOREST`, `DMForestGetComputeAdaptivitySF()`, `DMForestGetAdaptivitySF()`
961: @*/
962: PetscErrorCode DMForestSetComputeAdaptivitySF(DM dm, PetscBool computeSF)
963: {
964: DM_Forest *forest;
966: PetscFunctionBegin;
968: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot compute adaptivity PetscSFs after setup is called");
969: forest = (DM_Forest *)dm->data;
970: forest->computeAdaptSF = computeSF;
971: PetscFunctionReturn(PETSC_SUCCESS);
972: }
974: PetscErrorCode DMForestTransferVec(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time)
975: {
976: DM_Forest *forest;
978: PetscFunctionBegin;
983: forest = (DM_Forest *)dmIn->data;
984: PetscCheck(forest->transfervec, PetscObjectComm((PetscObject)dmIn), PETSC_ERR_SUP, "DMForestTransferVec() not implemented");
985: PetscCall((forest->transfervec)(dmIn, vecIn, dmOut, vecOut, useBCs, time));
986: PetscFunctionReturn(PETSC_SUCCESS);
987: }
989: PetscErrorCode DMForestTransferVecFromBase(DM dm, Vec vecIn, Vec vecOut)
990: {
991: DM_Forest *forest;
993: PetscFunctionBegin;
997: forest = (DM_Forest *)dm->data;
998: PetscCheck(forest->transfervecfrombase, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DMForestTransferVecFromBase() not implemented");
999: PetscCall((forest->transfervecfrombase)(dm, vecIn, vecOut));
1000: PetscFunctionReturn(PETSC_SUCCESS);
1001: }
1003: /*@
1004: DMForestGetComputeAdaptivitySF - Get whether transfer `PetscSF`s should be computed relating the cells of the
1005: pre-adaptation forest to the post-adaptiation forest. After `DMSetUp()` is called, these transfer PetscSFs can be
1006: accessed with `DMForestGetAdaptivitySF()`.
1008: Not Collective
1010: Input Parameter:
1011: . dm - the post-adaptation forest
1013: Output Parameter:
1014: . computeSF - default `PETSC_TRUE`
1016: Level: advanced
1018: .seealso: `DM`, `DMFOREST`, `DMForestSetComputeAdaptivitySF()`, `DMForestGetAdaptivitySF()`
1019: @*/
1020: PetscErrorCode DMForestGetComputeAdaptivitySF(DM dm, PetscBool *computeSF)
1021: {
1022: DM_Forest *forest;
1024: PetscFunctionBegin;
1026: forest = (DM_Forest *)dm->data;
1027: *computeSF = forest->computeAdaptSF;
1028: PetscFunctionReturn(PETSC_SUCCESS);
1029: }
1031: /*@
1032: DMForestGetAdaptivitySF - Get `PetscSF`s that relate the pre-adaptation forest to the post-adaptation forest.
1033: Adaptation can be any combination of refinement, coarsening, repartition, and change of overlap, so there may be
1034: some cells of the pre-adaptation that are parents of post-adaptation cells, and vice versa. Therefore there are two
1035: `PetscSF`s: one that relates pre-adaptation coarse cells to post-adaptation fine cells, and one that relates
1036: pre-adaptation fine cells to post-adaptation coarse cells.
1038: Not Collective
1040: Input Parameter:
1041: . dm - the post-adaptation forest
1043: Output Parameters:
1044: + preCoarseToFine - pre-adaptation coarse cells to post-adaptation fine cells: BCast goes from pre- to post-
1045: - coarseToPreFine - post-adaptation coarse cells to pre-adaptation fine cells: BCast goes from post- to pre-
1047: Level: advanced
1049: .seealso: `DM`, `DMFOREST`, `DMForestGetComputeAdaptivitySF()`, `DMForestSetComputeAdaptivitySF()`
1050: @*/
1051: PetscErrorCode DMForestGetAdaptivitySF(DM dm, PetscSF *preCoarseToFine, PetscSF *coarseToPreFine)
1052: {
1053: DM_Forest *forest;
1055: PetscFunctionBegin;
1057: PetscCall(DMSetUp(dm));
1058: forest = (DM_Forest *)dm->data;
1059: if (preCoarseToFine) *preCoarseToFine = forest->preCoarseToFine;
1060: if (coarseToPreFine) *coarseToPreFine = forest->coarseToPreFine;
1061: PetscFunctionReturn(PETSC_SUCCESS);
1062: }
1064: /*@
1065: DMForestSetGradeFactor - During the pre-setup phase, set the desired amount of grading in the mesh, e.g. give 2 to
1066: indicate that the diameter of neighboring cells should differ by at most a factor of 2. Subtypes of `DMFOREST` may
1067: only support one particular choice of grading factor.
1069: Logically Collective
1071: Input Parameters:
1072: + dm - the forest
1073: - grade - the grading factor
1075: Level: advanced
1077: .seealso: `DM`, `DMFOREST`, `DMForestGetGradeFactor()`
1078: @*/
1079: PetscErrorCode DMForestSetGradeFactor(DM dm, PetscInt grade)
1080: {
1081: DM_Forest *forest = (DM_Forest *)dm->data;
1083: PetscFunctionBegin;
1085: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the grade factor after setup");
1086: forest->gradeFactor = grade;
1087: PetscFunctionReturn(PETSC_SUCCESS);
1088: }
1090: /*@
1091: DMForestGetGradeFactor - Get the desired amount of grading in the mesh, e.g. give 2 to indicate that the diameter of
1092: neighboring cells should differ by at most a factor of 2. Subtypes of `DMFOREST` may only support one particular
1093: choice of grading factor.
1095: Not Collective
1097: Input Parameter:
1098: . dm - the forest
1100: Output Parameter:
1101: . grade - the grading factor
1103: Level: advanced
1105: .seealso: `DM`, `DMFOREST`, `DMForestSetGradeFactor()`
1106: @*/
1107: PetscErrorCode DMForestGetGradeFactor(DM dm, PetscInt *grade)
1108: {
1109: DM_Forest *forest = (DM_Forest *)dm->data;
1111: PetscFunctionBegin;
1114: *grade = forest->gradeFactor;
1115: PetscFunctionReturn(PETSC_SUCCESS);
1116: }
1118: /*@
1119: DMForestSetCellWeightFactor - During the pre-setup phase, set the factor by which the level of refinement changes
1120: the cell weight (see `DMForestSetCellWeights()`) when calculating partitions. The final weight of a cell will be
1121: (cellWeight) * (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on
1122: its level; a factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the
1123: computation associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1125: Logically Collective
1127: Input Parameters:
1128: + dm - the forest
1129: - weightsFactors - default 1.
1131: Level: advanced
1133: .seealso: `DM`, `DMFOREST`, `DMForestGetCellWeightFactor()`, `DMForestSetCellWeights()`
1134: @*/
1135: PetscErrorCode DMForestSetCellWeightFactor(DM dm, PetscReal weightsFactor)
1136: {
1137: DM_Forest *forest = (DM_Forest *)dm->data;
1139: PetscFunctionBegin;
1141: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the weights factor after setup");
1142: forest->weightsFactor = weightsFactor;
1143: PetscFunctionReturn(PETSC_SUCCESS);
1144: }
1146: /*@
1147: DMForestGetCellWeightFactor - Get the factor by which the level of refinement changes the cell weight (see
1148: `DMForestSetCellWeights()`) when calculating partitions. The final weight of a cell will be (cellWeight) *
1149: (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on its level; a
1150: factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the computation
1151: associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1153: Not Collective
1155: Input Parameter:
1156: . dm - the forest
1158: Output Parameter:
1159: . weightsFactors - default 1.
1161: Level: advanced
1163: .seealso: `DM`, `DMFOREST`, `DMForestSetCellWeightFactor()`, `DMForestSetCellWeights()`
1164: @*/
1165: PetscErrorCode DMForestGetCellWeightFactor(DM dm, PetscReal *weightsFactor)
1166: {
1167: DM_Forest *forest = (DM_Forest *)dm->data;
1169: PetscFunctionBegin;
1172: *weightsFactor = forest->weightsFactor;
1173: PetscFunctionReturn(PETSC_SUCCESS);
1174: }
1176: /*@
1177: DMForestGetCellChart - After the setup phase, get the local half-open interval of the chart of cells on this process
1179: Not Collective
1181: Input Parameter:
1182: . dm - the forest
1184: Output Parameters:
1185: + cStart - the first cell on this process
1186: - cEnd - one after the final cell on this process
1188: Level: intermediate
1190: .seealso: `DM`, `DMFOREST`, `DMForestGetCellSF()`
1191: @*/
1192: PetscErrorCode DMForestGetCellChart(DM dm, PetscInt *cStart, PetscInt *cEnd)
1193: {
1194: DM_Forest *forest = (DM_Forest *)dm->data;
1196: PetscFunctionBegin;
1200: if (((forest->cStart == PETSC_DETERMINE) || (forest->cEnd == PETSC_DETERMINE)) && forest->createcellchart) PetscCall(forest->createcellchart(dm, &forest->cStart, &forest->cEnd));
1201: *cStart = forest->cStart;
1202: *cEnd = forest->cEnd;
1203: PetscFunctionReturn(PETSC_SUCCESS);
1204: }
1206: /*@
1207: DMForestGetCellSF - After the setup phase, get the `PetscSF` for overlapping cells between processes
1209: Not Collective
1211: Input Parameter:
1212: . dm - the forest
1214: Output Parameter:
1215: . cellSF - the `PetscSF`
1217: Level: intermediate
1219: .seealso: `DM`, `DMFOREST`, `DMForestGetCellChart()`
1220: @*/
1221: PetscErrorCode DMForestGetCellSF(DM dm, PetscSF *cellSF)
1222: {
1223: DM_Forest *forest = (DM_Forest *)dm->data;
1225: PetscFunctionBegin;
1228: if ((!forest->cellSF) && forest->createcellsf) PetscCall(forest->createcellsf(dm, &forest->cellSF));
1229: *cellSF = forest->cellSF;
1230: PetscFunctionReturn(PETSC_SUCCESS);
1231: }
1233: /*@C
1234: DMForestSetAdaptivityLabel - During the pre-setup phase, set the label of the pre-adaptation forest (see
1235: `DMForestGetAdaptivityForest()`) that holds the adaptation flags (refinement, coarsening, or some combination). The
1236: interpretation of the label values is up to the subtype of `DMFOREST`, but `DM_ADAPT_DETERMINE`, `DM_ADAPT_KEEP`,
1237: `DM_ADAPT_REFINE`, and `DM_ADAPT_COARSEN` have been reserved as choices that should be accepted by all subtypes.
1239: Logically Collective
1241: Input Parameters:
1242: - dm - the forest
1243: + adaptLabel - the label in the pre-adaptation forest
1245: Level: intermediate
1247: .seealso: `DM`, `DMFOREST`, `DMForestGetAdaptivityLabel()`
1248: @*/
1249: PetscErrorCode DMForestSetAdaptivityLabel(DM dm, DMLabel adaptLabel)
1250: {
1251: DM_Forest *forest = (DM_Forest *)dm->data;
1253: PetscFunctionBegin;
1256: PetscCall(PetscObjectReference((PetscObject)adaptLabel));
1257: PetscCall(DMLabelDestroy(&forest->adaptLabel));
1258: forest->adaptLabel = adaptLabel;
1259: PetscFunctionReturn(PETSC_SUCCESS);
1260: }
1262: /*@C
1263: DMForestGetAdaptivityLabel - Get the label of the pre-adaptation forest (see `DMForestGetAdaptivityForest()`) that
1264: holds the adaptation flags (refinement, coarsening, or some combination). The interpretation of the label values is
1265: up to the subtype of `DMFOREST`, but `DM_ADAPT_DETERMINE`, `DM_ADAPT_KEEP`, `DM_ADAPT_REFINE`, and `DM_ADAPT_COARSEN` have
1266: been reserved as choices that should be accepted by all subtypes.
1268: Not Collective
1270: Input Parameter:
1271: . dm - the forest
1273: Output Parameter:
1274: . adaptLabel - the name of the label in the pre-adaptation forest
1276: Level: intermediate
1278: .seealso: `DM`, `DMFOREST`, `DMForestSetAdaptivityLabel()`
1279: @*/
1280: PetscErrorCode DMForestGetAdaptivityLabel(DM dm, DMLabel *adaptLabel)
1281: {
1282: DM_Forest *forest = (DM_Forest *)dm->data;
1284: PetscFunctionBegin;
1286: *adaptLabel = forest->adaptLabel;
1287: PetscFunctionReturn(PETSC_SUCCESS);
1288: }
1290: /*@
1291: DMForestSetCellWeights - Set the weights assigned to each of the cells (see `DMForestGetCellChart()`) of the current
1292: process: weights are used to determine parallel partitioning.
1294: Logically Collective
1296: Input Parameters:
1297: + dm - the forest
1298: . weights - the array of weights (see `DMForestSetWeightCapacity()`) for all cells, or `NULL` to indicate each cell has weight 1.
1299: - copyMode - how weights should reference weights
1301: Level: advanced
1303: .seealso: `DM`, `DMFOREST`, `DMForestGetCellWeights()`, `DMForestSetWeightCapacity()`
1304: @*/
1305: PetscErrorCode DMForestSetCellWeights(DM dm, PetscReal weights[], PetscCopyMode copyMode)
1306: {
1307: DM_Forest *forest = (DM_Forest *)dm->data;
1308: PetscInt cStart, cEnd;
1310: PetscFunctionBegin;
1312: PetscCall(DMForestGetCellChart(dm, &cStart, &cEnd));
1313: PetscCheck(cEnd >= cStart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "cell chart [%" PetscInt_FMT ",%" PetscInt_FMT ") is not valid", cStart, cEnd);
1314: if (copyMode == PETSC_COPY_VALUES) {
1315: if (forest->cellWeightsCopyMode != PETSC_OWN_POINTER || forest->cellWeights == weights) PetscCall(PetscMalloc1(cEnd - cStart, &forest->cellWeights));
1316: PetscCall(PetscArraycpy(forest->cellWeights, weights, cEnd - cStart));
1317: forest->cellWeightsCopyMode = PETSC_OWN_POINTER;
1318: PetscFunctionReturn(PETSC_SUCCESS);
1319: }
1320: if (forest->cellWeightsCopyMode == PETSC_OWN_POINTER) PetscCall(PetscFree(forest->cellWeights));
1321: forest->cellWeights = weights;
1322: forest->cellWeightsCopyMode = copyMode;
1323: PetscFunctionReturn(PETSC_SUCCESS);
1324: }
1326: /*@
1327: DMForestGetCellWeights - Get the weights assigned to each of the cells (see `DMForestGetCellChart()`) of the current
1328: process: weights are used to determine parallel partitioning.
1330: Not Collective
1332: Input Parameter:
1333: . dm - the forest
1335: Output Parameter:
1336: . weights - the array of weights for all cells, or `NULL` to indicate each cell has weight 1.
1338: Level: advanced
1340: .seealso: `DM`, `DMFOREST`, `DMForestSetCellWeights()`, `DMForestSetWeightCapacity()`
1341: @*/
1342: PetscErrorCode DMForestGetCellWeights(DM dm, PetscReal **weights)
1343: {
1344: DM_Forest *forest = (DM_Forest *)dm->data;
1346: PetscFunctionBegin;
1349: *weights = forest->cellWeights;
1350: PetscFunctionReturn(PETSC_SUCCESS);
1351: }
1353: /*@
1354: DMForestSetWeightCapacity - During the pre-setup phase, set the capacity of the current process when repartitioning
1355: a pre-adaptation forest (see `DMForestGetAdaptivityForest()`). After partitioning, the ratio of the weight of each
1356: process's cells to the process's capacity will be roughly equal for all processes. A capacity of 0 indicates that
1357: the current process should not have any cells after repartitioning.
1359: Logically Collective
1361: Input parameters:
1362: + dm - the forest
1363: - capacity - this process's capacity
1365: Level: advanced
1367: .seealso `DM`, `DMFOREST`, `DMForestGetWeightCapacity()`, `DMForestSetCellWeights()`, `DMForestSetCellWeightFactor()`
1368: @*/
1369: PetscErrorCode DMForestSetWeightCapacity(DM dm, PetscReal capacity)
1370: {
1371: DM_Forest *forest = (DM_Forest *)dm->data;
1373: PetscFunctionBegin;
1375: PetscCheck(!dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot change the weight capacity after setup");
1376: PetscCheck(capacity >= 0., PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have negative weight capacity; %g", (double)capacity);
1377: forest->weightCapacity = capacity;
1378: PetscFunctionReturn(PETSC_SUCCESS);
1379: }
1381: /*@
1382: DMForestGetWeightCapacity - Set the capacity of the current process when repartitioning a pre-adaptation forest (see
1383: `DMForestGetAdaptivityForest()`). After partitioning, the ratio of the weight of each process's cells to the
1384: process's capacity will be roughly equal for all processes. A capacity of 0 indicates that the current process
1385: should not have any cells after repartitioning.
1387: Not Collective
1389: Input parameter:
1390: . dm - the forest
1392: Output parameter:
1393: . capacity - this process's capacity
1395: Level: advanced
1397: .seealso `DM`, `DMFOREST`, `DMForestSetWeightCapacity()`, `DMForestSetCellWeights()`, `DMForestSetCellWeightFactor()`
1398: @*/
1399: PetscErrorCode DMForestGetWeightCapacity(DM dm, PetscReal *capacity)
1400: {
1401: DM_Forest *forest = (DM_Forest *)dm->data;
1403: PetscFunctionBegin;
1406: *capacity = forest->weightCapacity;
1407: PetscFunctionReturn(PETSC_SUCCESS);
1408: }
1410: PETSC_EXTERN PetscErrorCode DMSetFromOptions_Forest(DM dm, PetscOptionItems *PetscOptionsObject)
1411: {
1412: PetscBool flg, flg1, flg2, flg3, flg4;
1413: DMForestTopology oldTopo;
1414: char stringBuffer[256];
1415: PetscViewer viewer;
1416: PetscViewerFormat format;
1417: PetscInt adjDim, adjCodim, overlap, minRefinement, initRefinement, maxRefinement, grade;
1418: PetscReal weightsFactor;
1419: DMForestAdaptivityStrategy adaptStrategy;
1421: PetscFunctionBegin;
1422: PetscCall(DMForestGetTopology(dm, &oldTopo));
1423: PetscOptionsHeadBegin(PetscOptionsObject, "DMForest Options");
1424: PetscCall(PetscOptionsString("-dm_forest_topology", "the topology of the forest's base mesh", "DMForestSetTopology", oldTopo, stringBuffer, sizeof(stringBuffer), &flg1));
1425: PetscCall(PetscOptionsViewer("-dm_forest_base_dm", "load the base DM from a viewer specification", "DMForestSetBaseDM", &viewer, &format, &flg2));
1426: PetscCall(PetscOptionsViewer("-dm_forest_coarse_forest", "load the coarse forest from a viewer specification", "DMForestSetCoarseForest", &viewer, &format, &flg3));
1427: PetscCall(PetscOptionsViewer("-dm_forest_fine_forest", "load the fine forest from a viewer specification", "DMForestSetFineForest", &viewer, &format, &flg4));
1428: PetscCheck((PetscInt)flg1 + (PetscInt)flg2 + (PetscInt)flg3 + (PetscInt)flg4 <= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Specify only one of -dm_forest_{topology,base_dm,coarse_forest,fine_forest}");
1429: if (flg1) {
1430: PetscCall(DMForestSetTopology(dm, (DMForestTopology)stringBuffer));
1431: PetscCall(DMForestSetBaseDM(dm, NULL));
1432: PetscCall(DMForestSetAdaptivityForest(dm, NULL));
1433: }
1434: if (flg2) {
1435: DM base;
1437: PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &base));
1438: PetscCall(PetscViewerPushFormat(viewer, format));
1439: PetscCall(DMLoad(base, viewer));
1440: PetscCall(PetscViewerDestroy(&viewer));
1441: PetscCall(DMForestSetBaseDM(dm, base));
1442: PetscCall(DMDestroy(&base));
1443: PetscCall(DMForestSetTopology(dm, NULL));
1444: PetscCall(DMForestSetAdaptivityForest(dm, NULL));
1445: }
1446: if (flg3) {
1447: DM coarse;
1449: PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &coarse));
1450: PetscCall(PetscViewerPushFormat(viewer, format));
1451: PetscCall(DMLoad(coarse, viewer));
1452: PetscCall(PetscViewerDestroy(&viewer));
1453: PetscCall(DMForestSetAdaptivityForest(dm, coarse));
1454: PetscCall(DMDestroy(&coarse));
1455: PetscCall(DMForestSetTopology(dm, NULL));
1456: PetscCall(DMForestSetBaseDM(dm, NULL));
1457: }
1458: if (flg4) {
1459: DM fine;
1461: PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &fine));
1462: PetscCall(PetscViewerPushFormat(viewer, format));
1463: PetscCall(DMLoad(fine, viewer));
1464: PetscCall(PetscViewerDestroy(&viewer));
1465: PetscCall(DMForestSetAdaptivityForest(dm, fine));
1466: PetscCall(DMDestroy(&fine));
1467: PetscCall(DMForestSetTopology(dm, NULL));
1468: PetscCall(DMForestSetBaseDM(dm, NULL));
1469: }
1470: PetscCall(DMForestGetAdjacencyDimension(dm, &adjDim));
1471: PetscCall(PetscOptionsBoundedInt("-dm_forest_adjacency_dimension", "set the dimension of points that define adjacency in the forest", "DMForestSetAdjacencyDimension", adjDim, &adjDim, &flg, 0));
1472: if (flg) {
1473: PetscCall(DMForestSetAdjacencyDimension(dm, adjDim));
1474: } else {
1475: PetscCall(DMForestGetAdjacencyCodimension(dm, &adjCodim));
1476: PetscCall(PetscOptionsBoundedInt("-dm_forest_adjacency_codimension", "set the codimension of points that define adjacency in the forest", "DMForestSetAdjacencyCodimension", adjCodim, &adjCodim, &flg, 1));
1477: if (flg) PetscCall(DMForestSetAdjacencyCodimension(dm, adjCodim));
1478: }
1479: PetscCall(DMForestGetPartitionOverlap(dm, &overlap));
1480: PetscCall(PetscOptionsBoundedInt("-dm_forest_partition_overlap", "set the degree of partition overlap", "DMForestSetPartitionOverlap", overlap, &overlap, &flg, 0));
1481: if (flg) PetscCall(DMForestSetPartitionOverlap(dm, overlap));
1482: #if 0
1483: PetscCall(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));
1484: if (flg) {
1485: PetscCall(DMForestSetMinimumRefinement(dm,minRefinement));
1486: PetscCall(DMForestSetInitialRefinement(dm,minRefinement));
1487: }
1488: PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy","equivalent to -dm_forest_set_minimum_refinement 0 and -dm_forest_set_initial_refinement",NULL,initRefinement,&initRefinement,&flg,0));
1489: if (flg) {
1490: PetscCall(DMForestSetMinimumRefinement(dm,0));
1491: PetscCall(DMForestSetInitialRefinement(dm,initRefinement));
1492: }
1493: #endif
1494: PetscCall(DMForestGetMinimumRefinement(dm, &minRefinement));
1495: PetscCall(PetscOptionsBoundedInt("-dm_forest_minimum_refinement", "set the minimum level of refinement in the forest", "DMForestSetMinimumRefinement", minRefinement, &minRefinement, &flg, 0));
1496: if (flg) PetscCall(DMForestSetMinimumRefinement(dm, minRefinement));
1497: PetscCall(DMForestGetInitialRefinement(dm, &initRefinement));
1498: PetscCall(PetscOptionsBoundedInt("-dm_forest_initial_refinement", "set the initial level of refinement in the forest", "DMForestSetInitialRefinement", initRefinement, &initRefinement, &flg, 0));
1499: if (flg) PetscCall(DMForestSetInitialRefinement(dm, initRefinement));
1500: PetscCall(DMForestGetMaximumRefinement(dm, &maxRefinement));
1501: PetscCall(PetscOptionsBoundedInt("-dm_forest_maximum_refinement", "set the maximum level of refinement in the forest", "DMForestSetMaximumRefinement", maxRefinement, &maxRefinement, &flg, 0));
1502: if (flg) PetscCall(DMForestSetMaximumRefinement(dm, maxRefinement));
1503: PetscCall(DMForestGetAdaptivityStrategy(dm, &adaptStrategy));
1504: PetscCall(PetscOptionsString("-dm_forest_adaptivity_strategy", "the forest's adaptivity-flag resolution strategy", "DMForestSetAdaptivityStrategy", adaptStrategy, stringBuffer, sizeof(stringBuffer), &flg));
1505: if (flg) PetscCall(DMForestSetAdaptivityStrategy(dm, (DMForestAdaptivityStrategy)stringBuffer));
1506: PetscCall(DMForestGetGradeFactor(dm, &grade));
1507: PetscCall(PetscOptionsBoundedInt("-dm_forest_grade_factor", "grade factor between neighboring cells", "DMForestSetGradeFactor", grade, &grade, &flg, 0));
1508: if (flg) PetscCall(DMForestSetGradeFactor(dm, grade));
1509: PetscCall(DMForestGetCellWeightFactor(dm, &weightsFactor));
1510: PetscCall(PetscOptionsReal("-dm_forest_cell_weight_factor", "multiplying weight factor for cell refinement", "DMForestSetCellWeightFactor", weightsFactor, &weightsFactor, &flg));
1511: if (flg) PetscCall(DMForestSetCellWeightFactor(dm, weightsFactor));
1512: PetscOptionsHeadEnd();
1513: PetscFunctionReturn(PETSC_SUCCESS);
1514: }
1516: PetscErrorCode DMCreateSubDM_Forest(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1517: {
1518: PetscFunctionBegin;
1519: if (subdm) PetscCall(DMClone(dm, subdm));
1520: PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
1521: PetscFunctionReturn(PETSC_SUCCESS);
1522: }
1524: PetscErrorCode DMRefine_Forest(DM dm, MPI_Comm comm, DM *dmRefined)
1525: {
1526: DMLabel refine;
1527: DM fineDM;
1529: PetscFunctionBegin;
1530: PetscCall(DMGetFineDM(dm, &fineDM));
1531: if (fineDM) {
1532: PetscCall(PetscObjectReference((PetscObject)fineDM));
1533: *dmRefined = fineDM;
1534: PetscFunctionReturn(PETSC_SUCCESS);
1535: }
1536: PetscCall(DMForestTemplate(dm, comm, dmRefined));
1537: PetscCall(DMGetLabel(dm, "refine", &refine));
1538: if (!refine) {
1539: PetscCall(DMLabelCreate(PETSC_COMM_SELF, "refine", &refine));
1540: PetscCall(DMLabelSetDefaultValue(refine, DM_ADAPT_REFINE));
1541: } else PetscCall(PetscObjectReference((PetscObject)refine));
1542: PetscCall(DMForestSetAdaptivityLabel(*dmRefined, refine));
1543: PetscCall(DMLabelDestroy(&refine));
1544: PetscFunctionReturn(PETSC_SUCCESS);
1545: }
1547: PetscErrorCode DMCoarsen_Forest(DM dm, MPI_Comm comm, DM *dmCoarsened)
1548: {
1549: DMLabel coarsen;
1550: DM coarseDM;
1552: PetscFunctionBegin;
1553: {
1554: PetscMPIInt mpiComparison;
1555: MPI_Comm dmcomm = PetscObjectComm((PetscObject)dm);
1557: PetscCallMPI(MPI_Comm_compare(comm, dmcomm, &mpiComparison));
1558: PetscCheck(mpiComparison == MPI_IDENT || mpiComparison == MPI_CONGRUENT, dmcomm, PETSC_ERR_SUP, "No support for different communicators yet");
1559: }
1560: PetscCall(DMGetCoarseDM(dm, &coarseDM));
1561: if (coarseDM) {
1562: PetscCall(PetscObjectReference((PetscObject)coarseDM));
1563: *dmCoarsened = coarseDM;
1564: PetscFunctionReturn(PETSC_SUCCESS);
1565: }
1566: PetscCall(DMForestTemplate(dm, comm, dmCoarsened));
1567: PetscCall(DMForestSetAdaptivityPurpose(*dmCoarsened, DM_ADAPT_COARSEN));
1568: PetscCall(DMGetLabel(dm, "coarsen", &coarsen));
1569: if (!coarsen) {
1570: PetscCall(DMLabelCreate(PETSC_COMM_SELF, "coarsen", &coarsen));
1571: PetscCall(DMLabelSetDefaultValue(coarsen, DM_ADAPT_COARSEN));
1572: } else PetscCall(PetscObjectReference((PetscObject)coarsen));
1573: PetscCall(DMForestSetAdaptivityLabel(*dmCoarsened, coarsen));
1574: PetscCall(DMLabelDestroy(&coarsen));
1575: PetscFunctionReturn(PETSC_SUCCESS);
1576: }
1578: PetscErrorCode DMAdaptLabel_Forest(DM dm, PETSC_UNUSED Vec metric, DMLabel label, PETSC_UNUSED DMLabel rgLabel, DM *adaptedDM)
1579: {
1580: PetscBool success;
1582: PetscFunctionBegin;
1583: PetscCall(DMForestTemplate(dm, PetscObjectComm((PetscObject)dm), adaptedDM));
1584: PetscCall(DMForestSetAdaptivityLabel(*adaptedDM, label));
1585: PetscCall(DMSetUp(*adaptedDM));
1586: PetscCall(DMForestGetAdaptivitySuccess(*adaptedDM, &success));
1587: if (!success) {
1588: PetscCall(DMDestroy(adaptedDM));
1589: *adaptedDM = NULL;
1590: }
1591: PetscFunctionReturn(PETSC_SUCCESS);
1592: }
1594: static PetscErrorCode DMInitialize_Forest(DM dm)
1595: {
1596: PetscFunctionBegin;
1597: PetscCall(PetscMemzero(dm->ops, sizeof(*(dm->ops))));
1599: dm->ops->clone = DMClone_Forest;
1600: dm->ops->setfromoptions = DMSetFromOptions_Forest;
1601: dm->ops->destroy = DMDestroy_Forest;
1602: dm->ops->createsubdm = DMCreateSubDM_Forest;
1603: dm->ops->refine = DMRefine_Forest;
1604: dm->ops->coarsen = DMCoarsen_Forest;
1605: PetscFunctionReturn(PETSC_SUCCESS);
1606: }
1608: /*MC
1610: DMFOREST = "forest" - A DM object that encapsulates a hierarchically refined mesh. Forests usually have a base `DM`
1611: (see `DMForestGetBaseDM()`), from which it is refined. The refinement and partitioning of forests is considered
1612: immutable after `DMSetUp()` is called. To adapt a mesh, one should call `DMForestTemplate()` to create a new mesh that
1613: will default to being identical to it, specify how that mesh should differ, and then calling `DMSetUp()` on the new
1614: mesh.
1616: To specify that a mesh should be refined or coarsened from the previous mesh, a label should be defined on the
1617: previous mesh whose values indicate which cells should be refined (`DM_ADAPT_REFINE`) or coarsened (`DM_ADAPT_COARSEN`)
1618: and how (subtypes are free to allow additional values for things like anisotropic refinement). The label should be
1619: given to the *new* mesh with `DMForestSetAdaptivityLabel()`.
1621: Level: advanced
1623: .seealso: `DMType`, `DM`, `DMCreate()`, `DMSetType()`, `DMForestGetBaseDM()`, `DMForestSetBaseDM()`, `DMForestTemplate()`, `DMForestSetAdaptivityLabel()`
1624: M*/
1626: PETSC_EXTERN PetscErrorCode DMCreate_Forest(DM dm)
1627: {
1628: DM_Forest *forest;
1630: PetscFunctionBegin;
1632: PetscCall(PetscNew(&forest));
1633: dm->dim = 0;
1634: dm->data = forest;
1635: forest->refct = 1;
1636: forest->data = NULL;
1637: forest->topology = NULL;
1638: forest->adapt = NULL;
1639: forest->base = NULL;
1640: forest->adaptPurpose = DM_ADAPT_DETERMINE;
1641: forest->adjDim = PETSC_DEFAULT;
1642: forest->overlap = PETSC_DEFAULT;
1643: forest->minRefinement = PETSC_DEFAULT;
1644: forest->maxRefinement = PETSC_DEFAULT;
1645: forest->initRefinement = PETSC_DEFAULT;
1646: forest->cStart = PETSC_DETERMINE;
1647: forest->cEnd = PETSC_DETERMINE;
1648: forest->cellSF = NULL;
1649: forest->adaptLabel = NULL;
1650: forest->gradeFactor = 2;
1651: forest->cellWeights = NULL;
1652: forest->cellWeightsCopyMode = PETSC_USE_POINTER;
1653: forest->weightsFactor = 1.;
1654: forest->weightCapacity = 1.;
1655: PetscCall(DMForestSetAdaptivityStrategy(dm, DMFORESTADAPTALL));
1656: PetscCall(DMInitialize_Forest(dm));
1657: PetscFunctionReturn(PETSC_SUCCESS);
1658: }