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: while (link) {
22: oldLink = link;
23: PetscFree(oldLink->name);
24: link = oldLink->next;
25: PetscFree(oldLink);
26: }
27: return 0;
28: }
30: static PetscErrorCode DMForestPackageInitialize(void)
31: {
32: if (DMForestPackageInitialized) return 0;
33: DMForestPackageInitialized = PETSC_TRUE;
35: DMForestRegisterType(DMFOREST);
36: PetscRegisterFinalize(DMForestPackageFinalize);
37: return 0;
38: }
40: /*@C
41: DMForestRegisterType - Registers a `DMType` as a subtype of `DMFOREST` (so that `DMIsForest()` will be correct)
43: Not Collective
45: Input parameter:
46: . name - the name of the type
48: Level: advanced
50: .seealso: `DMFOREST`, `DMIsForest()`
51: @*/
52: PetscErrorCode DMForestRegisterType(DMType name)
53: {
54: DMForestTypeLink link;
56: DMForestPackageInitialize();
57: PetscNew(&link);
58: PetscStrallocpy(name, &link->name);
59: link->next = DMForestTypeList;
60: DMForestTypeList = link;
61: return 0;
62: }
64: /*@
65: DMIsForest - Check whether a DM uses the DMFOREST interface for hierarchically-refined meshes
67: Not Collective
69: Input parameter:
70: . dm - the DM object
72: Output parameter:
73: . isForest - whether dm is a subtype of DMFOREST
75: Level: intermediate
77: .seealso: `DMFOREST`, `DMForestRegisterType()`
78: @*/
79: PetscErrorCode DMIsForest(DM dm, PetscBool *isForest)
80: {
81: DMForestTypeLink link = DMForestTypeList;
83: while (link) {
84: PetscBool sameType;
85: PetscObjectTypeCompare((PetscObject)dm, link->name, &sameType);
86: if (sameType) {
87: *isForest = PETSC_TRUE;
88: return 0;
89: }
90: link = link->next;
91: }
92: *isForest = PETSC_FALSE;
93: return 0;
94: }
96: /*@
97: DMForestTemplate - Create a new DM that will be adapted from a source DM. The new DM reproduces the configuration
98: of the source, but is not yet setup, so that the user can then define only the ways that the new DM should differ
99: (by, e.g., refinement or repartitioning). The source DM is also set as the adaptivity source DM of the new DM (see
100: DMForestSetAdaptivityForest()).
102: Collective on dm
104: Input Parameters:
105: + dm - the source DM object
106: - comm - the communicator for the new DM (this communicator is currently ignored, but is present so that DMForestTemplate() can be used within DMCoarsen())
108: Output Parameter:
109: . tdm - the new DM object
111: Level: intermediate
113: .seealso: `DMForestSetAdaptivityForest()`
114: @*/
115: PetscErrorCode DMForestTemplate(DM dm, MPI_Comm comm, DM *tdm)
116: {
117: DM_Forest *forest = (DM_Forest *)dm->data;
118: DMType type;
119: DM base;
120: DMForestTopology topology;
121: MatType mtype;
122: PetscInt dim, overlap, ref, factor;
123: DMForestAdaptivityStrategy strat;
124: void *ctx;
125: PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *);
126: void *mapCtx;
129: DMCreate(PetscObjectComm((PetscObject)dm), tdm);
130: DMGetType(dm, &type);
131: DMSetType(*tdm, type);
132: DMForestGetBaseDM(dm, &base);
133: DMForestSetBaseDM(*tdm, base);
134: DMForestGetTopology(dm, &topology);
135: DMForestSetTopology(*tdm, topology);
136: DMForestGetAdjacencyDimension(dm, &dim);
137: DMForestSetAdjacencyDimension(*tdm, dim);
138: DMForestGetPartitionOverlap(dm, &overlap);
139: DMForestSetPartitionOverlap(*tdm, overlap);
140: DMForestGetMinimumRefinement(dm, &ref);
141: DMForestSetMinimumRefinement(*tdm, ref);
142: DMForestGetMaximumRefinement(dm, &ref);
143: DMForestSetMaximumRefinement(*tdm, ref);
144: DMForestGetAdaptivityStrategy(dm, &strat);
145: DMForestSetAdaptivityStrategy(*tdm, strat);
146: DMForestGetGradeFactor(dm, &factor);
147: DMForestSetGradeFactor(*tdm, factor);
148: DMForestGetBaseCoordinateMapping(dm, &map, &mapCtx);
149: DMForestSetBaseCoordinateMapping(*tdm, map, mapCtx);
150: if (forest->ftemplate) (*forest->ftemplate)(dm, *tdm);
151: DMForestSetAdaptivityForest(*tdm, dm);
152: DMCopyDisc(dm, *tdm);
153: DMGetApplicationContext(dm, &ctx);
154: DMSetApplicationContext(*tdm, &ctx);
155: {
156: const PetscReal *maxCell, *L, *Lstart;
158: DMGetPeriodicity(dm, &maxCell, &Lstart, &L);
159: DMSetPeriodicity(*tdm, maxCell, Lstart, L);
160: }
161: DMGetMatType(dm, &mtype);
162: DMSetMatType(*tdm, mtype);
163: return 0;
164: }
166: static PetscErrorCode DMInitialize_Forest(DM dm);
168: PETSC_EXTERN PetscErrorCode DMClone_Forest(DM dm, DM *newdm)
169: {
170: DM_Forest *forest = (DM_Forest *)dm->data;
171: const char *type;
173: forest->refct++;
174: (*newdm)->data = forest;
175: PetscObjectGetType((PetscObject)dm, &type);
176: PetscObjectChangeTypeName((PetscObject)*newdm, type);
177: DMInitialize_Forest(*newdm);
178: return 0;
179: }
181: static PetscErrorCode DMDestroy_Forest(DM dm)
182: {
183: DM_Forest *forest = (DM_Forest *)dm->data;
185: if (--forest->refct > 0) return 0;
186: if (forest->destroy) (*forest->destroy)(dm);
187: PetscSFDestroy(&forest->cellSF);
188: PetscSFDestroy(&forest->preCoarseToFine);
189: PetscSFDestroy(&forest->coarseToPreFine);
190: DMLabelDestroy(&forest->adaptLabel);
191: PetscFree(forest->adaptStrategy);
192: DMDestroy(&forest->base);
193: DMDestroy(&forest->adapt);
194: PetscFree(forest->topology);
195: PetscFree(forest);
196: return 0;
197: }
199: /*@C
200: DMForestSetTopology - Set the topology of a DMForest during the pre-setup phase. The topology is a string (e.g.
201: "cube", "shell") and can be interpreted by subtypes of DMFOREST) to construct the base DM of a forest during
202: DMSetUp().
204: Logically collective on dm
206: Input parameters:
207: + dm - the forest
208: - topology - the topology of the forest
210: Level: intermediate
212: .seealso: `DMForestGetTopology()`, `DMForestSetBaseDM()`
213: @*/
214: PetscErrorCode DMForestSetTopology(DM dm, DMForestTopology topology)
215: {
216: DM_Forest *forest = (DM_Forest *)dm->data;
220: PetscFree(forest->topology);
221: PetscStrallocpy((const char *)topology, (char **)&forest->topology);
222: return 0;
223: }
225: /*@C
226: DMForestGetTopology - Get a string describing the topology of a DMForest.
228: Not collective
230: Input parameter:
231: . dm - the forest
233: Output parameter:
234: . topology - the topology of the forest (e.g., 'cube', 'shell')
236: Level: intermediate
238: .seealso: `DMForestSetTopology()`
239: @*/
240: PetscErrorCode DMForestGetTopology(DM dm, DMForestTopology *topology)
241: {
242: DM_Forest *forest = (DM_Forest *)dm->data;
246: *topology = forest->topology;
247: return 0;
248: }
250: /*@
251: DMForestSetBaseDM - During the pre-setup phase, set the DM that defines the base mesh of a DMForest forest. The
252: forest will be hierarchically refined from the base, and all refinements/coarsenings of the forest will share its
253: base. In general, two forest must share a base to be comparable, to do things like construct interpolators.
255: Logically collective on dm
257: Input Parameters:
258: + dm - the forest
259: - base - the base DM of the forest
261: Notes:
262: Currently the base DM must be a DMPLEX
264: Level: intermediate
266: .seealso: `DMForestGetBaseDM()`
267: @*/
268: PetscErrorCode DMForestSetBaseDM(DM dm, DM base)
269: {
270: DM_Forest *forest = (DM_Forest *)dm->data;
271: PetscInt dim, dimEmbed;
275: PetscObjectReference((PetscObject)base);
276: DMDestroy(&forest->base);
277: forest->base = base;
278: if (base) {
279: const PetscReal *maxCell, *Lstart, *L;
282: DMGetDimension(base, &dim);
283: DMSetDimension(dm, dim);
284: DMGetCoordinateDim(base, &dimEmbed);
285: DMSetCoordinateDim(dm, dimEmbed);
286: DMGetPeriodicity(base, &maxCell, &Lstart, &L);
287: DMSetPeriodicity(dm, maxCell, Lstart, L);
288: } else DMSetPeriodicity(dm, NULL, NULL, NULL);
289: return 0;
290: }
292: /*@
293: DMForestGetBaseDM - Get the base DM of a DMForest forest. The forest will be hierarchically refined from the base,
294: and all refinements/coarsenings of the forest will share its base. In general, two forest must share a base to be
295: comparable, to do things like construct interpolators.
297: Not collective
299: Input Parameter:
300: . dm - the forest
302: Output Parameter:
303: . base - the base DM of the forest
305: Notes:
306: After DMSetUp(), the base DM will be redundantly distributed across MPI processes
308: Level: intermediate
310: .seealso: `DMForestSetBaseDM()`
311: @*/
312: PetscErrorCode DMForestGetBaseDM(DM dm, DM *base)
313: {
314: DM_Forest *forest = (DM_Forest *)dm->data;
318: *base = forest->base;
319: return 0;
320: }
322: PetscErrorCode DMForestSetBaseCoordinateMapping(DM dm, PetscErrorCode (*func)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *), void *ctx)
323: {
324: DM_Forest *forest = (DM_Forest *)dm->data;
327: forest->mapcoordinates = func;
328: forest->mapcoordinatesctx = ctx;
329: return 0;
330: }
332: PetscErrorCode DMForestGetBaseCoordinateMapping(DM dm, PetscErrorCode (**func)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void *), void *ctx)
333: {
334: DM_Forest *forest = (DM_Forest *)dm->data;
337: if (func) *func = forest->mapcoordinates;
338: if (ctx) *((void **)ctx) = forest->mapcoordinatesctx;
339: return 0;
340: }
342: /*@
343: DMForestSetAdaptivityForest - During the pre-setup phase, set the forest from which the current forest will be
344: adapted (e.g., the current forest will be refined/coarsened/repartitioned from it) im DMSetUp(). Usually not needed
345: by users directly: DMForestTemplate() constructs a new forest to be adapted from an old forest and calls this
346: routine.
348: Note that this can be called after setup with adapt = NULL, which will clear all internal data related to the
349: adaptivity forest from dm. This way, repeatedly adapting does not leave stale DM objects in memory.
351: Logically collective on dm
353: Input Parameters:
354: + dm - the new forest, which will be constructed from adapt
355: - adapt - the old forest
357: Level: intermediate
359: .seealso: `DMForestGetAdaptivityForest()`, `DMForestSetAdaptivityPurpose()`
360: @*/
361: PetscErrorCode DMForestSetAdaptivityForest(DM dm, DM adapt)
362: {
363: DM_Forest *forest, *adaptForest, *oldAdaptForest;
364: DM oldAdapt;
365: PetscBool isForest;
369: DMIsForest(dm, &isForest);
370: if (!isForest) return 0;
372: forest = (DM_Forest *)dm->data;
373: DMForestGetAdaptivityForest(dm, &oldAdapt);
374: adaptForest = (DM_Forest *)(adapt ? adapt->data : NULL);
375: oldAdaptForest = (DM_Forest *)(oldAdapt ? oldAdapt->data : NULL);
376: if (adaptForest != oldAdaptForest) {
377: PetscSFDestroy(&forest->preCoarseToFine);
378: PetscSFDestroy(&forest->coarseToPreFine);
379: if (forest->clearadaptivityforest) (*forest->clearadaptivityforest)(dm);
380: }
381: switch (forest->adaptPurpose) {
382: case DM_ADAPT_DETERMINE:
383: PetscObjectReference((PetscObject)adapt);
384: DMDestroy(&(forest->adapt));
385: forest->adapt = adapt;
386: break;
387: case DM_ADAPT_REFINE:
388: DMSetCoarseDM(dm, adapt);
389: break;
390: case DM_ADAPT_COARSEN:
391: case DM_ADAPT_COARSEN_LAST:
392: DMSetFineDM(dm, adapt);
393: break;
394: default:
395: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid adaptivity purpose");
396: }
397: return 0;
398: }
400: /*@
401: DMForestGetAdaptivityForest - Get the forest from which the current forest is adapted.
403: Not collective
405: Input Parameter:
406: . dm - the forest
408: Output Parameter:
409: . adapt - the forest from which dm is/was adapted
411: Level: intermediate
413: .seealso: `DMForestSetAdaptivityForest()`, `DMForestSetAdaptivityPurpose()`
414: @*/
415: PetscErrorCode DMForestGetAdaptivityForest(DM dm, DM *adapt)
416: {
417: DM_Forest *forest;
420: forest = (DM_Forest *)dm->data;
421: switch (forest->adaptPurpose) {
422: case DM_ADAPT_DETERMINE:
423: *adapt = forest->adapt;
424: break;
425: case DM_ADAPT_REFINE:
426: DMGetCoarseDM(dm, adapt);
427: break;
428: case DM_ADAPT_COARSEN:
429: case DM_ADAPT_COARSEN_LAST:
430: DMGetFineDM(dm, adapt);
431: break;
432: default:
433: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid adaptivity purpose");
434: }
435: return 0;
436: }
438: /*@
439: DMForestSetAdaptivityPurpose - During the pre-setup phase, set whether the current DM is being adapted from its
440: source (set with DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening
441: (DM_ADAPT_COARSEN), or undefined (DM_ADAPT_DETERMINE). This only matters for the purposes of reference counting:
442: during DMDestroy(), cyclic references can be found between DMs only if the cyclic reference is due to a fine/coarse
443: relationship (see DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does
444: not maintain a reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can
445: cause a memory leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.
447: Logically collective on dm
449: Input Parameters:
450: + dm - the forest
451: - purpose - the adaptivity purpose
453: Level: advanced
455: .seealso: `DMForestTemplate()`, `DMForestSetAdaptivityForest()`, `DMForestGetAdaptivityForest()`, `DMAdaptFlag`
456: @*/
457: PetscErrorCode DMForestSetAdaptivityPurpose(DM dm, DMAdaptFlag purpose)
458: {
459: DM_Forest *forest;
461: forest = (DM_Forest *)dm->data;
463: if (purpose != forest->adaptPurpose) {
464: DM adapt;
466: DMForestGetAdaptivityForest(dm, &adapt);
467: PetscObjectReference((PetscObject)adapt);
468: DMForestSetAdaptivityForest(dm, NULL);
470: forest->adaptPurpose = purpose;
472: DMForestSetAdaptivityForest(dm, adapt);
473: DMDestroy(&adapt);
474: }
475: return 0;
476: }
478: /*@
479: DMForestGetAdaptivityPurpose - Get whether the current DM is being adapted from its source (set with
480: DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening (DM_ADAPT_COARSEN),
481: coarsening only the last level (DM_ADAPT_COARSEN_LAST) or undefined (DM_ADAPT_DETERMINE).
482: This only matters for the purposes of reference counting: during DMDestroy(), cyclic
483: references can be found between DMs only if the cyclic reference is due to a fine/coarse relationship (see
484: DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does not maintain a
485: reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can cause a memory
486: leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.
488: Not collective
490: Input Parameter:
491: . dm - the forest
493: Output Parameter:
494: . purpose - the adaptivity purpose
496: Level: advanced
498: .seealso: `DMForestTemplate()`, `DMForestSetAdaptivityForest()`, `DMForestGetAdaptivityForest()`, `DMAdaptFlag`
499: @*/
500: PetscErrorCode DMForestGetAdaptivityPurpose(DM dm, DMAdaptFlag *purpose)
501: {
502: DM_Forest *forest;
504: forest = (DM_Forest *)dm->data;
505: *purpose = forest->adaptPurpose;
506: return 0;
507: }
509: /*@
510: DMForestSetAdjacencyDimension - During the pre-setup phase, set the dimension of interface points that determine
511: cell adjacency (for the purposes of partitioning and overlap).
513: Logically collective on dm
515: Input Parameters:
516: + dm - the forest
517: - adjDim - default 0 (i.e., vertices determine adjacency)
519: Level: intermediate
521: .seealso: `DMForestGetAdjacencyDimension()`, `DMForestSetAdjacencyCodimension()`, `DMForestSetPartitionOverlap()`
522: @*/
523: PetscErrorCode DMForestSetAdjacencyDimension(DM dm, PetscInt adjDim)
524: {
525: PetscInt dim;
526: DM_Forest *forest = (DM_Forest *)dm->data;
531: DMGetDimension(dm, &dim);
533: forest->adjDim = adjDim;
534: return 0;
535: }
537: /*@
538: DMForestSetAdjacencyCodimension - Like DMForestSetAdjacencyDimension(), but specified as a co-dimension (so that,
539: e.g., adjacency based on facets can be specified by codimension 1 in all cases)
541: Logically collective on dm
543: Input Parameters:
544: + dm - the forest
545: - adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices
547: Level: intermediate
549: .seealso: `DMForestGetAdjacencyCodimension()`, `DMForestSetAdjacencyDimension()`
550: @*/
551: PetscErrorCode DMForestSetAdjacencyCodimension(DM dm, PetscInt adjCodim)
552: {
553: PetscInt dim;
556: DMGetDimension(dm, &dim);
557: DMForestSetAdjacencyDimension(dm, dim - adjCodim);
558: return 0;
559: }
561: /*@
562: DMForestGetAdjacencyDimension - Get the dimension of interface points that determine cell adjacency (for the
563: purposes of partitioning and overlap).
565: Not collective
567: Input Parameter:
568: . dm - the forest
570: Output Parameter:
571: . adjDim - default 0 (i.e., vertices determine adjacency)
573: Level: intermediate
575: .seealso: `DMForestSetAdjacencyDimension()`, `DMForestGetAdjacencyCodimension()`, `DMForestSetPartitionOverlap()`
576: @*/
577: PetscErrorCode DMForestGetAdjacencyDimension(DM dm, PetscInt *adjDim)
578: {
579: DM_Forest *forest = (DM_Forest *)dm->data;
583: *adjDim = forest->adjDim;
584: return 0;
585: }
587: /*@
588: DMForestGetAdjacencyCodimension - Like DMForestGetAdjacencyDimension(), but specified as a co-dimension (so that,
589: e.g., adjacency based on facets can be specified by codimension 1 in all cases)
591: Not collective
593: Input Parameter:
594: . dm - the forest
596: Output Parameter:
597: . adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices
599: Level: intermediate
601: .seealso: `DMForestSetAdjacencyCodimension()`, `DMForestGetAdjacencyDimension()`
602: @*/
603: PetscErrorCode DMForestGetAdjacencyCodimension(DM dm, PetscInt *adjCodim)
604: {
605: DM_Forest *forest = (DM_Forest *)dm->data;
606: PetscInt dim;
610: DMGetDimension(dm, &dim);
611: *adjCodim = dim - forest->adjDim;
612: return 0;
613: }
615: /*@
616: DMForestSetPartitionOverlap - During the pre-setup phase, set the amount of cell-overlap present in parallel
617: partitions of a forest, with values > 0 indicating subdomains that are expanded by that many iterations of adding
618: adjacent cells
620: Logically collective on dm
622: Input Parameters:
623: + dm - the forest
624: - overlap - default 0
626: Level: intermediate
628: .seealso: `DMForestGetPartitionOverlap()`, `DMForestSetAdjacencyDimension()`, `DMForestSetAdjacencyCodimension()`
629: @*/
630: PetscErrorCode DMForestSetPartitionOverlap(DM dm, PetscInt overlap)
631: {
632: DM_Forest *forest = (DM_Forest *)dm->data;
637: forest->overlap = overlap;
638: return 0;
639: }
641: /*@
642: DMForestGetPartitionOverlap - Get the amount of cell-overlap present in parallel partitions of a forest, with values
643: > 0 indicating subdomains that are expanded by that many iterations of adding adjacent cells
645: Not collective
647: Input Parameter:
648: . dm - the forest
650: Output Parameter:
651: . overlap - default 0
653: Level: intermediate
655: .seealso: `DMForestGetPartitionOverlap()`, `DMForestSetAdjacencyDimension()`, `DMForestSetAdjacencyCodimension()`
656: @*/
657: PetscErrorCode DMForestGetPartitionOverlap(DM dm, PetscInt *overlap)
658: {
659: DM_Forest *forest = (DM_Forest *)dm->data;
663: *overlap = forest->overlap;
664: return 0;
665: }
667: /*@
668: DMForestSetMinimumRefinement - During the pre-setup phase, set the minimum level of refinement (relative to the base
669: DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest
670: (see DMForestGetAdaptivityForest()) this limits the amount of coarsening.
672: Logically collective on dm
674: Input Parameters:
675: + dm - the forest
676: - minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
678: Level: intermediate
680: .seealso: `DMForestGetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestSetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityForest()`
681: @*/
682: PetscErrorCode DMForestSetMinimumRefinement(DM dm, PetscInt minRefinement)
683: {
684: DM_Forest *forest = (DM_Forest *)dm->data;
688: forest->minRefinement = minRefinement;
689: return 0;
690: }
692: /*@
693: DMForestGetMinimumRefinement - Get the minimum level of refinement (relative to the base DM, see
694: DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest (see
695: DMForestGetAdaptivityForest()), this limits the amount of coarsening.
697: Not collective
699: Input Parameter:
700: . dm - the forest
702: Output Parameter:
703: . minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
705: Level: intermediate
707: .seealso: `DMForestSetMinimumRefinement()`, `DMForestGetMaximumRefinement()`, `DMForestGetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityForest()`
708: @*/
709: PetscErrorCode DMForestGetMinimumRefinement(DM dm, PetscInt *minRefinement)
710: {
711: DM_Forest *forest = (DM_Forest *)dm->data;
715: *minRefinement = forest->minRefinement;
716: return 0;
717: }
719: /*@
720: DMForestSetInitialRefinement - During the pre-setup phase, set the initial level of refinement (relative to the base
721: DM, see DMForestGetBaseDM()) allowed in the forest.
723: Logically collective on dm
725: Input Parameters:
726: + dm - the forest
727: - initefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
729: Level: intermediate
731: .seealso: `DMForestSetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestGetBaseDM()`
732: @*/
733: PetscErrorCode DMForestSetInitialRefinement(DM dm, PetscInt initRefinement)
734: {
735: DM_Forest *forest = (DM_Forest *)dm->data;
739: forest->initRefinement = initRefinement;
740: return 0;
741: }
743: /*@
744: DMForestGetInitialRefinement - Get the initial level of refinement (relative to the base DM, see
745: DMForestGetBaseDM()) allowed in the forest.
747: Not collective
749: Input Parameter:
750: . dm - the forest
752: Output Parameter:
753: . initRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
755: Level: intermediate
757: .seealso: `DMForestSetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestGetBaseDM()`
758: @*/
759: PetscErrorCode DMForestGetInitialRefinement(DM dm, PetscInt *initRefinement)
760: {
761: DM_Forest *forest = (DM_Forest *)dm->data;
765: *initRefinement = forest->initRefinement;
766: return 0;
767: }
769: /*@
770: DMForestSetMaximumRefinement - During the pre-setup phase, set the maximum level of refinement (relative to the base
771: DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest
772: (see DMForestGetAdaptivityForest()), this limits the amount of refinement.
774: Logically collective on dm
776: Input Parameters:
777: + dm - the forest
778: - maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
780: Level: intermediate
782: .seealso: `DMForestGetMinimumRefinement()`, `DMForestSetMaximumRefinement()`, `DMForestSetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityDM()`
783: @*/
784: PetscErrorCode DMForestSetMaximumRefinement(DM dm, PetscInt maxRefinement)
785: {
786: DM_Forest *forest = (DM_Forest *)dm->data;
790: forest->maxRefinement = maxRefinement;
791: return 0;
792: }
794: /*@
795: DMForestGetMaximumRefinement - Get the maximum level of refinement (relative to the base DM, see
796: DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest (see
797: DMForestGetAdaptivityForest()), this limits the amount of refinement.
799: Not collective
801: Input Parameter:
802: . dm - the forest
804: Output Parameter:
805: . maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
807: Level: intermediate
809: .seealso: `DMForestSetMaximumRefinement()`, `DMForestGetMinimumRefinement()`, `DMForestGetInitialRefinement()`, `DMForestGetBaseDM()`, `DMForestGetAdaptivityForest()`
810: @*/
811: PetscErrorCode DMForestGetMaximumRefinement(DM dm, PetscInt *maxRefinement)
812: {
813: DM_Forest *forest = (DM_Forest *)dm->data;
817: *maxRefinement = forest->maxRefinement;
818: return 0;
819: }
821: /*@C
822: DMForestSetAdaptivityStrategy - During the pre-setup phase, set the strategy for combining adaptivity labels from multiple processes.
823: Subtypes of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all processes must agree
824: for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only one process needs to
825: specify refinement/coarsening.
827: Logically collective on dm
829: Input Parameters:
830: + dm - the forest
831: - adaptStrategy - default DMFORESTADAPTALL
833: Level: advanced
835: .seealso: `DMForestGetAdaptivityStrategy()`
836: @*/
837: PetscErrorCode DMForestSetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy adaptStrategy)
838: {
839: DM_Forest *forest = (DM_Forest *)dm->data;
842: PetscFree(forest->adaptStrategy);
843: PetscStrallocpy((const char *)adaptStrategy, (char **)&forest->adaptStrategy);
844: return 0;
845: }
847: /*@C
848: DMForestSetAdaptivityStrategy - Get the strategy for combining adaptivity labels from multiple processes. Subtypes
849: of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all
850: processes must agree for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only
851: one process needs to specify refinement/coarsening.
853: Not collective
855: Input Parameter:
856: . dm - the forest
858: Output Parameter:
859: . adaptStrategy - the adaptivity strategy (default DMFORESTADAPTALL)
861: Level: advanced
863: .seealso: `DMForestSetAdaptivityStrategy()`
864: @*/
865: PetscErrorCode DMForestGetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy *adaptStrategy)
866: {
867: DM_Forest *forest = (DM_Forest *)dm->data;
871: *adaptStrategy = forest->adaptStrategy;
872: return 0;
873: }
875: /*@
876: DMForestGetAdaptivitySuccess - Return whether the requested adaptation (refinement, coarsening, repartitioning,
877: etc.) was successful. PETSC_FALSE indicates that the post-adaptation forest is the same as the pre-adpatation
878: forest. A requested adaptation may have been unsuccessful if, for example, the requested refinement would have
879: exceeded the maximum refinement level.
881: Collective on dm
883: Input Parameter:
885: . dm - the post-adaptation forest
887: Output Parameter:
889: . success - PETSC_TRUE if the post-adaptation forest is different from the pre-adaptation forest.
891: Level: intermediate
893: .see
894: @*/
895: PetscErrorCode DMForestGetAdaptivitySuccess(DM dm, PetscBool *success)
896: {
897: DM_Forest *forest;
901: forest = (DM_Forest *)dm->data;
902: (forest->getadaptivitysuccess)(dm, success);
903: return 0;
904: }
906: /*@
907: DMForestSetComputeAdaptivitySF - During the pre-setup phase, set whether transfer PetscSFs should be computed
908: 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().
910: Logically collective on dm
912: Input Parameters:
913: + dm - the post-adaptation forest
914: - computeSF - default PETSC_TRUE
916: Level: advanced
918: .seealso: `DMForestGetComputeAdaptivitySF()`, `DMForestGetAdaptivitySF()`
919: @*/
920: PetscErrorCode DMForestSetComputeAdaptivitySF(DM dm, PetscBool computeSF)
921: {
922: DM_Forest *forest;
926: forest = (DM_Forest *)dm->data;
927: forest->computeAdaptSF = computeSF;
928: return 0;
929: }
931: PetscErrorCode DMForestTransferVec(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time)
932: {
933: DM_Forest *forest;
939: forest = (DM_Forest *)dmIn->data;
941: (forest->transfervec)(dmIn, vecIn, dmOut, vecOut, useBCs, time);
942: return 0;
943: }
945: PetscErrorCode DMForestTransferVecFromBase(DM dm, Vec vecIn, Vec vecOut)
946: {
947: DM_Forest *forest;
952: forest = (DM_Forest *)dm->data;
954: (forest->transfervecfrombase)(dm, vecIn, vecOut);
955: return 0;
956: }
958: /*@
959: DMForestGetComputeAdaptivitySF - Get whether transfer PetscSFs should be computed relating the cells of the
960: pre-adaptation forest to the post-adaptiation forest. After DMSetUp() is called, these transfer PetscSFs can be
961: accessed with DMForestGetAdaptivitySF().
963: Not collective
965: Input Parameter:
966: . dm - the post-adaptation forest
968: Output Parameter:
969: . computeSF - default PETSC_TRUE
971: Level: advanced
973: .seealso: `DMForestSetComputeAdaptivitySF()`, `DMForestGetAdaptivitySF()`
974: @*/
975: PetscErrorCode DMForestGetComputeAdaptivitySF(DM dm, PetscBool *computeSF)
976: {
977: DM_Forest *forest;
980: forest = (DM_Forest *)dm->data;
981: *computeSF = forest->computeAdaptSF;
982: return 0;
983: }
985: /*@
986: DMForestGetAdaptivitySF - Get PetscSFs that relate the pre-adaptation forest to the post-adaptation forest.
987: Adaptation can be any combination of refinement, coarsening, repartition, and change of overlap, so there may be
988: some cells of the pre-adaptation that are parents of post-adaptation cells, and vice versa. Therefore there are two
989: PetscSFs: one that relates pre-adaptation coarse cells to post-adaptation fine cells, and one that relates
990: pre-adaptation fine cells to post-adaptation coarse cells.
992: Not collective
994: Input Parameter:
995: dm - the post-adaptation forest
997: Output Parameter:
998: preCoarseToFine - pre-adaptation coarse cells to post-adaptation fine cells: BCast goes from pre- to post-
999: coarseToPreFine - post-adaptation coarse cells to pre-adaptation fine cells: BCast goes from post- to pre-
1001: Level: advanced
1003: .seealso: `DMForestGetComputeAdaptivitySF()`, `DMForestSetComputeAdaptivitySF()`
1004: @*/
1005: PetscErrorCode DMForestGetAdaptivitySF(DM dm, PetscSF *preCoarseToFine, PetscSF *coarseToPreFine)
1006: {
1007: DM_Forest *forest;
1010: DMSetUp(dm);
1011: forest = (DM_Forest *)dm->data;
1012: if (preCoarseToFine) *preCoarseToFine = forest->preCoarseToFine;
1013: if (coarseToPreFine) *coarseToPreFine = forest->coarseToPreFine;
1014: return 0;
1015: }
1017: /*@
1018: DMForestSetGradeFactor - During the pre-setup phase, set the desired amount of grading in the mesh, e.g. give 2 to
1019: indicate that the diameter of neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may
1020: only support one particular choice of grading factor.
1022: Logically collective on dm
1024: Input Parameters:
1025: + dm - the forest
1026: - grade - the grading factor
1028: Level: advanced
1030: .seealso: `DMForestGetGradeFactor()`
1031: @*/
1032: PetscErrorCode DMForestSetGradeFactor(DM dm, PetscInt grade)
1033: {
1034: DM_Forest *forest = (DM_Forest *)dm->data;
1038: forest->gradeFactor = grade;
1039: return 0;
1040: }
1042: /*@
1043: DMForestGetGradeFactor - Get the desired amount of grading in the mesh, e.g. give 2 to indicate that the diameter of
1044: neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may only support one particular
1045: choice of grading factor.
1047: Not collective
1049: Input Parameter:
1050: . dm - the forest
1052: Output Parameter:
1053: . grade - the grading factor
1055: Level: advanced
1057: .seealso: `DMForestSetGradeFactor()`
1058: @*/
1059: PetscErrorCode DMForestGetGradeFactor(DM dm, PetscInt *grade)
1060: {
1061: DM_Forest *forest = (DM_Forest *)dm->data;
1065: *grade = forest->gradeFactor;
1066: return 0;
1067: }
1069: /*@
1070: DMForestSetCellWeightFactor - During the pre-setup phase, set the factor by which the level of refinement changes
1071: the cell weight (see DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be
1072: (cellWeight) * (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on
1073: its level; a factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the
1074: computation associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1076: Logically collective on dm
1078: Input Parameters:
1079: + dm - the forest
1080: - weightsFactors - default 1.
1082: Level: advanced
1084: .seealso: `DMForestGetCellWeightFactor()`, `DMForestSetCellWeights()`
1085: @*/
1086: PetscErrorCode DMForestSetCellWeightFactor(DM dm, PetscReal weightsFactor)
1087: {
1088: DM_Forest *forest = (DM_Forest *)dm->data;
1092: forest->weightsFactor = weightsFactor;
1093: return 0;
1094: }
1096: /*@
1097: DMForestGetCellWeightFactor - Get the factor by which the level of refinement changes the cell weight (see
1098: DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be (cellWeight) *
1099: (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on its level; a
1100: factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the computation
1101: associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1103: Not collective
1105: Input Parameter:
1106: . dm - the forest
1108: Output Parameter:
1109: . weightsFactors - default 1.
1111: Level: advanced
1113: .seealso: `DMForestSetCellWeightFactor()`, `DMForestSetCellWeights()`
1114: @*/
1115: PetscErrorCode DMForestGetCellWeightFactor(DM dm, PetscReal *weightsFactor)
1116: {
1117: DM_Forest *forest = (DM_Forest *)dm->data;
1121: *weightsFactor = forest->weightsFactor;
1122: return 0;
1123: }
1125: /*@
1126: DMForestGetCellChart - After the setup phase, get the local half-open interval of the chart of cells on this process
1128: Not collective
1130: Input Parameter:
1131: . dm - the forest
1133: Output Parameters:
1134: + cStart - the first cell on this process
1135: - cEnd - one after the final cell on this process
1137: Level: intermediate
1139: .seealso: `DMForestGetCellSF()`
1140: @*/
1141: PetscErrorCode DMForestGetCellChart(DM dm, PetscInt *cStart, PetscInt *cEnd)
1142: {
1143: DM_Forest *forest = (DM_Forest *)dm->data;
1148: if (((forest->cStart == PETSC_DETERMINE) || (forest->cEnd == PETSC_DETERMINE)) && forest->createcellchart) forest->createcellchart(dm, &forest->cStart, &forest->cEnd);
1149: *cStart = forest->cStart;
1150: *cEnd = forest->cEnd;
1151: return 0;
1152: }
1154: /*@
1155: DMForestGetCellSF - After the setup phase, get the PetscSF for overlapping cells between processes
1157: Not collective
1159: Input Parameter:
1160: . dm - the forest
1162: Output Parameter:
1163: . cellSF - the PetscSF
1165: Level: intermediate
1167: .seealso: `DMForestGetCellChart()`
1168: @*/
1169: PetscErrorCode DMForestGetCellSF(DM dm, PetscSF *cellSF)
1170: {
1171: DM_Forest *forest = (DM_Forest *)dm->data;
1175: if ((!forest->cellSF) && forest->createcellsf) forest->createcellsf(dm, &forest->cellSF);
1176: *cellSF = forest->cellSF;
1177: return 0;
1178: }
1180: /*@C
1181: DMForestSetAdaptivityLabel - During the pre-setup phase, set the label of the pre-adaptation forest (see
1182: DMForestGetAdaptivityForest()) that holds the adaptation flags (refinement, coarsening, or some combination). The
1183: interpretation of the label values is up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP,
1184: DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have been reserved as choices that should be accepted by all subtypes.
1186: Logically collective on dm
1188: Input Parameters:
1189: - dm - the forest
1190: + adaptLabel - the label in the pre-adaptation forest
1192: Level: intermediate
1194: .seealso `DMForestGetAdaptivityLabel()`
1195: @*/
1196: PetscErrorCode DMForestSetAdaptivityLabel(DM dm, DMLabel adaptLabel)
1197: {
1198: DM_Forest *forest = (DM_Forest *)dm->data;
1202: PetscObjectReference((PetscObject)adaptLabel);
1203: DMLabelDestroy(&forest->adaptLabel);
1204: forest->adaptLabel = adaptLabel;
1205: return 0;
1206: }
1208: /*@C
1209: DMForestGetAdaptivityLabel - Get the label of the pre-adaptation forest (see DMForestGetAdaptivityForest()) that
1210: holds the adaptation flags (refinement, coarsening, or some combination). The interpretation of the label values is
1211: up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have
1212: been reserved as choices that should be accepted by all subtypes.
1214: Not collective
1216: Input Parameter:
1217: . dm - the forest
1219: Output Parameter:
1220: . adaptLabel - the name of the label in the pre-adaptation forest
1222: Level: intermediate
1224: .seealso `DMForestSetAdaptivityLabel()`
1225: @*/
1226: PetscErrorCode DMForestGetAdaptivityLabel(DM dm, DMLabel *adaptLabel)
1227: {
1228: DM_Forest *forest = (DM_Forest *)dm->data;
1231: *adaptLabel = forest->adaptLabel;
1232: return 0;
1233: }
1235: /*@
1236: DMForestSetCellWeights - Set the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
1237: process: weights are used to determine parallel partitioning. Partitions will be created so that each process's
1238: ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
1239: of 1.
1241: Logically collective on dm
1243: Input Parameters:
1244: + dm - the forest
1245: . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.
1246: - copyMode - how weights should reference weights
1248: Level: advanced
1250: .seealso: `DMForestGetCellWeights()`, `DMForestSetWeightCapacity()`
1251: @*/
1252: PetscErrorCode DMForestSetCellWeights(DM dm, PetscReal weights[], PetscCopyMode copyMode)
1253: {
1254: DM_Forest *forest = (DM_Forest *)dm->data;
1255: PetscInt cStart, cEnd;
1258: DMForestGetCellChart(dm, &cStart, &cEnd);
1260: if (copyMode == PETSC_COPY_VALUES) {
1261: if (forest->cellWeightsCopyMode != PETSC_OWN_POINTER || forest->cellWeights == weights) PetscMalloc1(cEnd - cStart, &forest->cellWeights);
1262: PetscArraycpy(forest->cellWeights, weights, cEnd - cStart);
1263: forest->cellWeightsCopyMode = PETSC_OWN_POINTER;
1264: return 0;
1265: }
1266: if (forest->cellWeightsCopyMode == PETSC_OWN_POINTER) PetscFree(forest->cellWeights);
1267: forest->cellWeights = weights;
1268: forest->cellWeightsCopyMode = copyMode;
1269: return 0;
1270: }
1272: /*@
1273: DMForestGetCellWeights - Get the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
1274: process: weights are used to determine parallel partitioning. Partitions will be created so that each process's
1275: ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
1276: of 1.
1278: Not collective
1280: Input Parameter:
1281: . dm - the forest
1283: Output Parameter:
1284: . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.
1286: Level: advanced
1288: .seealso: `DMForestSetCellWeights()`, `DMForestSetWeightCapacity()`
1289: @*/
1290: PetscErrorCode DMForestGetCellWeights(DM dm, PetscReal **weights)
1291: {
1292: DM_Forest *forest = (DM_Forest *)dm->data;
1296: *weights = forest->cellWeights;
1297: return 0;
1298: }
1300: /*@
1301: DMForestSetWeightCapacity - During the pre-setup phase, set the capacity of the current process when repartitioning
1302: a pre-adaptation forest (see DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each
1303: process's cells to the process's capacity will be roughly equal for all processes. A capacity of 0 indicates that
1304: the current process should not have any cells after repartitioning.
1306: Logically Collective on dm
1308: Input parameters:
1309: + dm - the forest
1310: - capacity - this process's capacity
1312: Level: advanced
1314: .seealso `DMForestGetWeightCapacity()`, `DMForestSetCellWeights()`, `DMForestSetCellWeightFactor()`
1315: @*/
1316: PetscErrorCode DMForestSetWeightCapacity(DM dm, PetscReal capacity)
1317: {
1318: DM_Forest *forest = (DM_Forest *)dm->data;
1323: forest->weightCapacity = capacity;
1324: return 0;
1325: }
1327: /*@
1328: DMForestGetWeightCapacity - Set the capacity of the current process when repartitioning a pre-adaptation forest (see
1329: DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each process's cells to the
1330: process's capacity will be roughly equal for all processes. A capacity of 0 indicates that the current process
1331: should not have any cells after repartitioning.
1333: Not collective
1335: Input parameter:
1336: . dm - the forest
1338: Output parameter:
1339: . capacity - this process's capacity
1341: Level: advanced
1343: .seealso `DMForestSetWeightCapacity()`, `DMForestSetCellWeights()`, `DMForestSetCellWeightFactor()`
1344: @*/
1345: PetscErrorCode DMForestGetWeightCapacity(DM dm, PetscReal *capacity)
1346: {
1347: DM_Forest *forest = (DM_Forest *)dm->data;
1351: *capacity = forest->weightCapacity;
1352: return 0;
1353: }
1355: PETSC_EXTERN PetscErrorCode DMSetFromOptions_Forest(DM dm, PetscOptionItems *PetscOptionsObject)
1356: {
1357: PetscBool flg, flg1, flg2, flg3, flg4;
1358: DMForestTopology oldTopo;
1359: char stringBuffer[256];
1360: PetscViewer viewer;
1361: PetscViewerFormat format;
1362: PetscInt adjDim, adjCodim, overlap, minRefinement, initRefinement, maxRefinement, grade;
1363: PetscReal weightsFactor;
1364: DMForestAdaptivityStrategy adaptStrategy;
1366: DMForestGetTopology(dm, &oldTopo);
1367: PetscOptionsHeadBegin(PetscOptionsObject, "DMForest Options");
1368: PetscOptionsString("-dm_forest_topology", "the topology of the forest's base mesh", "DMForestSetTopology", oldTopo, stringBuffer, sizeof(stringBuffer), &flg1);
1369: PetscOptionsViewer("-dm_forest_base_dm", "load the base DM from a viewer specification", "DMForestSetBaseDM", &viewer, &format, &flg2);
1370: PetscOptionsViewer("-dm_forest_coarse_forest", "load the coarse forest from a viewer specification", "DMForestSetCoarseForest", &viewer, &format, &flg3);
1371: PetscOptionsViewer("-dm_forest_fine_forest", "load the fine forest from a viewer specification", "DMForestSetFineForest", &viewer, &format, &flg4);
1373: if (flg1) {
1374: DMForestSetTopology(dm, (DMForestTopology)stringBuffer);
1375: DMForestSetBaseDM(dm, NULL);
1376: DMForestSetAdaptivityForest(dm, NULL);
1377: }
1378: if (flg2) {
1379: DM base;
1381: DMCreate(PetscObjectComm((PetscObject)dm), &base);
1382: PetscViewerPushFormat(viewer, format);
1383: DMLoad(base, viewer);
1384: PetscViewerDestroy(&viewer);
1385: DMForestSetBaseDM(dm, base);
1386: DMDestroy(&base);
1387: DMForestSetTopology(dm, NULL);
1388: DMForestSetAdaptivityForest(dm, NULL);
1389: }
1390: if (flg3) {
1391: DM coarse;
1393: DMCreate(PetscObjectComm((PetscObject)dm), &coarse);
1394: PetscViewerPushFormat(viewer, format);
1395: DMLoad(coarse, viewer);
1396: PetscViewerDestroy(&viewer);
1397: DMForestSetAdaptivityForest(dm, coarse);
1398: DMDestroy(&coarse);
1399: DMForestSetTopology(dm, NULL);
1400: DMForestSetBaseDM(dm, NULL);
1401: }
1402: if (flg4) {
1403: DM fine;
1405: DMCreate(PetscObjectComm((PetscObject)dm), &fine);
1406: PetscViewerPushFormat(viewer, format);
1407: DMLoad(fine, viewer);
1408: PetscViewerDestroy(&viewer);
1409: DMForestSetAdaptivityForest(dm, fine);
1410: DMDestroy(&fine);
1411: DMForestSetTopology(dm, NULL);
1412: DMForestSetBaseDM(dm, NULL);
1413: }
1414: DMForestGetAdjacencyDimension(dm, &adjDim);
1415: PetscOptionsBoundedInt("-dm_forest_adjacency_dimension", "set the dimension of points that define adjacency in the forest", "DMForestSetAdjacencyDimension", adjDim, &adjDim, &flg, 0);
1416: if (flg) {
1417: DMForestSetAdjacencyDimension(dm, adjDim);
1418: } else {
1419: DMForestGetAdjacencyCodimension(dm, &adjCodim);
1420: PetscOptionsBoundedInt("-dm_forest_adjacency_codimension", "set the codimension of points that define adjacency in the forest", "DMForestSetAdjacencyCodimension", adjCodim, &adjCodim, &flg, 1);
1421: if (flg) DMForestSetAdjacencyCodimension(dm, adjCodim);
1422: }
1423: DMForestGetPartitionOverlap(dm, &overlap);
1424: PetscOptionsBoundedInt("-dm_forest_partition_overlap", "set the degree of partition overlap", "DMForestSetPartitionOverlap", overlap, &overlap, &flg, 0);
1425: if (flg) DMForestSetPartitionOverlap(dm, overlap);
1426: #if 0
1427: 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);
1428: if (flg) {
1429: DMForestSetMinimumRefinement(dm,minRefinement);
1430: DMForestSetInitialRefinement(dm,minRefinement);
1431: }
1432: PetscOptionsBoundedInt("-dm_refine_hierarchy","equivalent to -dm_forest_set_minimum_refinement 0 and -dm_forest_set_initial_refinement",NULL,initRefinement,&initRefinement,&flg,0);
1433: if (flg) {
1434: DMForestSetMinimumRefinement(dm,0);
1435: DMForestSetInitialRefinement(dm,initRefinement);
1436: }
1437: #endif
1438: DMForestGetMinimumRefinement(dm, &minRefinement);
1439: PetscOptionsBoundedInt("-dm_forest_minimum_refinement", "set the minimum level of refinement in the forest", "DMForestSetMinimumRefinement", minRefinement, &minRefinement, &flg, 0);
1440: if (flg) DMForestSetMinimumRefinement(dm, minRefinement);
1441: DMForestGetInitialRefinement(dm, &initRefinement);
1442: PetscOptionsBoundedInt("-dm_forest_initial_refinement", "set the initial level of refinement in the forest", "DMForestSetInitialRefinement", initRefinement, &initRefinement, &flg, 0);
1443: if (flg) DMForestSetInitialRefinement(dm, initRefinement);
1444: DMForestGetMaximumRefinement(dm, &maxRefinement);
1445: PetscOptionsBoundedInt("-dm_forest_maximum_refinement", "set the maximum level of refinement in the forest", "DMForestSetMaximumRefinement", maxRefinement, &maxRefinement, &flg, 0);
1446: if (flg) DMForestSetMaximumRefinement(dm, maxRefinement);
1447: DMForestGetAdaptivityStrategy(dm, &adaptStrategy);
1448: PetscOptionsString("-dm_forest_adaptivity_strategy", "the forest's adaptivity-flag resolution strategy", "DMForestSetAdaptivityStrategy", adaptStrategy, stringBuffer, sizeof(stringBuffer), &flg);
1449: if (flg) DMForestSetAdaptivityStrategy(dm, (DMForestAdaptivityStrategy)stringBuffer);
1450: DMForestGetGradeFactor(dm, &grade);
1451: PetscOptionsBoundedInt("-dm_forest_grade_factor", "grade factor between neighboring cells", "DMForestSetGradeFactor", grade, &grade, &flg, 0);
1452: if (flg) DMForestSetGradeFactor(dm, grade);
1453: DMForestGetCellWeightFactor(dm, &weightsFactor);
1454: PetscOptionsReal("-dm_forest_cell_weight_factor", "multiplying weight factor for cell refinement", "DMForestSetCellWeightFactor", weightsFactor, &weightsFactor, &flg);
1455: if (flg) DMForestSetCellWeightFactor(dm, weightsFactor);
1456: PetscOptionsHeadEnd();
1457: return 0;
1458: }
1460: PetscErrorCode DMCreateSubDM_Forest(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1461: {
1462: if (subdm) DMClone(dm, subdm);
1463: DMCreateSectionSubDM(dm, numFields, fields, is, subdm);
1464: return 0;
1465: }
1467: PetscErrorCode DMRefine_Forest(DM dm, MPI_Comm comm, DM *dmRefined)
1468: {
1469: DMLabel refine;
1470: DM fineDM;
1472: DMGetFineDM(dm, &fineDM);
1473: if (fineDM) {
1474: PetscObjectReference((PetscObject)fineDM);
1475: *dmRefined = fineDM;
1476: return 0;
1477: }
1478: DMForestTemplate(dm, comm, dmRefined);
1479: DMGetLabel(dm, "refine", &refine);
1480: if (!refine) {
1481: DMLabelCreate(PETSC_COMM_SELF, "refine", &refine);
1482: DMLabelSetDefaultValue(refine, DM_ADAPT_REFINE);
1483: } else PetscObjectReference((PetscObject)refine);
1484: DMForestSetAdaptivityLabel(*dmRefined, refine);
1485: DMLabelDestroy(&refine);
1486: return 0;
1487: }
1489: PetscErrorCode DMCoarsen_Forest(DM dm, MPI_Comm comm, DM *dmCoarsened)
1490: {
1491: DMLabel coarsen;
1492: DM coarseDM;
1494: {
1495: PetscMPIInt mpiComparison;
1496: MPI_Comm dmcomm = PetscObjectComm((PetscObject)dm);
1498: MPI_Comm_compare(comm, dmcomm, &mpiComparison);
1500: }
1501: DMGetCoarseDM(dm, &coarseDM);
1502: if (coarseDM) {
1503: PetscObjectReference((PetscObject)coarseDM);
1504: *dmCoarsened = coarseDM;
1505: return 0;
1506: }
1507: DMForestTemplate(dm, comm, dmCoarsened);
1508: DMForestSetAdaptivityPurpose(*dmCoarsened, DM_ADAPT_COARSEN);
1509: DMGetLabel(dm, "coarsen", &coarsen);
1510: if (!coarsen) {
1511: DMLabelCreate(PETSC_COMM_SELF, "coarsen", &coarsen);
1512: DMLabelSetDefaultValue(coarsen, DM_ADAPT_COARSEN);
1513: } else PetscObjectReference((PetscObject)coarsen);
1514: DMForestSetAdaptivityLabel(*dmCoarsened, coarsen);
1515: DMLabelDestroy(&coarsen);
1516: return 0;
1517: }
1519: PetscErrorCode DMAdaptLabel_Forest(DM dm, PETSC_UNUSED Vec metric, DMLabel label, PETSC_UNUSED DMLabel rgLabel, DM *adaptedDM)
1520: {
1521: PetscBool success;
1523: DMForestTemplate(dm, PetscObjectComm((PetscObject)dm), adaptedDM);
1524: DMForestSetAdaptivityLabel(*adaptedDM, label);
1525: DMSetUp(*adaptedDM);
1526: DMForestGetAdaptivitySuccess(*adaptedDM, &success);
1527: if (!success) {
1528: DMDestroy(adaptedDM);
1529: *adaptedDM = NULL;
1530: }
1531: return 0;
1532: }
1534: static PetscErrorCode DMInitialize_Forest(DM dm)
1535: {
1536: PetscMemzero(dm->ops, sizeof(*(dm->ops)));
1538: dm->ops->clone = DMClone_Forest;
1539: dm->ops->setfromoptions = DMSetFromOptions_Forest;
1540: dm->ops->destroy = DMDestroy_Forest;
1541: dm->ops->createsubdm = DMCreateSubDM_Forest;
1542: dm->ops->refine = DMRefine_Forest;
1543: dm->ops->coarsen = DMCoarsen_Forest;
1544: return 0;
1545: }
1547: /*MC
1549: DMFOREST = "forest" - A DM object that encapsulates a hierarchically refined mesh. Forests usually have a base DM
1550: (see DMForestGetBaseDM()), from which it is refined. The refinement and partitioning of forests is considered
1551: immutable after DMSetUp() is called. To adapt a mesh, one should call DMForestTemplate() to create a new mesh that
1552: will default to being identical to it, specify how that mesh should differ, and then calling DMSetUp() on the new
1553: mesh.
1555: To specify that a mesh should be refined or coarsened from the previous mesh, a label should be defined on the
1556: previous mesh whose values indicate which cells should be refined (DM_ADAPT_REFINE) or coarsened (DM_ADAPT_COARSEN)
1557: and how (subtypes are free to allow additional values for things like anisotropic refinement). The label should be
1558: given to the *new* mesh with DMForestSetAdaptivityLabel().
1560: Level: advanced
1562: .seealso: `DMType`, `DMCreate()`, `DMSetType()`, `DMForestGetBaseDM()`, `DMForestSetBaseDM()`, `DMForestTemplate()`, `DMForestSetAdaptivityLabel()`
1563: M*/
1565: PETSC_EXTERN PetscErrorCode DMCreate_Forest(DM dm)
1566: {
1567: DM_Forest *forest;
1570: PetscNew(&forest);
1571: dm->dim = 0;
1572: dm->data = forest;
1573: forest->refct = 1;
1574: forest->data = NULL;
1575: forest->topology = NULL;
1576: forest->adapt = NULL;
1577: forest->base = NULL;
1578: forest->adaptPurpose = DM_ADAPT_DETERMINE;
1579: forest->adjDim = PETSC_DEFAULT;
1580: forest->overlap = PETSC_DEFAULT;
1581: forest->minRefinement = PETSC_DEFAULT;
1582: forest->maxRefinement = PETSC_DEFAULT;
1583: forest->initRefinement = PETSC_DEFAULT;
1584: forest->cStart = PETSC_DETERMINE;
1585: forest->cEnd = PETSC_DETERMINE;
1586: forest->cellSF = NULL;
1587: forest->adaptLabel = NULL;
1588: forest->gradeFactor = 2;
1589: forest->cellWeights = NULL;
1590: forest->cellWeightsCopyMode = PETSC_USE_POINTER;
1591: forest->weightsFactor = 1.;
1592: forest->weightCapacity = 1.;
1593: DMForestSetAdaptivityStrategy(dm, DMFORESTADAPTALL);
1594: DMInitialize_Forest(dm);
1595: return 0;
1596: }