Actual source code: dmgenerate.c
1: #include <petsc/private/dmimpl.h>
3: PETSC_EXTERN PetscErrorCode DMIsForest(DM, PetscBool *);
5: DMGeneratorFunctionList DMGenerateList = NULL;
6: PetscBool DMGenerateRegisterAllCalled = PETSC_FALSE;
8: #if defined(PETSC_HAVE_TRIANGLE)
9: PETSC_EXTERN PetscErrorCode DMPlexGenerate_Triangle(DM, PetscBool, DM *);
10: PETSC_EXTERN PetscErrorCode DMPlexRefine_Triangle(DM, PetscReal *, DM *);
11: #endif
12: #if defined(PETSC_HAVE_TETGEN)
13: PETSC_EXTERN PetscErrorCode DMPlexGenerate_Tetgen(DM, PetscBool, DM *);
14: PETSC_EXTERN PetscErrorCode DMPlexRefine_Tetgen(DM, double *, DM *);
15: #endif
16: #if defined(PETSC_HAVE_CTETGEN)
17: PETSC_EXTERN PetscErrorCode DMPlexGenerate_CTetgen(DM, PetscBool, DM *);
18: PETSC_EXTERN PetscErrorCode DMPlexRefine_CTetgen(DM, double *, DM *);
19: #endif
20: #if defined(PETSC_HAVE_PRAGMATIC)
21: PETSC_EXTERN PetscErrorCode DMAdaptMetric_Pragmatic_Plex(DM, Vec, DMLabel, DMLabel, DM *);
22: #endif
23: #if defined(PETSC_HAVE_MMG)
24: PETSC_EXTERN PetscErrorCode DMAdaptMetric_Mmg_Plex(DM, Vec, DMLabel, DMLabel, DM *);
25: #endif
26: #if defined(PETSC_HAVE_PARMMG)
27: PETSC_EXTERN PetscErrorCode DMAdaptMetric_ParMmg_Plex(DM, Vec, DMLabel, DMLabel, DM *);
28: #endif
29: PETSC_EXTERN PetscErrorCode DMPlexTransformAdaptLabel(DM, Vec, DMLabel, DMLabel, DM *);
30: PETSC_EXTERN PetscErrorCode DMAdaptLabel_Forest(DM, Vec, DMLabel, DMLabel, DM *);
32: /*@C
33: DMGenerateRegisterAll - Registers all of the mesh generation methods in the `DM` package.
35: Not Collective
37: Level: advanced
39: .seealso: `DM`, `DMGenerateRegisterDestroy()`
40: @*/
41: PetscErrorCode DMGenerateRegisterAll(void)
42: {
43: PetscFunctionBegin;
44: if (DMGenerateRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
45: DMGenerateRegisterAllCalled = PETSC_TRUE;
46: #if defined(PETSC_HAVE_TRIANGLE)
47: PetscCall(DMGenerateRegister("triangle", DMPlexGenerate_Triangle, DMPlexRefine_Triangle, NULL, 1));
48: #endif
49: #if defined(PETSC_HAVE_CTETGEN)
50: PetscCall(DMGenerateRegister("ctetgen", DMPlexGenerate_CTetgen, DMPlexRefine_CTetgen, NULL, 2));
51: #endif
52: #if defined(PETSC_HAVE_TETGEN)
53: PetscCall(DMGenerateRegister("tetgen", DMPlexGenerate_Tetgen, DMPlexRefine_Tetgen, NULL, 2));
54: #endif
55: #if defined(PETSC_HAVE_PRAGMATIC)
56: PetscCall(DMGenerateRegister("pragmatic", NULL, NULL, DMAdaptMetric_Pragmatic_Plex, -1));
57: #endif
58: #if defined(PETSC_HAVE_MMG)
59: PetscCall(DMGenerateRegister("mmg", NULL, NULL, DMAdaptMetric_Mmg_Plex, -1));
60: #endif
61: #if defined(PETSC_HAVE_PARMMG)
62: PetscCall(DMGenerateRegister("parmmg", NULL, NULL, DMAdaptMetric_ParMmg_Plex, -1));
63: #endif
64: PetscCall(DMGenerateRegister("cellrefiner", NULL, NULL, DMPlexTransformAdaptLabel, -1));
65: PetscCall(DMGenerateRegister("forest", NULL, NULL, DMAdaptLabel_Forest, -1));
66: PetscFunctionReturn(PETSC_SUCCESS);
67: }
69: /*@C
70: DMGenerateRegister - Adds a grid generator to `DM`
72: Not Collective, No Fortran Support
74: Input Parameters:
75: + sname - name of a new user-defined grid generator
76: . fnc - generator function
77: . rfnc - refinement function
78: . alfnc - adapt by label function
79: - dim - dimension of boundary of domain
81: Example Usage:
82: .vb
83: DMGenerateRegister("my_generator", MyGeneratorCreate, MyGeneratorRefiner, MyGeneratorAdaptor, dim);
84: .ve
86: Then, your generator can be chosen with the procedural interface via
87: .vb
88: DMGenerate(dm, "my_generator",...)
89: .ve
90: or at runtime via the option
91: .vb
92: -dm_generator my_generator
93: .ve
95: Level: advanced
97: Note:
98: `DMGenerateRegister()` may be called multiple times to add several user-defined generators
100: .seealso: `DM`, `DMGenerateRegisterAll()`, `DMPlexGenerate()`, `DMGenerateRegisterDestroy()`
101: @*/
102: PetscErrorCode DMGenerateRegister(const char sname[], PetscErrorCode (*fnc)(DM, PetscBool, DM *), PetscErrorCode (*rfnc)(DM, PetscReal *, DM *), PetscErrorCode (*alfnc)(DM, Vec, DMLabel, DMLabel, DM *), PetscInt dim)
103: {
104: DMGeneratorFunctionList entry;
106: PetscFunctionBegin;
107: PetscCall(PetscNew(&entry));
108: PetscCall(PetscStrallocpy(sname, &entry->name));
109: entry->generate = fnc;
110: entry->refine = rfnc;
111: entry->adapt = alfnc;
112: entry->dim = dim;
113: entry->next = NULL;
114: if (!DMGenerateList) DMGenerateList = entry;
115: else {
116: DMGeneratorFunctionList fl = DMGenerateList;
117: while (fl->next) fl = fl->next;
118: fl->next = entry;
119: }
120: PetscFunctionReturn(PETSC_SUCCESS);
121: }
123: /*@
124: DMGenerateRegisterDestroy - Frees the list of `DM` mesh generators that were registered by `DMGenerateRegister()` or `DMGenerateRegisterAll()`.
126: Not Collective
128: Level: advanced
130: .seealso: `DM`, `DMGenerateRegister()`, `DMGenerateRegisterAll()`
131: @*/
132: PetscErrorCode DMGenerateRegisterDestroy(void)
133: {
134: DMGeneratorFunctionList next, fl;
136: PetscFunctionBegin;
137: next = fl = DMGenerateList;
138: while (next) {
139: next = fl ? fl->next : NULL;
140: if (fl) PetscCall(PetscFree(fl->name));
141: PetscCall(PetscFree(fl));
142: fl = next;
143: }
144: DMGenerateList = NULL;
145: DMGenerateRegisterAllCalled = PETSC_FALSE;
146: PetscFunctionReturn(PETSC_SUCCESS);
147: }
149: /*@
150: DMAdaptLabel - Adapt a `DM` based on a `DMLabel` with values interpreted as coarsening and refining flags. Specific implementations of `DM` maybe have
151: specialized flags, but all implementations should accept flag values `DM_ADAPT_DETERMINE`, `DM_ADAPT_KEEP`, `DM_ADAPT_REFINE`, and,
152: `DM_ADAPT_COARSEN`.
154: Collective
156: Input Parameters:
157: + dm - the pre-adaptation `DM` object
158: - label - label with the flags
160: Output Parameters:
161: . dmAdapt - the adapted `DM` object: may be `NULL` if an adapted `DM` could not be produced.
163: Level: intermediate
165: .seealso: `DM`, `DMAdaptMetric()`, `DMCoarsen()`, `DMRefine()`
166: @*/
167: PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
168: {
169: DMGeneratorFunctionList fl;
170: char adaptname[PETSC_MAX_PATH_LEN];
171: const char *name;
172: PetscInt dim;
173: PetscBool flg, isForest, found = PETSC_FALSE;
175: PetscFunctionBegin;
178: PetscAssertPointer(dmAdapt, 3);
179: *dmAdapt = NULL;
180: PetscCall(DMGetDimension(dm, &dim));
181: PetscCall(DMIsForest(dm, &isForest));
182: name = isForest ? "forest" : "cellrefiner";
183: PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_adaptor", adaptname, sizeof(adaptname), &flg));
184: if (flg) name = adaptname;
186: fl = DMGenerateList;
187: while (fl) {
188: PetscCall(PetscStrcmp(fl->name, name, &flg));
189: if (flg) {
190: PetscCall((*fl->adapt)(dm, NULL, label, NULL, dmAdapt));
191: found = PETSC_TRUE;
192: }
193: fl = fl->next;
194: }
195: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Grid adaptor %s not registered; you may need to add --download-%s to your ./configure options", name, name);
196: if (*dmAdapt) {
197: PetscCtx ctx;
199: (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */
200: PetscCall(PetscFree((*dmAdapt)->vectype));
201: PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*dmAdapt)->vectype));
202: PetscCall(PetscFree((*dmAdapt)->mattype));
203: PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*dmAdapt)->mattype));
204: PetscCall(DMGetApplicationContext(dm, &ctx));
205: PetscCall(DMSetApplicationContext(*dmAdapt, ctx));
206: }
207: PetscFunctionReturn(PETSC_SUCCESS);
208: }
210: /*@
211: DMAdaptMetric - Generates a mesh adapted to the specified metric field.
213: Input Parameters:
214: + dm - The DM object
215: . metric - The metric to which the mesh is adapted, defined vertex-wise.
216: . bdLabel - Label for boundary tags, which will be preserved in the output mesh. `bdLabel` should be `NULL` if there is no such label, and should be different from "_boundary_".
217: - rgLabel - Label for cell tags, which will be preserved in the output mesh. `rgLabel` should be `NULL` if there is no such label, and should be different from "_regions_".
219: Output Parameter:
220: . dmAdapt - Pointer to the `DM` object containing the adapted mesh
222: Note:
223: The label in the adapted mesh will be registered under the name of the input `DMLabel` object
225: Level: advanced
227: .seealso: `DMAdaptLabel()`, `DMCoarsen()`, `DMRefine()`
228: @*/
229: PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DMLabel rgLabel, DM *dmAdapt)
230: {
231: DMGeneratorFunctionList fl;
232: char adaptname[PETSC_MAX_PATH_LEN];
233: const char *name;
234: const char *const adaptors[3] = {"pragmatic", "mmg", "parmmg"};
235: PetscInt dim;
236: PetscBool flg, found = PETSC_FALSE;
238: PetscFunctionBegin;
243: PetscAssertPointer(dmAdapt, 5);
244: *dmAdapt = NULL;
245: PetscCall(DMGetDimension(dm, &dim));
246: PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_adaptor", adaptname, sizeof(adaptname), &flg));
248: /* Default to Mmg in serial and ParMmg in parallel */
249: if (flg) name = adaptname;
250: else {
251: MPI_Comm comm;
252: PetscMPIInt size;
254: PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
255: PetscCallMPI(MPI_Comm_size(comm, &size));
256: if (size == 1) name = adaptors[1];
257: else name = adaptors[2];
258: }
260: fl = DMGenerateList;
261: while (fl) {
262: PetscCall(PetscStrcmp(fl->name, name, &flg));
263: if (flg) {
264: PetscCall((*fl->adapt)(dm, metric, bdLabel, rgLabel, dmAdapt));
265: found = PETSC_TRUE;
266: }
267: fl = fl->next;
268: }
269: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Grid adaptor %s not registered; you may need to add --download-%s to your ./configure options", name, name);
270: if (*dmAdapt) {
271: (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */
272: PetscCall(PetscFree((*dmAdapt)->vectype));
273: PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*dmAdapt)->vectype));
274: PetscCall(PetscFree((*dmAdapt)->mattype));
275: PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*dmAdapt)->mattype));
276: }
277: PetscFunctionReturn(PETSC_SUCCESS);
278: }