Actual source code: forest.c
petsc-3.9.4 2018-09-11
1: #include <petsc/private/dmforestimpl.h>
2: #include <petsc/private/dmimpl.h>
3: #include <petsc/private/dmlabelimpl.h>
4: #include <petscsf.h>
6: PetscBool DMForestPackageInitialized = PETSC_FALSE;
8: typedef struct _DMForestTypeLink*DMForestTypeLink;
10: struct _DMForestTypeLink
11: {
12: char *name;
13: DMForestTypeLink next;
14: };
16: DMForestTypeLink DMForestTypeList;
18: static PetscErrorCode DMForestPackageFinalize(void)
19: {
20: DMForestTypeLink oldLink, link = DMForestTypeList;
21: PetscErrorCode ierr;
24: while (link) {
25: oldLink = link;
26: PetscFree(oldLink->name);
27: link = oldLink->next;
28: PetscFree(oldLink);
29: }
30: return(0);
31: }
33: static PetscErrorCode DMForestPackageInitialize(void)
34: {
38: if (DMForestPackageInitialized) return(0);
39: DMForestPackageInitialized = PETSC_TRUE;
41: DMForestRegisterType(DMFOREST);
42: PetscRegisterFinalize(DMForestPackageFinalize);
43: return(0);
44: }
46: /*@C
47: DMForestRegisterType - Registers a DMType as a subtype of DMFOREST (so that DMIsForest() will be correct)
49: Not Collective
51: Input parameter:
52: . name - the name of the type
54: Level: advanced
56: .seealso: DMFOREST, DMIsForest()
57: @*/
58: PetscErrorCode DMForestRegisterType(DMType name)
59: {
60: DMForestTypeLink link;
61: PetscErrorCode ierr;
64: DMForestPackageInitialize();
65: PetscNew(&link);
66: PetscStrallocpy(name,&link->name);
67: link->next = DMForestTypeList;
68: DMForestTypeList = link;
69: return(0);
70: }
72: /*@
73: DMIsForest - Check whether a DM uses the DMFOREST interface for hierarchically-refined meshes
75: Not Collective
77: Input parameter:
78: . dm - the DM object
80: Output parameter:
81: . isForest - whether dm is a subtype of DMFOREST
83: Level: intermediate
85: .seealso: DMFOREST, DMForestRegisterType()
86: @*/
87: PetscErrorCode DMIsForest(DM dm, PetscBool *isForest)
88: {
89: DMForestTypeLink link = DMForestTypeList;
90: PetscErrorCode ierr;
93: while (link) {
94: PetscBool sameType;
95: PetscObjectTypeCompare((PetscObject)dm,link->name,&sameType);
96: if (sameType) {
97: *isForest = PETSC_TRUE;
98: return(0);
99: }
100: link = link->next;
101: }
102: *isForest = PETSC_FALSE;
103: return(0);
104: }
106: /*@
107: DMForestTemplate - Create a new DM that will be adapted from a source DM. The new DM reproduces the configuration
108: of the source, but is not yet setup, so that the user can then define only the ways that the new DM should differ
109: (by, e.g., refinement or repartitioning). The source DM is also set as the adaptivity source DM of the new DM (see
110: DMForestSetAdaptivityForest()).
112: Collective on dm
114: Input Parameters:
115: + dm - the source DM object
116: - comm - the communicator for the new DM (this communicator is currently ignored, but is present so that DMForestTemplate() can be used within DMCoarsen())
118: Output Parameter:
119: . tdm - the new DM object
121: Level: intermediate
123: .seealso: DMForestSetAdaptivityForest()
124: @*/
125: PetscErrorCode DMForestTemplate(DM dm, MPI_Comm comm, DM *tdm)
126: {
127: DM_Forest *forest = (DM_Forest*) dm->data;
128: DMType type;
129: DM base;
130: DMForestTopology topology;
131: PetscInt dim, overlap, ref, factor;
132: DMForestAdaptivityStrategy strat;
133: PetscDS ds;
134: void *ctx;
135: PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void*);
136: void *mapCtx;
137: PetscErrorCode ierr;
141: DMCreate(PetscObjectComm((PetscObject)dm),tdm);
142: DMGetType(dm,&type);
143: DMSetType(*tdm,type);
144: DMForestGetBaseDM(dm,&base);
145: DMForestSetBaseDM(*tdm,base);
146: DMForestGetTopology(dm,&topology);
147: DMForestSetTopology(*tdm,topology);
148: DMForestGetAdjacencyDimension(dm,&dim);
149: DMForestSetAdjacencyDimension(*tdm,dim);
150: DMForestGetPartitionOverlap(dm,&overlap);
151: DMForestSetPartitionOverlap(*tdm,overlap);
152: DMForestGetMinimumRefinement(dm,&ref);
153: DMForestSetMinimumRefinement(*tdm,ref);
154: DMForestGetMaximumRefinement(dm,&ref);
155: DMForestSetMaximumRefinement(*tdm,ref);
156: DMForestGetAdaptivityStrategy(dm,&strat);
157: DMForestSetAdaptivityStrategy(*tdm,strat);
158: DMForestGetGradeFactor(dm,&factor);
159: DMForestSetGradeFactor(*tdm,factor);
160: DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx);
161: DMForestSetBaseCoordinateMapping(*tdm,map,mapCtx);
162: if (forest->ftemplate) {
163: (forest->ftemplate)(dm, *tdm);
164: }
165: DMForestSetAdaptivityForest(*tdm,dm);
166: DMGetDS(dm,&ds);
167: DMSetDS(*tdm,ds);
168: DMGetApplicationContext(dm,&ctx);
169: DMSetApplicationContext(*tdm,&ctx);
170: {
171: PetscBool isper;
172: const PetscReal *maxCell, *L;
173: const DMBoundaryType *bd;
175: DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);
176: DMSetPeriodicity(*tdm,isper,maxCell,L,bd);
177: }
178: DMCopyBoundary(dm,*tdm);
179: return(0);
180: }
182: static PetscErrorCode DMInitialize_Forest(DM dm);
184: PETSC_EXTERN PetscErrorCode DMClone_Forest(DM dm, DM *newdm)
185: {
186: DM_Forest *forest = (DM_Forest*) dm->data;
187: const char *type;
191: forest->refct++;
192: (*newdm)->data = forest;
193: PetscObjectGetType((PetscObject) dm, &type);
194: PetscObjectChangeTypeName((PetscObject) *newdm, type);
195: DMInitialize_Forest(*newdm);
196: return(0);
197: }
199: static PetscErrorCode DMDestroy_Forest(DM dm)
200: {
201: DM_Forest *forest = (DM_Forest*) dm->data;
205: if (--forest->refct > 0) return(0);
206: if (forest->destroy) {forest->destroy(dm);}
207: PetscSFDestroy(&forest->cellSF);
208: PetscSFDestroy(&forest->preCoarseToFine);
209: PetscSFDestroy(&forest->coarseToPreFine);
210: DMLabelDestroy(&forest->adaptLabel);
211: PetscFree(forest->adaptStrategy);
212: DMDestroy(&forest->base);
213: DMDestroy(&forest->adapt);
214: PetscFree(forest->topology);
215: PetscFree(forest);
216: return(0);
217: }
219: /*@C
220: DMForestSetTopology - Set the topology of a DMForest during the pre-setup phase. The topology is a string (e.g.
221: "cube", "shell") and can be interpreted by subtypes of DMFOREST) to construct the base DM of a forest during
222: DMSetUp().
224: Logically collective on dm
226: Input parameters:
227: + dm - the forest
228: - topology - the topology of the forest
230: Level: intermediate
232: .seealso(): DMForestGetTopology(), DMForestSetBaseDM()
233: @*/
234: PetscErrorCode DMForestSetTopology(DM dm, DMForestTopology topology)
235: {
236: DM_Forest *forest = (DM_Forest*) dm->data;
241: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the topology after setup");
242: PetscFree(forest->topology);
243: PetscStrallocpy((const char*)topology,(char**) &forest->topology);
244: return(0);
245: }
247: /*@C
248: DMForestGetTopology - Get a string describing the topology of a DMForest.
250: Not collective
252: Input parameter:
253: . dm - the forest
255: Output parameter:
256: . topology - the topology of the forest (e.g., 'cube', 'shell')
258: Level: intermediate
260: .seealso: DMForestSetTopology()
261: @*/
262: PetscErrorCode DMForestGetTopology(DM dm, DMForestTopology *topology)
263: {
264: DM_Forest *forest = (DM_Forest*) dm->data;
269: *topology = forest->topology;
270: return(0);
271: }
273: /*@
274: DMForestSetBaseDM - During the pre-setup phase, set the DM that defines the base mesh of a DMForest forest. The
275: forest will be hierarchically refined from the base, and all refinements/coarsenings of the forest will share its
276: base. In general, two forest must share a base to be comparable, to do things like construct interpolators.
278: Logically collective on dm
280: Input Parameters:
281: + dm - the forest
282: - base - the base DM of the forest
284: Notes: Currently the base DM must be a DMPLEX
286: Level: intermediate
288: .seealso(): DMForestGetBaseDM()
289: @*/
290: PetscErrorCode DMForestSetBaseDM(DM dm, DM base)
291: {
292: DM_Forest *forest = (DM_Forest*) dm->data;
293: PetscInt dim, dimEmbed;
298: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the base after setup");
299: PetscObjectReference((PetscObject)base);
300: DMDestroy(&forest->base);
301: forest->base = base;
302: if (base) {
304: DMGetDimension(base,&dim);
305: DMSetDimension(dm,dim);
306: DMGetCoordinateDim(base,&dimEmbed);
307: DMSetCoordinateDim(dm,dimEmbed);
308: }
309: return(0);
310: }
312: /*@
313: DMForestGetBaseDM - Get the base DM of a DMForest forest. The forest will be hierarchically refined from the base,
314: and all refinements/coarsenings of the forest will share its base. In general, two forest must share a base to be
315: comparable, to do things like construct interpolators.
317: Not collective
319: Input Parameter:
320: . dm - the forest
322: Output Parameter:
323: . base - the base DM of the forest
325: Level: intermediate
327: .seealso(); DMForestSetBaseDM()
328: @*/
329: PetscErrorCode DMForestGetBaseDM(DM dm, DM *base)
330: {
331: DM_Forest *forest = (DM_Forest*) dm->data;
336: *base = forest->base;
337: return(0);
338: }
340: PetscErrorCode DMForestSetBaseCoordinateMapping(DM dm, PetscErrorCode (*func)(DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx)
341: {
342: DM_Forest *forest = (DM_Forest*) dm->data;
346: forest->mapcoordinates = func;
347: forest->mapcoordinatesctx = ctx;
348: return(0);
349: }
351: PetscErrorCode DMForestGetBaseCoordinateMapping(DM dm, PetscErrorCode (**func) (DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx)
352: {
353: DM_Forest *forest = (DM_Forest*) dm->data;
357: if (func) *func = forest->mapcoordinates;
358: if (ctx) *((void**) ctx) = forest->mapcoordinatesctx;
359: return(0);
360: }
362: /*@
363: DMForestSetAdaptivityForest - During the pre-setup phase, set the forest from which the current forest will be
364: adapted (e.g., the current forest will be refined/coarsened/repartitioned from it) im DMSetUp(). Usually not needed
365: by users directly: DMForestTemplate() constructs a new forest to be adapted from an old forest and calls this
366: routine.
368: Note that this can be called after setup with adapt = NULL, which will clear all internal data related to the
369: adaptivity forest from dm. This way, repeatedly adapting does not leave stale DM objects in memory.
371: Logically collective on dm
373: Input Parameter:
374: + dm - the new forest, which will be constructed from adapt
375: - adapt - the old forest
377: Level: intermediate
379: .seealso: DMForestGetAdaptivityForest(), DMForestSetAdaptivityPurpose()
380: @*/
381: PetscErrorCode DMForestSetAdaptivityForest(DM dm,DM adapt)
382: {
383: DM_Forest *forest, *adaptForest, *oldAdaptForest;
384: DM oldAdapt;
385: PetscBool isForest;
391: DMIsForest(dm, &isForest);
392: if (!isForest) return(0);
393: forest = (DM_Forest*) dm->data;
394: DMForestGetAdaptivityForest(dm,&oldAdapt);
395: if (adapt != NULL && dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adaptation forest after setup");
396: adaptForest = (DM_Forest*) (adapt ? adapt->data : NULL);
397: oldAdaptForest = (DM_Forest*) (oldAdapt ? oldAdapt->data : NULL);
398: if (adaptForest != oldAdaptForest) {
399: PetscSFDestroy(&forest->preCoarseToFine);
400: PetscSFDestroy(&forest->coarseToPreFine);
401: if (forest->clearadaptivityforest) {(forest->clearadaptivityforest)(dm);}
402: }
403: switch (forest->adaptPurpose) {
404: case DM_ADAPT_DETERMINE:
405: PetscObjectReference((PetscObject)adapt);
406: DMDestroy(&(forest->adapt));
407: forest->adapt = adapt;
408: break;
409: case DM_ADAPT_REFINE:
410: DMSetCoarseDM(dm,adapt);
411: break;
412: case DM_ADAPT_COARSEN:
413: DMSetFineDM(dm,adapt);
414: break;
415: default:
416: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose");
417: }
418: return(0);
419: }
421: /*@
422: DMForestGetAdaptivityForest - Get the forest from which the current forest is adapted.
424: Not collective
426: Input Parameter:
427: . dm - the forest
429: Output Parameter:
430: . adapt - the forest from which dm is/was adapted
432: Level: intermediate
434: .seealso: DMForestSetAdaptivityForest(), DMForestSetAdaptivityPurpose()
435: @*/
436: PetscErrorCode DMForestGetAdaptivityForest(DM dm, DM *adapt)
437: {
438: DM_Forest *forest;
443: forest = (DM_Forest*) dm->data;
444: switch (forest->adaptPurpose) {
445: case DM_ADAPT_DETERMINE:
446: *adapt = forest->adapt;
447: break;
448: case DM_ADAPT_REFINE:
449: DMGetCoarseDM(dm,adapt);
450: break;
451: case DM_ADAPT_COARSEN:
452: DMGetFineDM(dm,adapt);
453: break;
454: default:
455: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose");
456: }
457: return(0);
458: }
460: /*@
461: DMForestSetAdaptivityPurpose - During the pre-setup phase, set whether the current DM is being adapted from its
462: source (set with DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening
463: (DM_ADAPT_COARSEN), or undefined (DM_ADAPT_DETERMINE). This only matters for the purposes of reference counting:
464: during DMDestroy(), cyclic references can be found between DMs only if the cyclic reference is due to a fine/coarse
465: relationship (see DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does
466: not maintain a reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can
467: cause a memory leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.
469: Logically collective on dm
471: Input Parameters:
472: + dm - the forest
473: - purpose - the adaptivity purpose (DM_ADAPT_DETERMINE/DM_ADAPT_REFINE/DM_ADAPT_COARSEN)
475: Level: advanced
477: .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest()
478: @*/
479: PetscErrorCode DMForestSetAdaptivityPurpose(DM dm, DMAdaptFlag purpose)
480: {
481: DM_Forest *forest;
485: forest = (DM_Forest*) dm->data;
486: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adaptation forest after setup");
487: if (purpose != forest->adaptPurpose) {
488: DM adapt;
490: DMForestGetAdaptivityForest(dm,&adapt);
491: PetscObjectReference((PetscObject)adapt);
492: DMForestSetAdaptivityForest(dm,NULL);
494: forest->adaptPurpose = purpose;
496: DMForestSetAdaptivityForest(dm,adapt);
497: DMDestroy(&adapt);
498: }
499: return(0);
500: }
502: /*@
503: DMForestGetAdaptivityPurpose - Get whether the current DM is being adapted from its source (set with
504: DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening (DM_ADAPT_COARSEN), or
505: undefined (DM_ADAPT_DETERMINE). This only matters for the purposes of reference counting: during DMDestroy(), cyclic
506: references can be found between DMs only if the cyclic reference is due to a fine/coarse relationship (see
507: DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does not maintain a
508: reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can cause a memory
509: leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.
511: Not collective
513: Input Parameter:
514: . dm - the forest
516: Output Parameter:
517: . purpose - the adaptivity purpose (DM_ADAPT_DETERMINE/DM_ADAPT_REFINE/DM_ADAPT_COARSEN)
519: Level: advanced
521: .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest()
522: @*/
523: PetscErrorCode DMForestGetAdaptivityPurpose(DM dm, DMAdaptFlag *purpose)
524: {
525: DM_Forest *forest;
528: forest = (DM_Forest*) dm->data;
529: *purpose = forest->adaptPurpose;
530: return(0);
531: }
533: /*@
534: DMForestSetAdjacencyDimension - During the pre-setup phase, set the dimension of interface points that determine
535: cell adjacency (for the purposes of partitioning and overlap).
537: Logically collective on dm
539: Input Parameters:
540: + dm - the forest
541: - adjDim - default 0 (i.e., vertices determine adjacency)
543: Level: intermediate
545: .seealso: DMForestGetAdjacencyDimension(), DMForestSetAdjacencyCodimension(), DMForestSetPartitionOverlap()
546: @*/
547: PetscErrorCode DMForestSetAdjacencyDimension(DM dm, PetscInt adjDim)
548: {
549: PetscInt dim;
550: DM_Forest *forest = (DM_Forest*) dm->data;
555: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adjacency dimension after setup");
556: if (adjDim < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be < 0: %d", adjDim);
557: DMGetDimension(dm,&dim);
558: if (adjDim > dim) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be > %d: %d", dim, adjDim);
559: forest->adjDim = adjDim;
560: return(0);
561: }
563: /*@
564: DMForestSetAdjacencyCodimension - Like DMForestSetAdjacencyDimension(), but specified as a co-dimension (so that,
565: e.g., adjacency based on facets can be specified by codimension 1 in all cases)
567: Logically collective on dm
569: Input Parameters:
570: + dm - the forest
571: - adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices
573: Level: intermediate
575: .seealso: DMForestGetAdjacencyCodimension(), DMForestSetAdjacencyDimension()
576: @*/
577: PetscErrorCode DMForestSetAdjacencyCodimension(DM dm, PetscInt adjCodim)
578: {
579: PetscInt dim;
584: DMGetDimension(dm,&dim);
585: DMForestSetAdjacencyDimension(dm,dim-adjCodim);
586: return(0);
587: }
589: /*@
590: DMForestGetAdjacencyDimension - Get the dimension of interface points that determine cell adjacency (for the
591: purposes of partitioning and overlap).
593: Not collective
595: Input Parameter:
596: . dm - the forest
598: Output Parameter:
599: . adjDim - default 0 (i.e., vertices determine adjacency)
601: Level: intermediate
603: .seealso: DMForestSetAdjacencyDimension(), DMForestGetAdjacencyCodimension(), DMForestSetPartitionOverlap()
604: @*/
605: PetscErrorCode DMForestGetAdjacencyDimension(DM dm, PetscInt *adjDim)
606: {
607: DM_Forest *forest = (DM_Forest*) dm->data;
612: *adjDim = forest->adjDim;
613: return(0);
614: }
616: /*@
617: DMForestGetAdjacencyCodimension - Like DMForestGetAdjacencyDimension(), but specified as a co-dimension (so that,
618: e.g., adjacency based on facets can be specified by codimension 1 in all cases)
620: Not collective
622: Input Parameter:
623: . dm - the forest
625: Output Parameter:
626: . adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices
628: Level: intermediate
630: .seealso: DMForestSetAdjacencyCodimension(), DMForestGetAdjacencyDimension()
631: @*/
632: PetscErrorCode DMForestGetAdjacencyCodimension(DM dm, PetscInt *adjCodim)
633: {
634: DM_Forest *forest = (DM_Forest*) dm->data;
635: PetscInt dim;
641: DMGetDimension(dm,&dim);
642: *adjCodim = dim - forest->adjDim;
643: return(0);
644: }
646: /*@
647: DMForestSetPartitionOverlap - During the pre-setup phase, set the amount of cell-overlap present in parallel
648: partitions of a forest, with values > 0 indicating subdomains that are expanded by that many iterations of adding
649: adjacent cells
651: Logically collective on dm
653: Input Parameters:
654: + dm - the forest
655: - overlap - default 0
657: Level: intermediate
659: .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension()
660: @*/
661: PetscErrorCode DMForestSetPartitionOverlap(DM dm, PetscInt overlap)
662: {
663: DM_Forest *forest = (DM_Forest*) dm->data;
667: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the overlap after setup");
668: if (overlap < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"overlap cannot be < 0: %d", overlap);
669: forest->overlap = overlap;
670: return(0);
671: }
673: /*@
674: DMForestGetPartitionOverlap - Get the amount of cell-overlap present in parallel partitions of a forest, with values
675: > 0 indicating subdomains that are expanded by that many iterations of adding adjacent cells
677: Not collective
679: Input Parameter:
680: . dm - the forest
682: Output Parameter:
683: . overlap - default 0
685: Level: intermediate
687: .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension()
688: @*/
689: PetscErrorCode DMForestGetPartitionOverlap(DM dm, PetscInt *overlap)
690: {
691: DM_Forest *forest = (DM_Forest*) dm->data;
696: *overlap = forest->overlap;
697: return(0);
698: }
700: /*@
701: DMForestSetMinimumRefinement - During the pre-setup phase, set the minimum level of refinement (relative to the base
702: DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest
703: (see DMForestGetAdaptivityForest()) this limits the amount of coarsening.
705: Logically collective on dm
707: Input Parameters:
708: + dm - the forest
709: - minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
711: Level: intermediate
713: .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
714: @*/
715: PetscErrorCode DMForestSetMinimumRefinement(DM dm, PetscInt minRefinement)
716: {
717: DM_Forest *forest = (DM_Forest*) dm->data;
721: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the minimum refinement after setup");
722: forest->minRefinement = minRefinement;
723: return(0);
724: }
726: /*@
727: DMForestGetMinimumRefinement - Get the minimum level of refinement (relative to the base DM, see
728: DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest (see
729: DMForestGetAdaptivityForest()), this limits the amount of coarsening.
731: Not collective
733: Input Parameter:
734: . dm - the forest
736: Output Parameter:
737: . minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
739: Level: intermediate
741: .seealso: DMForestSetMinimumRefinement(), DMForestGetMaximumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
742: @*/
743: PetscErrorCode DMForestGetMinimumRefinement(DM dm, PetscInt *minRefinement)
744: {
745: DM_Forest *forest = (DM_Forest*) dm->data;
750: *minRefinement = forest->minRefinement;
751: return(0);
752: }
754: /*@
755: DMForestSetInitialRefinement - During the pre-setup phase, set the initial level of refinement (relative to the base
756: DM, see DMForestGetBaseDM()) allowed in the forest.
758: Logically collective on dm
760: Input Parameters:
761: + dm - the forest
762: - initefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
764: Level: intermediate
766: .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM()
767: @*/
768: PetscErrorCode DMForestSetInitialRefinement(DM dm, PetscInt initRefinement)
769: {
770: DM_Forest *forest = (DM_Forest*) dm->data;
774: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the initial refinement after setup");
775: forest->initRefinement = initRefinement;
776: return(0);
777: }
779: /*@
780: DMForestGetInitialRefinement - Get the initial level of refinement (relative to the base DM, see
781: DMForestGetBaseDM()) allowed in the forest.
783: Not collective
785: Input Parameter:
786: . dm - the forest
788: Output Paramater:
789: . initefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
791: Level: intermediate
793: .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM()
794: @*/
795: PetscErrorCode DMForestGetInitialRefinement(DM dm, PetscInt *initRefinement)
796: {
797: DM_Forest *forest = (DM_Forest*) dm->data;
802: *initRefinement = forest->initRefinement;
803: return(0);
804: }
806: /*@
807: DMForestSetMaximumRefinement - During the pre-setup phase, set the maximum level of refinement (relative to the base
808: DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest
809: (see DMForestGetAdaptivityForest()), this limits the amount of refinement.
811: Logically collective on dm
813: Input Parameters:
814: + dm - the forest
815: - maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
817: Level: intermediate
819: .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityDM()
820: @*/
821: PetscErrorCode DMForestSetMaximumRefinement(DM dm, PetscInt maxRefinement)
822: {
823: DM_Forest *forest = (DM_Forest*) dm->data;
827: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the maximum refinement after setup");
828: forest->maxRefinement = maxRefinement;
829: return(0);
830: }
832: /*@
833: DMForestGetMaximumRefinement - Get the maximum level of refinement (relative to the base DM, see
834: DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest (see
835: DMForestGetAdaptivityForest()), this limits the amount of refinement.
837: Not collective
839: Input Parameter:
840: . dm - the forest
842: Output Parameter:
843: . maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
845: Level: intermediate
847: .seealso: DMForestSetMaximumRefinement(), DMForestGetMinimumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
848: @*/
849: PetscErrorCode DMForestGetMaximumRefinement(DM dm, PetscInt *maxRefinement)
850: {
851: DM_Forest *forest = (DM_Forest*) dm->data;
856: *maxRefinement = forest->maxRefinement;
857: return(0);
858: }
860: /*@C
861: DMForestSetAdaptivityStrategy - During the pre-setup phase, set the strategy for combining adaptivity labels from multiple processes.
862: Subtypes of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all processes must agree
863: for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only one process needs to
864: specify refinement/coarsening.
866: Logically collective on dm
868: Input Parameters:
869: + dm - the forest
870: - adaptStrategy - default DMFORESTADAPTALL
872: Level: advanced
874: .seealso: DMForestGetAdaptivityStrategy()
875: @*/
876: PetscErrorCode DMForestSetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy adaptStrategy)
877: {
878: DM_Forest *forest = (DM_Forest*) dm->data;
883: PetscFree(forest->adaptStrategy);
884: PetscStrallocpy((const char*) adaptStrategy,(char**)&forest->adaptStrategy);
885: return(0);
886: }
888: /*@C
889: DMForestSetAdaptivityStrategy - Get the strategy for combining adaptivity labels from multiple processes. Subtypes
890: of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all
891: processes must agree for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only
892: one process needs to specify refinement/coarsening.
894: Not collective
896: Input Parameter:
897: . dm - the forest
899: Output Parameter:
900: . adaptStrategy - the adaptivity strategy (default DMFORESTADAPTALL)
902: Level: advanced
904: .seealso: DMForestSetAdaptivityStrategy()
905: @*/
906: PetscErrorCode DMForestGetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy *adaptStrategy)
907: {
908: DM_Forest *forest = (DM_Forest*) dm->data;
913: *adaptStrategy = forest->adaptStrategy;
914: return(0);
915: }
917: /*@
918: DMForestGetAdaptivitySuccess - Return whether the requested adaptation (refinement, coarsening, repartitioning,
919: etc.) was successful. PETSC_FALSE indicates that the post-adaptation forest is the same as the pre-adpatation
920: forest. A requested adaptation may have been unsuccessful if, for example, the requested refinement would have
921: exceeded the maximum refinement level.
923: Collective on dm
925: Input Parameter:
927: . dm - the post-adaptation forest
929: Output Parameter:
931: . success - PETSC_TRUE if the post-adaptation forest is different from the pre-adaptation forest.
933: Level: intermediate
935: .see
936: @*/
937: PetscErrorCode DMForestGetAdaptivitySuccess(DM dm, PetscBool *success)
938: {
939: DM_Forest *forest;
944: if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"DMSetUp() has not been called yet.");
945: forest = (DM_Forest *) dm->data;
946: (forest->getadaptivitysuccess)(dm,success);
947: return(0);
948: }
950: /*@
951: DMForestSetComputeAdaptivitySF - During the pre-setup phase, set whether transfer PetscSFs should be computed
952: 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().
954: Logically collective on dm
956: Input Parameters:
957: + dm - the post-adaptation forest
958: - computeSF - default PETSC_TRUE
960: Level: advanced
962: .seealso: DMForestGetComputeAdaptivitySF(), DMForestGetAdaptivitySF()
963: @*/
964: PetscErrorCode DMForestSetComputeAdaptivitySF(DM dm, PetscBool computeSF)
965: {
966: DM_Forest *forest;
970: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot compute adaptivity PetscSFs after setup is called");
971: forest = (DM_Forest*) dm->data;
972: forest->computeAdaptSF = computeSF;
973: return(0);
974: }
976: PetscErrorCode DMForestTransferVec(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time)
977: {
978: DM_Forest *forest;
986: forest = (DM_Forest *) dmIn->data;
987: if (!forest->transfervec) SETERRQ(PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"DMForestTransferVec() not implemented");
988: (forest->transfervec)(dmIn,vecIn,dmOut,vecOut,useBCs,time);
989: return(0);
990: }
992: /*@
993: DMForestGetComputeAdaptivitySF - Get whether transfer PetscSFs should be computed relating the cells of the
994: pre-adaptation forest to the post-adaptiation forest. After DMSetUp() is called, these transfer PetscSFs can be
995: accessed with DMForestGetAdaptivitySF().
997: Not collective
999: Input Parameter:
1000: . dm - the post-adaptation forest
1002: Output Parameter:
1003: . computeSF - default PETSC_TRUE
1005: Level: advanced
1007: .seealso: DMForestSetComputeAdaptivitySF(), DMForestGetAdaptivitySF()
1008: @*/
1009: PetscErrorCode DMForestGetComputeAdaptivitySF(DM dm, PetscBool *computeSF)
1010: {
1011: DM_Forest *forest;
1015: forest = (DM_Forest*) dm->data;
1016: *computeSF = forest->computeAdaptSF;
1017: return(0);
1018: }
1020: /*@
1021: DMForestGetAdaptivitySF - Get PetscSFs that relate the pre-adaptation forest to the post-adaptation forest.
1022: Adaptation can be any combination of refinement, coarsening, repartition, and change of overlap, so there may be
1023: some cells of the pre-adaptation that are parents of post-adaptation cells, and vice versa. Therefore there are two
1024: PetscSFs: one that relates pre-adaptation coarse cells to post-adaptation fine cells, and one that relates
1025: pre-adaptation fine cells to post-adaptation coarse cells.
1027: Not collective
1029: Input Parameter:
1030: dm - the post-adaptation forest
1032: Output Parameter:
1033: preCoarseToFine - pre-adaptation coarse cells to post-adaptation fine cells: BCast goes from pre- to post-
1034: coarseToPreFine - post-adaptation coarse cells to pre-adaptation fine cells: BCast goes from post- to pre-
1036: Level: advanced
1038: .seealso: DMForestGetComputeAdaptivitySF(), DMForestSetComputeAdaptivitySF()
1039: @*/
1040: PetscErrorCode DMForestGetAdaptivitySF(DM dm, PetscSF *preCoarseToFine, PetscSF *coarseToPreFine)
1041: {
1042: DM_Forest *forest;
1047: DMSetUp(dm);
1048: forest = (DM_Forest*) dm->data;
1049: if (preCoarseToFine) *preCoarseToFine = forest->preCoarseToFine;
1050: if (coarseToPreFine) *coarseToPreFine = forest->coarseToPreFine;
1051: return(0);
1052: }
1054: /*@
1055: DMForestSetGradeFactor - During the pre-setup phase, set the desired amount of grading in the mesh, e.g. give 2 to
1056: indicate that the diameter of neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may
1057: only support one particular choice of grading factor.
1059: Logically collective on dm
1061: Input Parameters:
1062: + dm - the forest
1063: - grade - the grading factor
1065: Level: advanced
1067: .seealso: DMForestGetGradeFactor()
1068: @*/
1069: PetscErrorCode DMForestSetGradeFactor(DM dm, PetscInt grade)
1070: {
1071: DM_Forest *forest = (DM_Forest*) dm->data;
1075: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the grade factor after setup");
1076: forest->gradeFactor = grade;
1077: return(0);
1078: }
1080: /*@
1081: DMForestGetGradeFactor - Get the desired amount of grading in the mesh, e.g. give 2 to indicate that the diameter of
1082: neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may only support one particular
1083: choice of grading factor.
1085: Not collective
1087: Input Parameter:
1088: . dm - the forest
1090: Output Parameter:
1091: . grade - the grading factor
1093: Level: advanced
1095: .seealso: DMForestSetGradeFactor()
1096: @*/
1097: PetscErrorCode DMForestGetGradeFactor(DM dm, PetscInt *grade)
1098: {
1099: DM_Forest *forest = (DM_Forest*) dm->data;
1104: *grade = forest->gradeFactor;
1105: return(0);
1106: }
1108: /*@
1109: DMForestSetCellWeightFactor - During the pre-setup phase, set the factor by which the level of refinement changes
1110: the cell weight (see DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be
1111: (cellWeight) * (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on
1112: its level; a factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the
1113: computation associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1115: Logically collective on dm
1117: Input Parameters:
1118: + dm - the forest
1119: - weightsFactors - default 1.
1121: Level: advanced
1123: .seealso: DMForestGetCellWeightFactor(), DMForestSetCellWeights()
1124: @*/
1125: PetscErrorCode DMForestSetCellWeightFactor(DM dm, PetscReal weightsFactor)
1126: {
1127: DM_Forest *forest = (DM_Forest*) dm->data;
1131: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weights factor after setup");
1132: forest->weightsFactor = weightsFactor;
1133: return(0);
1134: }
1136: /*@
1137: DMForestGetCellWeightFactor - Get the factor by which the level of refinement changes the cell weight (see
1138: DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be (cellWeight) *
1139: (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on its level; a
1140: factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the computation
1141: associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1143: Not collective
1145: Input Parameter:
1146: . dm - the forest
1148: Output Parameter:
1149: . weightsFactors - default 1.
1151: Level: advanced
1153: .seealso: DMForestSetCellWeightFactor(), DMForestSetCellWeights()
1154: @*/
1155: PetscErrorCode DMForestGetCellWeightFactor(DM dm, PetscReal *weightsFactor)
1156: {
1157: DM_Forest *forest = (DM_Forest*) dm->data;
1162: *weightsFactor = forest->weightsFactor;
1163: return(0);
1164: }
1166: /*@
1167: DMForestGetCellChart - After the setup phase, get the local half-open interval of the chart of cells on this process
1169: Not collective
1171: Input Parameter:
1172: . dm - the forest
1174: Output Parameters:
1175: + cStart - the first cell on this process
1176: - cEnd - one after the final cell on this process
1178: Level: intermediate
1180: .seealso: DMForestGetCellSF()
1181: @*/
1182: PetscErrorCode DMForestGetCellChart(DM dm, PetscInt *cStart, PetscInt *cEnd)
1183: {
1184: DM_Forest *forest = (DM_Forest*) dm->data;
1191: if (((forest->cStart == PETSC_DETERMINE) || (forest->cEnd == PETSC_DETERMINE)) && forest->createcellchart) {
1192: forest->createcellchart(dm,&forest->cStart,&forest->cEnd);
1193: }
1194: *cStart = forest->cStart;
1195: *cEnd = forest->cEnd;
1196: return(0);
1197: }
1199: /*@
1200: DMForestGetCellSF - After the setup phase, get the PetscSF for overlapping cells between processes
1202: Not collective
1204: Input Parameter:
1205: . dm - the forest
1207: Output Parameter:
1208: . cellSF - the PetscSF
1210: Level: intermediate
1212: .seealso: DMForestGetCellChart()
1213: @*/
1214: PetscErrorCode DMForestGetCellSF(DM dm, PetscSF *cellSF)
1215: {
1216: DM_Forest *forest = (DM_Forest*) dm->data;
1222: if ((!forest->cellSF) && forest->createcellsf) {
1223: forest->createcellsf(dm,&forest->cellSF);
1224: }
1225: *cellSF = forest->cellSF;
1226: return(0);
1227: }
1229: /*@C
1230: DMForestSetAdaptivityLabel - During the pre-setup phase, set the label of the pre-adaptation forest (see
1231: DMForestGetAdaptivityForest()) that holds the adaptation flags (refinement, coarsening, or some combination). The
1232: interpretation of the label values is up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP,
1233: DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have been reserved as choices that should be accepted by all subtypes.
1235: Logically collective on dm
1237: Input Parameters:
1238: - dm - the forest
1239: + adaptLabel - the label in the pre-adaptation forest
1241: Level: intermediate
1243: .seealso DMForestGetAdaptivityLabel()
1244: @*/
1245: PetscErrorCode DMForestSetAdaptivityLabel(DM dm, DMLabel adaptLabel)
1246: {
1247: DM_Forest *forest = (DM_Forest*) dm->data;
1252: adaptLabel->refct++;
1253: if (forest->adaptLabel) {DMLabelDestroy(&forest->adaptLabel);}
1254: forest->adaptLabel = adaptLabel;
1255: return(0);
1256: }
1258: /*@C
1259: DMForestGetAdaptivityLabel - Get the label of the pre-adaptation forest (see DMForestGetAdaptivityForest()) that
1260: holds the adaptation flags (refinement, coarsening, or some combination). The interpretation of the label values is
1261: up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have
1262: been reserved as choices that should be accepted by all subtypes.
1264: Not collective
1266: Input Parameter:
1267: . dm - the forest
1269: Output Parameter:
1270: . adaptLabel - the name of the label in the pre-adaptation forest
1272: Level: intermediate
1274: .seealso DMForestSetAdaptivityLabel()
1275: @*/
1276: PetscErrorCode DMForestGetAdaptivityLabel(DM dm, DMLabel *adaptLabel)
1277: {
1278: DM_Forest *forest = (DM_Forest*) dm->data;
1282: *adaptLabel = forest->adaptLabel;
1283: return(0);
1284: }
1286: /*@
1287: DMForestSetCellWeights - Set the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
1288: process: weights are used to determine parallel partitioning. Partitions will be created so that each process's
1289: ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
1290: of 1.
1292: Logically collective on dm
1294: Input Parameters:
1295: + dm - the forest
1296: . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.
1297: - copyMode - how weights should reference weights
1299: Level: advanced
1301: .seealso: DMForestGetCellWeights(), DMForestSetWeightCapacity()
1302: @*/
1303: PetscErrorCode DMForestSetCellWeights(DM dm, PetscReal weights[], PetscCopyMode copyMode)
1304: {
1305: DM_Forest *forest = (DM_Forest*) dm->data;
1306: PetscInt cStart, cEnd;
1311: DMForestGetCellChart(dm,&cStart,&cEnd);
1312: if (cEnd < cStart) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"cell chart [%d,%d) is not valid",cStart,cEnd);
1313: if (copyMode == PETSC_COPY_VALUES) {
1314: if (forest->cellWeightsCopyMode != PETSC_OWN_POINTER || forest->cellWeights == weights) {
1315: PetscMalloc1(cEnd-cStart,&forest->cellWeights);
1316: }
1317: PetscMemcpy(forest->cellWeights,weights,(cEnd-cStart)*sizeof(*weights));
1318: forest->cellWeightsCopyMode = PETSC_OWN_POINTER;
1319: return(0);
1320: }
1321: if (forest->cellWeightsCopyMode == PETSC_OWN_POINTER) {
1322: PetscFree(forest->cellWeights);
1323: }
1324: forest->cellWeights = weights;
1325: forest->cellWeightsCopyMode = copyMode;
1326: return(0);
1327: }
1329: /*@
1330: DMForestGetCellWeights - Get the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
1331: process: weights are used to determine parallel partitioning. Partitions will be created so that each process's
1332: ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
1333: of 1.
1335: Not collective
1337: Input Parameter:
1338: . dm - the forest
1340: Output Parameter:
1341: . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.
1343: Level: advanced
1345: .seealso: DMForestSetCellWeights(), DMForestSetWeightCapacity()
1346: @*/
1347: PetscErrorCode DMForestGetCellWeights(DM dm, PetscReal **weights)
1348: {
1349: DM_Forest *forest = (DM_Forest*) dm->data;
1354: *weights = forest->cellWeights;
1355: return(0);
1356: }
1358: /*@
1359: DMForestSetWeightCapacity - During the pre-setup phase, set the capacity of the current process when repartitioning
1360: a pre-adaptation forest (see DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each
1361: process's cells to the process's capacity will be roughly equal for all processes. A capacity of 0 indicates that
1362: the current process should not have any cells after repartitioning.
1364: Logically Collective on dm
1366: Input parameters:
1367: + dm - the forest
1368: - capacity - this process's capacity
1370: Level: advanced
1372: .seealso DMForestGetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor()
1373: @*/
1374: PetscErrorCode DMForestSetWeightCapacity(DM dm, PetscReal capacity)
1375: {
1376: DM_Forest *forest = (DM_Forest*) dm->data;
1380: if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weight capacity after setup");
1381: if (capacity < 0.) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have negative weight capacity; %f",capacity);
1382: forest->weightCapacity = capacity;
1383: return(0);
1384: }
1386: /*@
1387: DMForestGetWeightCapacity - Set the capacity of the current process when repartitioning a pre-adaptation forest (see
1388: DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each process's cells to the
1389: process's capacity will be roughly equal for all processes. A capacity of 0 indicates that the current process
1390: should not have any cells after repartitioning.
1392: Not collective
1394: Input parameter:
1395: . dm - the forest
1397: Output parameter:
1398: . capacity - this process's capacity
1400: Level: advanced
1402: .seealso DMForestSetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor()
1403: @*/
1404: PetscErrorCode DMForestGetWeightCapacity(DM dm, PetscReal *capacity)
1405: {
1406: DM_Forest *forest = (DM_Forest*) dm->data;
1411: *capacity = forest->weightCapacity;
1412: return(0);
1413: }
1415: PETSC_EXTERN PetscErrorCode DMSetFromOptions_Forest(PetscOptionItems *PetscOptionsObject,DM dm)
1416: {
1417: DM_Forest *forest = (DM_Forest*) dm->data;
1418: PetscBool flg, flg1, flg2, flg3, flg4;
1419: DMForestTopology oldTopo;
1420: char stringBuffer[256];
1421: PetscViewer viewer;
1422: PetscViewerFormat format;
1423: PetscInt adjDim, adjCodim, overlap, minRefinement, initRefinement, maxRefinement, grade;
1424: PetscReal weightsFactor;
1425: DMForestAdaptivityStrategy adaptStrategy;
1426: PetscErrorCode ierr;
1430: forest->setfromoptionscalled = PETSC_TRUE;
1431: DMForestGetTopology(dm, &oldTopo);
1432: PetscOptionsHead(PetscOptionsObject,"DMForest Options");
1433: PetscOptionsString("-dm_forest_topology","the topology of the forest's base mesh","DMForestSetTopology",oldTopo,stringBuffer,256,&flg1);
1434: PetscOptionsViewer("-dm_forest_base_dm","load the base DM from a viewer specification","DMForestSetBaseDM",&viewer,&format,&flg2);
1435: PetscOptionsViewer("-dm_forest_coarse_forest","load the coarse forest from a viewer specification","DMForestSetCoarseForest",&viewer,&format,&flg3);
1436: PetscOptionsViewer("-dm_forest_fine_forest","load the fine forest from a viewer specification","DMForestSetFineForest",&viewer,&format,&flg4);
1437: if ((PetscInt) flg1 + (PetscInt) flg2 + (PetscInt) flg3 + (PetscInt) flg4 > 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Specify only one of -dm_forest_{topology,base_dm,coarse_forest,fine_forest}");
1438: if (flg1) {
1439: DMForestSetTopology(dm,(DMForestTopology)stringBuffer);
1440: DMForestSetBaseDM(dm,NULL);
1441: DMForestSetAdaptivityForest(dm,NULL);
1442: }
1443: if (flg2) {
1444: DM base;
1446: DMCreate(PetscObjectComm((PetscObject)dm),&base);
1447: PetscViewerPushFormat(viewer,format);
1448: DMLoad(base,viewer);
1449: PetscViewerDestroy(&viewer);
1450: DMForestSetBaseDM(dm,base);
1451: DMDestroy(&base);
1452: DMForestSetTopology(dm,NULL);
1453: DMForestSetAdaptivityForest(dm,NULL);
1454: }
1455: if (flg3) {
1456: DM coarse;
1458: DMCreate(PetscObjectComm((PetscObject)dm),&coarse);
1459: PetscViewerPushFormat(viewer,format);
1460: DMLoad(coarse,viewer);
1461: PetscViewerDestroy(&viewer);
1462: DMForestSetAdaptivityForest(dm,coarse);
1463: DMDestroy(&coarse);
1464: DMForestSetTopology(dm,NULL);
1465: DMForestSetBaseDM(dm,NULL);
1466: }
1467: if (flg4) {
1468: DM fine;
1470: DMCreate(PetscObjectComm((PetscObject)dm),&fine);
1471: PetscViewerPushFormat(viewer,format);
1472: DMLoad(fine,viewer);
1473: PetscViewerDestroy(&viewer);
1474: DMForestSetAdaptivityForest(dm,fine);
1475: DMDestroy(&fine);
1476: DMForestSetTopology(dm,NULL);
1477: DMForestSetBaseDM(dm,NULL);
1478: }
1479: DMForestGetAdjacencyDimension(dm,&adjDim);
1480: PetscOptionsInt("-dm_forest_adjacency_dimension","set the dimension of points that define adjacency in the forest","DMForestSetAdjacencyDimension",adjDim,&adjDim,&flg);
1481: if (flg) {
1482: DMForestSetAdjacencyDimension(dm,adjDim);
1483: } else {
1484: DMForestGetAdjacencyCodimension(dm,&adjCodim);
1485: PetscOptionsInt("-dm_forest_adjacency_codimension","set the codimension of points that define adjacency in the forest","DMForestSetAdjacencyCodimension",adjCodim,&adjCodim,&flg);
1486: if (flg) {
1487: DMForestSetAdjacencyCodimension(dm,adjCodim);
1488: }
1489: }
1490: DMForestGetPartitionOverlap(dm,&overlap);
1491: PetscOptionsInt("-dm_forest_partition_overlap","set the degree of partition overlap","DMForestSetPartitionOverlap",overlap,&overlap,&flg);
1492: if (flg) {
1493: DMForestSetPartitionOverlap(dm,overlap);
1494: }
1495: #if 0
1496: PetscOptionsInt("-dm_refine","equivalent to -dm_forest_set_minimum_refinement and -dm_forest_set_initial_refinement with the same value",NULL,minRefinement,&minRefinement,&flg);
1497: if (flg) {
1498: DMForestSetMinimumRefinement(dm,minRefinement);
1499: DMForestSetInitialRefinement(dm,minRefinement);
1500: }
1501: PetscOptionsInt("-dm_refine_hierarchy","equivalent to -dm_forest_set_minimum_refinement 0 and -dm_forest_set_initial_refinement",NULL,initRefinement,&initRefinement,&flg);
1502: if (flg) {
1503: DMForestSetMinimumRefinement(dm,0);
1504: DMForestSetInitialRefinement(dm,initRefinement);
1505: }
1506: #endif
1507: DMForestGetMinimumRefinement(dm,&minRefinement);
1508: PetscOptionsInt("-dm_forest_minimum_refinement","set the minimum level of refinement in the forest","DMForestSetMinimumRefinement",minRefinement,&minRefinement,&flg);
1509: if (flg) {
1510: DMForestSetMinimumRefinement(dm,minRefinement);
1511: }
1512: DMForestGetInitialRefinement(dm,&initRefinement);
1513: PetscOptionsInt("-dm_forest_initial_refinement","set the initial level of refinement in the forest","DMForestSetInitialRefinement",initRefinement,&initRefinement,&flg);
1514: if (flg) {
1515: DMForestSetInitialRefinement(dm,initRefinement);
1516: }
1517: DMForestGetMaximumRefinement(dm,&maxRefinement);
1518: PetscOptionsInt("-dm_forest_maximum_refinement","set the maximum level of refinement in the forest","DMForestSetMaximumRefinement",maxRefinement,&maxRefinement,&flg);
1519: if (flg) {
1520: DMForestSetMaximumRefinement(dm,maxRefinement);
1521: }
1522: DMForestGetAdaptivityStrategy(dm,&adaptStrategy);
1523: PetscOptionsString("-dm_forest_adaptivity_strategy","the forest's adaptivity-flag resolution strategy","DMForestSetAdaptivityStrategy",adaptStrategy,stringBuffer,256,&flg);
1524: if (flg) {
1525: DMForestSetAdaptivityStrategy(dm,(DMForestAdaptivityStrategy)stringBuffer);
1526: }
1527: DMForestGetGradeFactor(dm,&grade);
1528: PetscOptionsInt("-dm_forest_grade_factor","grade factor between neighboring cells","DMForestSetGradeFactor",grade,&grade,&flg);
1529: if (flg) {
1530: DMForestSetGradeFactor(dm,grade);
1531: }
1532: DMForestGetCellWeightFactor(dm,&weightsFactor);
1533: PetscOptionsReal("-dm_forest_cell_weight_factor","multiplying weight factor for cell refinement","DMForestSetCellWeightFactor",weightsFactor,&weightsFactor,&flg);
1534: if (flg) {
1535: DMForestSetCellWeightFactor(dm,weightsFactor);
1536: }
1537: PetscOptionsTail();
1538: return(0);
1539: }
1541: PetscErrorCode DMCreateSubDM_Forest(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1542: {
1546: if (subdm) {DMClone(dm, subdm);}
1547: DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);
1548: return(0);
1549: }
1551: PetscErrorCode DMRefine_Forest(DM dm, MPI_Comm comm, DM *dmRefined)
1552: {
1553: DMLabel refine;
1554: DM fineDM;
1558: DMGetFineDM(dm,&fineDM);
1559: if (fineDM) {
1560: PetscObjectReference((PetscObject)fineDM);
1561: *dmRefined = fineDM;
1562: return(0);
1563: }
1564: DMForestTemplate(dm,comm,dmRefined);
1565: DMGetLabel(dm,"refine",&refine);
1566: if (!refine) {
1567: DMLabelCreate("refine",&refine);
1568: DMLabelSetDefaultValue(refine,DM_ADAPT_REFINE);
1569: }
1570: else {
1571: refine->refct++;
1572: }
1573: DMForestSetAdaptivityLabel(*dmRefined,refine);
1574: DMLabelDestroy(&refine);
1575: return(0);
1576: }
1578: PetscErrorCode DMCoarsen_Forest(DM dm, MPI_Comm comm, DM *dmCoarsened)
1579: {
1580: DMLabel coarsen;
1581: DM coarseDM;
1585: {
1586: PetscMPIInt mpiComparison;
1587: MPI_Comm dmcomm = PetscObjectComm((PetscObject)dm);
1589: MPI_Comm_compare(comm, dmcomm, &mpiComparison);
1590: if (mpiComparison != MPI_IDENT && mpiComparison != MPI_CONGRUENT) SETERRQ(dmcomm,PETSC_ERR_SUP,"No support for different communicators yet");
1591: }
1592: DMGetCoarseDM(dm,&coarseDM);
1593: if (coarseDM) {
1594: PetscObjectReference((PetscObject)coarseDM);
1595: *dmCoarsened = coarseDM;
1596: return(0);
1597: }
1598: DMForestTemplate(dm,comm,dmCoarsened);
1599: DMForestSetAdaptivityPurpose(coarseDM,DM_ADAPT_COARSEN);
1600: DMGetLabel(dm,"coarsen",&coarsen);
1601: if (!coarsen) {
1602: DMLabelCreate("coarsen",&coarsen);
1603: DMLabelSetDefaultValue(coarsen,DM_ADAPT_COARSEN);
1604: } else {
1605: coarsen->refct++;
1606: }
1607: DMForestSetAdaptivityLabel(*dmCoarsened,coarsen);
1608: DMLabelDestroy(&coarsen);
1609: return(0);
1610: }
1612: static PetscErrorCode DMAdaptLabel_Forest(DM dm, DMLabel label, DM *adaptedDM)
1613: {
1614: PetscBool success;
1618: DMForestTemplate(dm,PetscObjectComm((PetscObject)dm),adaptedDM);
1619: DMForestSetAdaptivityLabel(*adaptedDM,label);
1620: DMSetUp(*adaptedDM);
1621: DMForestGetAdaptivitySuccess(*adaptedDM,&success);
1622: if (!success) {
1623: DMDestroy(adaptedDM);
1624: *adaptedDM = NULL;
1625: }
1626: return(0);
1627: }
1629: static PetscErrorCode DMInitialize_Forest(DM dm)
1630: {
1634: PetscMemzero(dm->ops,sizeof(*(dm->ops)));
1636: dm->ops->clone = DMClone_Forest;
1637: dm->ops->setfromoptions = DMSetFromOptions_Forest;
1638: dm->ops->destroy = DMDestroy_Forest;
1639: dm->ops->createsubdm = DMCreateSubDM_Forest;
1640: dm->ops->refine = DMRefine_Forest;
1641: dm->ops->coarsen = DMCoarsen_Forest;
1642: dm->ops->adaptlabel = DMAdaptLabel_Forest;
1643: return(0);
1644: }
1646: /*MC
1648: DMFOREST = "forest" - A DM object that encapsulates a hierarchically refined mesh. Forests usually have a base DM
1649: (see DMForestGetBaseDM()), from which it is refined. The refinement and partitioning of forests is considered
1650: immutable after DMSetUp() is called. To adapt a mesh, one should call DMForestTemplate() to create a new mesh that
1651: will default to being identical to it, specify how that mesh should differ, and then calling DMSetUp() on the new
1652: mesh.
1654: To specify that a mesh should be refined or coarsened from the previous mesh, a label should be defined on the
1655: previous mesh whose values indicate which cells should be refined (DM_ADAPT_REFINE) or coarsened (DM_ADAPT_COARSEN)
1656: and how (subtypes are free to allow additional values for things like anisotropic refinement). The label should be
1657: given to the *new* mesh with DMForestSetAdaptivityLabel().
1659: Level: advanced
1661: .seealso: DMType, DMCreate(), DMSetType(), DMForestGetBaseDM(), DMForestSetBaseDM(), DMForestTemplate(), DMForestSetAdaptivityLabel()
1662: M*/
1664: PETSC_EXTERN PetscErrorCode DMCreate_Forest(DM dm)
1665: {
1666: DM_Forest *forest;
1671: PetscNewLog(dm,&forest);
1672: dm->dim = 0;
1673: dm->data = forest;
1674: forest->refct = 1;
1675: forest->data = NULL;
1676: forest->setfromoptionscalled = PETSC_FALSE;
1677: forest->topology = NULL;
1678: forest->adapt = NULL;
1679: forest->base = NULL;
1680: forest->adaptPurpose = DM_ADAPT_DETERMINE;
1681: forest->adjDim = PETSC_DEFAULT;
1682: forest->overlap = PETSC_DEFAULT;
1683: forest->minRefinement = PETSC_DEFAULT;
1684: forest->maxRefinement = PETSC_DEFAULT;
1685: forest->initRefinement = PETSC_DEFAULT;
1686: forest->cStart = PETSC_DETERMINE;
1687: forest->cEnd = PETSC_DETERMINE;
1688: forest->cellSF = NULL;
1689: forest->adaptLabel = NULL;
1690: forest->gradeFactor = 2;
1691: forest->cellWeights = NULL;
1692: forest->cellWeightsCopyMode = PETSC_USE_POINTER;
1693: forest->weightsFactor = 1.;
1694: forest->weightCapacity = 1.;
1695: DMForestSetAdaptivityStrategy(dm,DMFORESTADAPTALL);
1696: DMInitialize_Forest(dm);
1697: return(0);
1698: }