1c0517cd5SMatthew G. Knepley #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
2c0517cd5SMatthew G. Knepley
3c0517cd5SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMIsForest(DM, PetscBool *);
4c0517cd5SMatthew G. Knepley
5c0517cd5SMatthew G. Knepley DMGeneratorFunctionList DMGenerateList = NULL;
6c0517cd5SMatthew G. Knepley PetscBool DMGenerateRegisterAllCalled = PETSC_FALSE;
7c0517cd5SMatthew G. Knepley
8c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_TRIANGLE)
9c0517cd5SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMPlexGenerate_Triangle(DM, PetscBool, DM *);
1004f3ee44SStefano Zampini PETSC_EXTERN PetscErrorCode DMPlexRefine_Triangle(DM, PetscReal *, DM *);
11c0517cd5SMatthew G. Knepley #endif
12c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_TETGEN)
13c0517cd5SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMPlexGenerate_Tetgen(DM, PetscBool, DM *);
14c0517cd5SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMPlexRefine_Tetgen(DM, double *, DM *);
15c0517cd5SMatthew G. Knepley #endif
16c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_CTETGEN)
17c0517cd5SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMPlexGenerate_CTetgen(DM, PetscBool, DM *);
18c0517cd5SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMPlexRefine_CTetgen(DM, double *, DM *);
19c0517cd5SMatthew G. Knepley #endif
20c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMATIC)
219fe9e680SJoe Wallwork PETSC_EXTERN PetscErrorCode DMAdaptMetric_Pragmatic_Plex(DM, Vec, DMLabel, DMLabel, DM *);
22c0517cd5SMatthew G. Knepley #endif
23c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_MMG)
249fe9e680SJoe Wallwork PETSC_EXTERN PetscErrorCode DMAdaptMetric_Mmg_Plex(DM, Vec, DMLabel, DMLabel, DM *);
25c0517cd5SMatthew G. Knepley #endif
26c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_PARMMG)
279fe9e680SJoe Wallwork PETSC_EXTERN PetscErrorCode DMAdaptMetric_ParMmg_Plex(DM, Vec, DMLabel, DMLabel, DM *);
28c0517cd5SMatthew G. Knepley #endif
299fe9e680SJoe Wallwork PETSC_EXTERN PetscErrorCode DMPlexTransformAdaptLabel(DM, Vec, DMLabel, DMLabel, DM *);
309fe9e680SJoe Wallwork PETSC_EXTERN PetscErrorCode DMAdaptLabel_Forest(DM, Vec, DMLabel, DMLabel, DM *);
31c0517cd5SMatthew G. Knepley
32c0517cd5SMatthew G. Knepley /*@C
3316a05f60SBarry Smith DMGenerateRegisterAll - Registers all of the mesh generation methods in the `DM` package.
34c0517cd5SMatthew G. Knepley
35c0517cd5SMatthew G. Knepley Not Collective
36c0517cd5SMatthew G. Knepley
37c0517cd5SMatthew G. Knepley Level: advanced
38c0517cd5SMatthew G. Knepley
3916a05f60SBarry Smith .seealso: `DM`, `DMGenerateRegisterDestroy()`
40c0517cd5SMatthew G. Knepley @*/
DMGenerateRegisterAll(void)41d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGenerateRegisterAll(void)
42d71ae5a4SJacob Faibussowitsch {
43c0517cd5SMatthew G. Knepley PetscFunctionBegin;
443ba16761SJacob Faibussowitsch if (DMGenerateRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
45c0517cd5SMatthew G. Knepley DMGenerateRegisterAllCalled = PETSC_TRUE;
46c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_TRIANGLE)
479566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("triangle", DMPlexGenerate_Triangle, DMPlexRefine_Triangle, NULL, 1));
48c0517cd5SMatthew G. Knepley #endif
49c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_CTETGEN)
509566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("ctetgen", DMPlexGenerate_CTetgen, DMPlexRefine_CTetgen, NULL, 2));
51c0517cd5SMatthew G. Knepley #endif
52c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_TETGEN)
539566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("tetgen", DMPlexGenerate_Tetgen, DMPlexRefine_Tetgen, NULL, 2));
54c0517cd5SMatthew G. Knepley #endif
55c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMATIC)
569566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("pragmatic", NULL, NULL, DMAdaptMetric_Pragmatic_Plex, -1));
57c0517cd5SMatthew G. Knepley #endif
58c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_MMG)
599566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("mmg", NULL, NULL, DMAdaptMetric_Mmg_Plex, -1));
60c0517cd5SMatthew G. Knepley #endif
61c0517cd5SMatthew G. Knepley #if defined(PETSC_HAVE_PARMMG)
629566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("parmmg", NULL, NULL, DMAdaptMetric_ParMmg_Plex, -1));
63c0517cd5SMatthew G. Knepley #endif
649566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("cellrefiner", NULL, NULL, DMPlexTransformAdaptLabel, -1));
659566063dSJacob Faibussowitsch PetscCall(DMGenerateRegister("forest", NULL, NULL, DMAdaptLabel_Forest, -1));
663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
67c0517cd5SMatthew G. Knepley }
68c0517cd5SMatthew G. Knepley
69c0517cd5SMatthew G. Knepley /*@C
7016a05f60SBarry Smith DMGenerateRegister - Adds a grid generator to `DM`
71c0517cd5SMatthew G. Knepley
72a3b724e8SBarry Smith Not Collective, No Fortran Support
73c0517cd5SMatthew G. Knepley
74c0517cd5SMatthew G. Knepley Input Parameters:
7520f4b53cSBarry Smith + sname - name of a new user-defined grid generator
76c0517cd5SMatthew G. Knepley . fnc - generator function
77c0517cd5SMatthew G. Knepley . rfnc - refinement function
78c0517cd5SMatthew G. Knepley . alfnc - adapt by label function
79c0517cd5SMatthew G. Knepley - dim - dimension of boundary of domain
80c0517cd5SMatthew G. Knepley
8160225df5SJacob Faibussowitsch Example Usage:
82c0517cd5SMatthew G. Knepley .vb
83c0517cd5SMatthew G. Knepley DMGenerateRegister("my_generator", MyGeneratorCreate, MyGeneratorRefiner, MyGeneratorAdaptor, dim);
84c0517cd5SMatthew G. Knepley .ve
85c0517cd5SMatthew G. Knepley
86c0517cd5SMatthew G. Knepley Then, your generator can be chosen with the procedural interface via
87b44f4de4SBarry Smith .vb
88b44f4de4SBarry Smith DMGenerate(dm, "my_generator",...)
89b44f4de4SBarry Smith .ve
90c0517cd5SMatthew G. Knepley or at runtime via the option
91b44f4de4SBarry Smith .vb
92b44f4de4SBarry Smith -dm_generator my_generator
93b44f4de4SBarry Smith .ve
94c0517cd5SMatthew G. Knepley
95c0517cd5SMatthew G. Knepley Level: advanced
96c0517cd5SMatthew G. Knepley
9720f4b53cSBarry Smith Note:
9820f4b53cSBarry Smith `DMGenerateRegister()` may be called multiple times to add several user-defined generators
99c0517cd5SMatthew G. Knepley
10020f4b53cSBarry Smith .seealso: `DM`, `DMGenerateRegisterAll()`, `DMPlexGenerate()`, `DMGenerateRegisterDestroy()`
101c0517cd5SMatthew G. Knepley @*/
DMGenerateRegister(const char sname[],PetscErrorCode (* fnc)(DM,PetscBool,DM *),PetscErrorCode (* rfnc)(DM,PetscReal *,DM *),PetscErrorCode (* alfnc)(DM,Vec,DMLabel,DMLabel,DM *),PetscInt dim)102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGenerateRegister(const char sname[], PetscErrorCode (*fnc)(DM, PetscBool, DM *), PetscErrorCode (*rfnc)(DM, PetscReal *, DM *), PetscErrorCode (*alfnc)(DM, Vec, DMLabel, DMLabel, DM *), PetscInt dim)
103d71ae5a4SJacob Faibussowitsch {
104c0517cd5SMatthew G. Knepley DMGeneratorFunctionList entry;
105c0517cd5SMatthew G. Knepley
106c0517cd5SMatthew G. Knepley PetscFunctionBegin;
1079566063dSJacob Faibussowitsch PetscCall(PetscNew(&entry));
1089566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(sname, &entry->name));
109c0517cd5SMatthew G. Knepley entry->generate = fnc;
110c0517cd5SMatthew G. Knepley entry->refine = rfnc;
111c0517cd5SMatthew G. Knepley entry->adapt = alfnc;
112c0517cd5SMatthew G. Knepley entry->dim = dim;
113c0517cd5SMatthew G. Knepley entry->next = NULL;
114c0517cd5SMatthew G. Knepley if (!DMGenerateList) DMGenerateList = entry;
115c0517cd5SMatthew G. Knepley else {
116c0517cd5SMatthew G. Knepley DMGeneratorFunctionList fl = DMGenerateList;
117c0517cd5SMatthew G. Knepley while (fl->next) fl = fl->next;
118c0517cd5SMatthew G. Knepley fl->next = entry;
119c0517cd5SMatthew G. Knepley }
1203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
121c0517cd5SMatthew G. Knepley }
122c0517cd5SMatthew G. Knepley
DMGenerateRegisterDestroy(void)123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGenerateRegisterDestroy(void)
124d71ae5a4SJacob Faibussowitsch {
125c0517cd5SMatthew G. Knepley DMGeneratorFunctionList next, fl;
126c0517cd5SMatthew G. Knepley
127c0517cd5SMatthew G. Knepley PetscFunctionBegin;
128c0517cd5SMatthew G. Knepley next = fl = DMGenerateList;
129c0517cd5SMatthew G. Knepley while (next) {
130c0517cd5SMatthew G. Knepley next = fl ? fl->next : NULL;
1319566063dSJacob Faibussowitsch if (fl) PetscCall(PetscFree(fl->name));
1329566063dSJacob Faibussowitsch PetscCall(PetscFree(fl));
133c0517cd5SMatthew G. Knepley fl = next;
134c0517cd5SMatthew G. Knepley }
135c0517cd5SMatthew G. Knepley DMGenerateList = NULL;
136c0517cd5SMatthew G. Knepley DMGenerateRegisterAllCalled = PETSC_FALSE;
1373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
138c0517cd5SMatthew G. Knepley }
139c0517cd5SMatthew G. Knepley
1405d83a8b1SBarry Smith /*@
14120f4b53cSBarry Smith DMAdaptLabel - Adapt a `DM` based on a `DMLabel` with values interpreted as coarsening and refining flags. Specific implementations of `DM` maybe have
14220f4b53cSBarry Smith specialized flags, but all implementations should accept flag values `DM_ADAPT_DETERMINE`, `DM_ADAPT_KEEP`, `DM_ADAPT_REFINE`, and,
14320f4b53cSBarry Smith `DM_ADAPT_COARSEN`.
144c0517cd5SMatthew G. Knepley
14520f4b53cSBarry Smith Collective
146c0517cd5SMatthew G. Knepley
14760225df5SJacob Faibussowitsch Input Parameters:
14820f4b53cSBarry Smith + dm - the pre-adaptation `DM` object
149c0517cd5SMatthew G. Knepley - label - label with the flags
150c0517cd5SMatthew G. Knepley
15160225df5SJacob Faibussowitsch Output Parameters:
15220f4b53cSBarry Smith . dmAdapt - the adapted `DM` object: may be `NULL` if an adapted `DM` could not be produced.
153c0517cd5SMatthew G. Knepley
154c0517cd5SMatthew G. Knepley Level: intermediate
155c0517cd5SMatthew G. Knepley
15620f4b53cSBarry Smith .seealso: `DM`, `DMAdaptMetric()`, `DMCoarsen()`, `DMRefine()`
157c0517cd5SMatthew G. Knepley @*/
DMAdaptLabel(DM dm,DMLabel label,DM * dmAdapt)158d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
159d71ae5a4SJacob Faibussowitsch {
160c0517cd5SMatthew G. Knepley DMGeneratorFunctionList fl;
161c0517cd5SMatthew G. Knepley char adaptname[PETSC_MAX_PATH_LEN];
162c0517cd5SMatthew G. Knepley const char *name;
163c0517cd5SMatthew G. Knepley PetscInt dim;
164c0517cd5SMatthew G. Knepley PetscBool flg, isForest, found = PETSC_FALSE;
165c0517cd5SMatthew G. Knepley
166c0517cd5SMatthew G. Knepley PetscFunctionBegin;
167c0517cd5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
168292bffcbSToby Isaac if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
1694f572ea9SToby Isaac PetscAssertPointer(dmAdapt, 3);
170c0517cd5SMatthew G. Knepley *dmAdapt = NULL;
1719566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
1729566063dSJacob Faibussowitsch PetscCall(DMIsForest(dm, &isForest));
173c0517cd5SMatthew G. Knepley name = isForest ? "forest" : "cellrefiner";
1749566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_adaptor", adaptname, sizeof(adaptname), &flg));
175c0517cd5SMatthew G. Knepley if (flg) name = adaptname;
176c0517cd5SMatthew G. Knepley
177c0517cd5SMatthew G. Knepley fl = DMGenerateList;
178c0517cd5SMatthew G. Knepley while (fl) {
1799566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(fl->name, name, &flg));
180c0517cd5SMatthew G. Knepley if (flg) {
1819566063dSJacob Faibussowitsch PetscCall((*fl->adapt)(dm, NULL, label, NULL, dmAdapt));
182c0517cd5SMatthew G. Knepley found = PETSC_TRUE;
183c0517cd5SMatthew G. Knepley }
184c0517cd5SMatthew G. Knepley fl = fl->next;
185c0517cd5SMatthew G. Knepley }
1867a8be351SBarry Smith 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);
187c0517cd5SMatthew G. Knepley if (*dmAdapt) {
188*2a8381b2SBarry Smith PetscCtx ctx;
1893a336bb1SMatthew G. Knepley
190c0517cd5SMatthew G. Knepley (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */
1919566063dSJacob Faibussowitsch PetscCall(PetscFree((*dmAdapt)->vectype));
1929566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*dmAdapt)->vectype));
1939566063dSJacob Faibussowitsch PetscCall(PetscFree((*dmAdapt)->mattype));
1949566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*dmAdapt)->mattype));
1953a336bb1SMatthew G. Knepley PetscCall(DMGetApplicationContext(dm, &ctx));
1963a336bb1SMatthew G. Knepley PetscCall(DMSetApplicationContext(*dmAdapt, ctx));
197c0517cd5SMatthew G. Knepley }
1983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
199c0517cd5SMatthew G. Knepley }
200c0517cd5SMatthew G. Knepley
2015d83a8b1SBarry Smith /*@
202c0517cd5SMatthew G. Knepley DMAdaptMetric - Generates a mesh adapted to the specified metric field.
203c0517cd5SMatthew G. Knepley
204c0517cd5SMatthew G. Knepley Input Parameters:
205c0517cd5SMatthew G. Knepley + dm - The DM object
206c0517cd5SMatthew G. Knepley . metric - The metric to which the mesh is adapted, defined vertex-wise.
207dc9a610eSPierre Jolivet . 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_".
208dc9a610eSPierre Jolivet - 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_".
209c0517cd5SMatthew G. Knepley
210c0517cd5SMatthew G. Knepley Output Parameter:
211a3b724e8SBarry Smith . dmAdapt - Pointer to the `DM` object containing the adapted mesh
212c0517cd5SMatthew G. Knepley
213a4e35b19SJacob Faibussowitsch Note:
214a4e35b19SJacob Faibussowitsch The label in the adapted mesh will be registered under the name of the input `DMLabel` object
215c0517cd5SMatthew G. Knepley
216c0517cd5SMatthew G. Knepley Level: advanced
217c0517cd5SMatthew G. Knepley
218db781477SPatrick Sanan .seealso: `DMAdaptLabel()`, `DMCoarsen()`, `DMRefine()`
219c0517cd5SMatthew G. Knepley @*/
DMAdaptMetric(DM dm,Vec metric,DMLabel bdLabel,DMLabel rgLabel,DM * dmAdapt)220d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DMLabel rgLabel, DM *dmAdapt)
221d71ae5a4SJacob Faibussowitsch {
222c0517cd5SMatthew G. Knepley DMGeneratorFunctionList fl;
223c0517cd5SMatthew G. Knepley char adaptname[PETSC_MAX_PATH_LEN];
22406716a2aSJoe Wallwork const char *name;
22506716a2aSJoe Wallwork const char *const adaptors[3] = {"pragmatic", "mmg", "parmmg"};
226c0517cd5SMatthew G. Knepley PetscInt dim;
227c0517cd5SMatthew G. Knepley PetscBool flg, found = PETSC_FALSE;
228c0517cd5SMatthew G. Knepley
229c0517cd5SMatthew G. Knepley PetscFunctionBegin;
230c0517cd5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
231c0517cd5SMatthew G. Knepley PetscValidHeaderSpecific(metric, VEC_CLASSID, 2);
232292bffcbSToby Isaac if (bdLabel) PetscValidHeaderSpecific(bdLabel, DMLABEL_CLASSID, 3);
233292bffcbSToby Isaac if (rgLabel) PetscValidHeaderSpecific(rgLabel, DMLABEL_CLASSID, 4);
2344f572ea9SToby Isaac PetscAssertPointer(dmAdapt, 5);
235c0517cd5SMatthew G. Knepley *dmAdapt = NULL;
2369566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
2379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_adaptor", adaptname, sizeof(adaptname), &flg));
23806716a2aSJoe Wallwork
23906716a2aSJoe Wallwork /* Default to Mmg in serial and ParMmg in parallel */
240c0517cd5SMatthew G. Knepley if (flg) name = adaptname;
24106716a2aSJoe Wallwork else {
24206716a2aSJoe Wallwork MPI_Comm comm;
24306716a2aSJoe Wallwork PetscMPIInt size;
24406716a2aSJoe Wallwork
2459566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
2469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
24706716a2aSJoe Wallwork if (size == 1) name = adaptors[1];
24806716a2aSJoe Wallwork else name = adaptors[2];
24906716a2aSJoe Wallwork }
250c0517cd5SMatthew G. Knepley
251c0517cd5SMatthew G. Knepley fl = DMGenerateList;
252c0517cd5SMatthew G. Knepley while (fl) {
2539566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(fl->name, name, &flg));
254c0517cd5SMatthew G. Knepley if (flg) {
2559566063dSJacob Faibussowitsch PetscCall((*fl->adapt)(dm, metric, bdLabel, rgLabel, dmAdapt));
256c0517cd5SMatthew G. Knepley found = PETSC_TRUE;
257c0517cd5SMatthew G. Knepley }
258c0517cd5SMatthew G. Knepley fl = fl->next;
259c0517cd5SMatthew G. Knepley }
2607a8be351SBarry Smith 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);
261c0517cd5SMatthew G. Knepley if (*dmAdapt) {
262c0517cd5SMatthew G. Knepley (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */
2639566063dSJacob Faibussowitsch PetscCall(PetscFree((*dmAdapt)->vectype));
2649566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*dmAdapt)->vectype));
2659566063dSJacob Faibussowitsch PetscCall(PetscFree((*dmAdapt)->mattype));
2669566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*dmAdapt)->mattype));
267c0517cd5SMatthew G. Knepley }
2683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
269c0517cd5SMatthew G. Knepley }
270