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, double*, 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: DMGenerateRegisterDestroy()
40: @*/
41: PetscErrorCode DMGenerateRegisterAll(void)
42: {
43: if (DMGenerateRegisterAllCalled) return 0;
44: DMGenerateRegisterAllCalled = PETSC_TRUE;
45: #if defined(PETSC_HAVE_TRIANGLE)
46: DMGenerateRegister("triangle",DMPlexGenerate_Triangle,DMPlexRefine_Triangle,NULL,1);
47: #endif
48: #if defined(PETSC_HAVE_CTETGEN)
49: DMGenerateRegister("ctetgen",DMPlexGenerate_CTetgen,DMPlexRefine_CTetgen,NULL,2);
50: #endif
51: #if defined(PETSC_HAVE_TETGEN)
52: DMGenerateRegister("tetgen",DMPlexGenerate_Tetgen,DMPlexRefine_Tetgen,NULL,2);
53: #endif
54: #if defined(PETSC_HAVE_PRAGMATIC)
55: DMGenerateRegister("pragmatic",NULL,NULL,DMAdaptMetric_Pragmatic_Plex,-1);
56: #endif
57: #if defined(PETSC_HAVE_MMG)
58: DMGenerateRegister("mmg",NULL,NULL,DMAdaptMetric_Mmg_Plex,-1);
59: #endif
60: #if defined(PETSC_HAVE_PARMMG)
61: DMGenerateRegister("parmmg",NULL,NULL,DMAdaptMetric_ParMmg_Plex,-1);
62: #endif
63: DMGenerateRegister("cellrefiner",NULL,NULL,DMPlexTransformAdaptLabel,-1);
64: DMGenerateRegister("forest",NULL,NULL,DMAdaptLabel_Forest,-1);
65: return 0;
66: }
68: /*@C
69: DMGenerateRegister - Adds a grid generator to DM
71: Not Collective
73: Input Parameters:
74: + name_solver - name of a new user-defined grid generator
75: . fnc - generator function
76: . rfnc - refinement function
77: . alfnc - adapt by label function
78: - dim - dimension of boundary of domain
80: Notes:
81: DMGenerateRegister() may be called multiple times to add several user-defined solvers.
83: Sample usage:
84: .vb
85: DMGenerateRegister("my_generator",MyGeneratorCreate,MyGeneratorRefiner,MyGeneratorAdaptor,dim);
86: .ve
88: Then, your generator can be chosen with the procedural interface via
89: $ DMGenerate(dm,"my_generator",...)
90: or at runtime via the option
91: $ -dm_generator my_generator
93: Level: advanced
95: .seealso: DMGenerateRegisterAll(), DMPlexGenerate(), DMGenerateRegisterDestroy()
97: @*/
98: PetscErrorCode DMGenerateRegister(const char sname[], PetscErrorCode (*fnc)(DM, PetscBool, DM*), PetscErrorCode (*rfnc)(DM, PetscReal*, DM*), PetscErrorCode (*alfnc)(DM, Vec, DMLabel, DMLabel, DM*), PetscInt dim)
99: {
100: DMGeneratorFunctionList entry;
102: PetscNew(&entry);
103: PetscStrallocpy(sname,&entry->name);
104: entry->generate = fnc;
105: entry->refine = rfnc;
106: entry->adapt = alfnc;
107: entry->dim = dim;
108: entry->next = NULL;
109: if (!DMGenerateList) DMGenerateList = entry;
110: else {
111: DMGeneratorFunctionList fl = DMGenerateList;
112: while (fl->next) fl = fl->next;
113: fl->next = entry;
114: }
115: return 0;
116: }
118: extern PetscBool DMGenerateRegisterAllCalled;
120: PetscErrorCode DMGenerateRegisterDestroy(void)
121: {
122: DMGeneratorFunctionList next, fl;
124: next = fl = DMGenerateList;
125: while (next) {
126: next = fl ? fl->next : NULL;
127: if (fl) PetscFree(fl->name);
128: PetscFree(fl);
129: fl = next;
130: }
131: DMGenerateList = NULL;
132: DMGenerateRegisterAllCalled = PETSC_FALSE;
133: return 0;
134: }
136: /*@C
137: DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have
138: specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN.
140: Collective on dm
142: Input parameters:
143: + dm - the pre-adaptation DM object
144: - label - label with the flags
146: Output parameters:
147: . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced.
149: Level: intermediate
151: .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine()
152: @*/
153: PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt)
154: {
155: DMGeneratorFunctionList fl;
156: char adaptname[PETSC_MAX_PATH_LEN];
157: const char *name;
158: PetscInt dim;
159: PetscBool flg, isForest, found = PETSC_FALSE;
164: *dmAdapt = NULL;
165: DMGetDimension(dm, &dim);
166: DMIsForest(dm, &isForest);
167: name = isForest ? "forest" : "cellrefiner";
168: PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_adaptor", adaptname, sizeof(adaptname), &flg);
169: if (flg) name = adaptname;
171: fl = DMGenerateList;
172: while (fl) {
173: PetscStrcmp(fl->name, name, &flg);
174: if (flg) {
175: (*fl->adapt)(dm, NULL, label, NULL, dmAdapt);
176: found = PETSC_TRUE;
177: }
178: fl = fl->next;
179: }
181: if (*dmAdapt) {
182: (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */
183: PetscFree((*dmAdapt)->vectype);
184: PetscStrallocpy(dm->vectype,(char**)&(*dmAdapt)->vectype);
185: PetscFree((*dmAdapt)->mattype);
186: PetscStrallocpy(dm->mattype,(char**)&(*dmAdapt)->mattype);
187: }
188: return 0;
189: }
191: /*@C
192: DMAdaptMetric - Generates a mesh adapted to the specified metric field.
194: Input Parameters:
195: + dm - The DM object
196: . metric - The metric to which the mesh is adapted, defined vertex-wise.
197: . 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_".
198: - 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_".
200: Output Parameter:
201: . dmAdapt - Pointer to the DM object containing the adapted mesh
203: Note: The label in the adapted mesh will be registered under the name of the input DMLabel object
205: Level: advanced
207: .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine()
208: @*/
209: PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DMLabel rgLabel, DM *dmAdapt)
210: {
211: DMGeneratorFunctionList fl;
212: char adaptname[PETSC_MAX_PATH_LEN];
213: const char *name;
214: const char * const adaptors[3] = {"pragmatic", "mmg", "parmmg"};
215: PetscInt dim;
216: PetscBool flg, found = PETSC_FALSE;
223: *dmAdapt = NULL;
224: DMGetDimension(dm, &dim);
225: PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_adaptor", adaptname, sizeof(adaptname), &flg);
227: /* Default to Mmg in serial and ParMmg in parallel */
228: if (flg) name = adaptname;
229: else {
230: MPI_Comm comm;
231: PetscMPIInt size;
233: PetscObjectGetComm((PetscObject)dm, &comm);
234: MPI_Comm_size(comm, &size);
235: if (size == 1) name = adaptors[1];
236: else name = adaptors[2];
237: }
239: fl = DMGenerateList;
240: while (fl) {
241: PetscStrcmp(fl->name, name, &flg);
242: if (flg) {
243: (*fl->adapt)(dm, metric, bdLabel, rgLabel, dmAdapt);
244: found = PETSC_TRUE;
245: }
246: fl = fl->next;
247: }
249: if (*dmAdapt) {
250: (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */
251: PetscFree((*dmAdapt)->vectype);
252: PetscStrallocpy(dm->vectype,(char**)&(*dmAdapt)->vectype);
253: PetscFree((*dmAdapt)->mattype);
254: PetscStrallocpy(dm->mattype,(char**)&(*dmAdapt)->mattype);
255: }
256: return 0;
257: }