xref: /petsc/src/dm/interface/dmgeommodel.c (revision a02648fdf9ec0d41d7b5ca02cb70ddcfa0e65728)
1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
2 
3 PetscFunctionList DMGeomModelList              = NULL;
4 PetscBool         DMGeomModelRegisterAllCalled = PETSC_FALSE;
5 
6 #if defined(PETSC_HAVE_EGADS)
7 PETSC_INTERN PetscErrorCode DMSnapToGeomModel_EGADS(DM, PetscInt, PetscInt, const PetscScalar[], PetscScalar[]);
8 #endif
9 
10 static PetscErrorCode DMSnapToGeomModelBall(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[])
11 {
12   PetscInt val;
13 
14   PetscFunctionBeginUser;
15   PetscCall(DMGetLabelValue(dm, "marker", p, &val));
16   if (val >= 0) {
17     PetscReal norm = 0.;
18 
19     for (PetscInt d = 0; d < dE; ++d) norm += PetscSqr(PetscRealPart(mcoords[d]));
20     norm = PetscSqrtReal(norm);
21     for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d] / norm;
22   } else {
23     for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
24   }
25   PetscFunctionReturn(PETSC_SUCCESS);
26 }
27 
28 static PetscErrorCode DMSnapToGeomModelCylinder(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[])
29 {
30   PetscReal gmin[3], gmax[3];
31   PetscInt  val;
32 
33   PetscFunctionBeginUser;
34   PetscCall(DMGetBoundingBox(dm, gmin, gmax));
35   PetscCall(DMGetLabelValue(dm, "generatrix", p, &val));
36   if (val >= 0) {
37     PetscReal norm = 0.;
38 
39     for (PetscInt d = 0; d < dE - 1; ++d) norm += PetscSqr(PetscRealPart(mcoords[d]));
40     norm = PetscSqrtReal(norm);
41     for (PetscInt d = 0; d < dE - 1; ++d) gcoords[d] = mcoords[d] * gmax[0] / norm;
42     gcoords[dE - 1] = mcoords[dE - 1];
43   } else {
44     for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
45   }
46   PetscFunctionReturn(PETSC_SUCCESS);
47 }
48 
49 /*@C
50   DMGeomModelRegisterAll - Registers all of the geometry model methods in the `DM` package.
51 
52   Not Collective
53 
54   Level: advanced
55 
56 .seealso: `DM`, `DMGeomModelRegisterDestroy()`
57 @*/
58 PetscErrorCode DMGeomModelRegisterAll(void)
59 {
60   PetscFunctionBegin;
61   if (DMGeomModelRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
62   DMGeomModelRegisterAllCalled = PETSC_TRUE;
63   PetscCall(DMGeomModelRegister("ball", DMSnapToGeomModelBall));
64   PetscCall(DMGeomModelRegister("cylinder", DMSnapToGeomModelCylinder));
65 #if defined(PETSC_HAVE_EGADS)
66   // FIXME: Brandon uses DMPlexSnapToGeomModel() here instead
67   PetscCall(DMGeomModelRegister("egads", DMSnapToGeomModel_EGADS));
68 #endif
69   PetscFunctionReturn(PETSC_SUCCESS);
70 }
71 
72 /*@C
73   DMGeomModelRegister -  Adds a geometry model to `DM`
74 
75   Not Collective, No Fortran Support
76 
77   Input Parameters:
78 + sname - name of a new user-defined geometry model
79 - fnc   - geometry model function
80 
81   Example Usage:
82 .vb
83    DMGeomModelRegister("my_geom_model", MySnapToGeomModel);
84 .ve
85 
86   Then, your generator can be chosen with the procedural interface via
87 $     DMSetGeomModel(dm, "my_geom_model",...)
88   or at runtime via the option
89 $     -dm_geom_model my_geom_model
90 
91   Level: advanced
92 
93   Note:
94   `DMGeomModelRegister()` may be called multiple times to add several user-defined generators
95 
96 .seealso: `DM`, `DMGeomModelRegisterAll()`, `DMPlexGeomModel()`, `DMGeomModelRegisterDestroy()`
97 @*/
98 PetscErrorCode DMGeomModelRegister(const char sname[], PetscErrorCode (*fnc)(DM, PetscInt, PetscInt, const PetscScalar[], PetscScalar[]))
99 {
100   PetscFunctionBegin;
101   PetscCall(PetscFunctionListAdd(&DMGeomModelList, sname, fnc));
102   PetscFunctionReturn(PETSC_SUCCESS);
103 }
104 
105 PetscErrorCode DMGeomModelRegisterDestroy(void)
106 {
107   PetscFunctionBegin;
108   PetscCall(PetscFunctionListDestroy(&DMGeomModelList));
109   DMGeomModelRegisterAllCalled = PETSC_FALSE;
110   PetscFunctionReturn(PETSC_SUCCESS);
111 }
112 
113 /*@
114   DMSetSnapToGeomModel - Choose a geometry model for this `DM`.
115 
116   Not Collective
117 
118   Input Parameters:
119 + dm   - The `DM` object
120 - name - A geometry model name, or `NULL` for the default
121 
122   Level: intermediate
123 
124 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexCreate()`, `DMSnapToGeomModel()`
125 @*/
126 PetscErrorCode DMSetSnapToGeomModel(DM dm, const char name[])
127 {
128   char      geomname[PETSC_MAX_PATH_LEN];
129   PetscBool flg;
130 
131   PetscFunctionBegin;
132   if (!name && dm->ops->snaptogeommodel) PetscFunctionReturn(PETSC_SUCCESS);
133   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_geom_model", geomname, sizeof(geomname), &flg));
134   if (flg) name = geomname;
135   if (!name) {
136     PetscObject modelObj;
137 
138     PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj));
139     if (modelObj) name = "egads";
140     else {
141       PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", &modelObj));
142       if (modelObj) name = "egads";
143     }
144   }
145   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
146 
147   PetscCall(PetscFunctionListFind(DMGeomModelList, name, &dm->ops->snaptogeommodel));
148   PetscCheck(dm->ops->snaptogeommodel, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Geometry model %s not registered; you may need to add --download-%s to your ./configure options", name, name);
149   PetscFunctionReturn(PETSC_SUCCESS);
150 }
151 
152 /*@
153   DMSnapToGeomModel - Given a coordinate point 'mcoords' on the mesh point 'p', return the closest coordinate point 'gcoords' on the geometry model associated with that point.
154 
155   Not Collective
156 
157   Input Parameters:
158 + dm      - The `DMPLEX` object
159 . p       - The mesh point
160 . dE      - The coordinate dimension
161 - mcoords - A coordinate point lying on the mesh point
162 
163   Output Parameter:
164 . gcoords - The closest coordinate point on the geometry model associated with 'p' to the given point
165 
166   Level: intermediate
167 
168   Note:
169   Returns the original coordinates if no geometry model is found.
170 
171   The coordinate dimension may be different from the coordinate dimension of the `dm`, for example if the transformation is extrusion.
172 
173 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexCreate()`, `DMPlexSetRefinementUniform()`
174 @*/
175 PetscErrorCode DMSnapToGeomModel(DM dm, PetscInt p, PetscInt dE, const PetscScalar mcoords[], PetscScalar gcoords[])
176 {
177   PetscFunctionBegin;
178   if (!dm->ops->snaptogeommodel)
179     for (PetscInt d = 0; d < dE; ++d) gcoords[d] = mcoords[d];
180   else PetscUseTypeMethod(dm, snaptogeommodel, p, dE, mcoords, gcoords);
181   PetscFunctionReturn(PETSC_SUCCESS);
182 }
183