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