Actual source code: plexreftosimplex.c

  1: #include <petsc/private/dmplextransformimpl.h>

  3: static PetscErrorCode DMPlexTransformView_ToSimplex(DMPlexTransform tr, PetscViewer viewer)
  4: {
  5:   PetscBool isascii;

  7:   PetscFunctionBegin;
 10:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
 11:   if (isascii) {
 12:     const char *name;

 14:     PetscCall(PetscObjectGetName((PetscObject)tr, &name));
 15:     PetscCall(PetscViewerASCIIPrintf(viewer, "ToSimplex refinement %s\n", name ? name : ""));
 16:   } else {
 17:     SETERRQ(PetscObjectComm((PetscObject)tr), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlexTransform writing", ((PetscObject)viewer)->type_name);
 18:   }
 19:   PetscFunctionReturn(PETSC_SUCCESS);
 20: }

 22: static PetscErrorCode DMPlexTransformDestroy_ToSimplex(DMPlexTransform tr)
 23: {
 24:   DMPlexRefine_ToSimplex *f = (DMPlexRefine_ToSimplex *)tr->data;

 26:   PetscFunctionBegin;
 27:   PetscCall(PetscFree(f));
 28:   PetscFunctionReturn(PETSC_SUCCESS);
 29: }

 31: static PetscErrorCode DMPlexTransformGetSubcellOrientation_ToSimplex(DMPlexTransform tr, DMPolytopeType sct, PetscInt sp, PetscInt so, DMPolytopeType tct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
 32: {
 33:   DM              dm;
 34:   PetscInt        dim;
 35:   PetscBool       reflect;
 36:   PetscInt       *quad_tri;
 37:   static PetscInt quad_seg[] = {
 38:     0, -1, /* o = -4 */
 39:     0, -1, /* o = -3 */
 40:     0, -1, /* o = -2 */
 41:     0, -1, /* o = -1 */
 42:     0, 0,  /* o = 0 */
 43:     0, 0,  /* o = 1 */
 44:     0, 0,  /* o = 2 */
 45:     0, 0,  /* o = 3 */
 46:   };
 47:   // TODO: I don't know how to map the subcells into each other because the
 48:   // symmetry isn't there, this is a total guess
 49:   static PetscInt quad_tri_noreflect[] = {
 50:     0, -4, 1, -4, /* o = -4 */
 51:     0, -3, 1, -3, /* o = -3 */
 52:     1, -2, 0, -2, /* o = -2 */
 53:     1, -1, 0, -1, /* o = -1 */
 54:     0, 0,  1, 0,  /* o = 0 */
 55:     1, 1,  0, 1,  /* o = 1 */
 56:     1, 2,  0, 2,  /* o = 2 */
 57:     0, 3,  1, 3,  /* o = 3 */
 58:   };
 59:   static PetscInt quad_tri_reflect[] = {
 60:     0, -4, 1, -4, /* o = -4 */
 61:     1, -3, 0, -3, /* o = -3 */
 62:     1, -2, 1, -2, /* o = -2 */
 63:     0, -1, 1, -1, /* o = -1 */
 64:     0, 0,  1, 0,  /* o = 0 */
 65:     0, 1,  1, 1,  /* o = 1 */
 66:     1, 2,  0, 2,  /* o = 2 */
 67:     1, 3,  0, 3,  /* o = 3 */
 68:   };

 70:   PetscFunctionBeginHot;
 71:   *rnew = r;
 72:   *onew = o;
 73:   if (!so) PetscFunctionReturn(PETSC_SUCCESS);
 74:   PetscCall(DMPlexRefineToSimplexGetReflect(tr, &reflect));
 75:   if (reflect) quad_tri = quad_tri_reflect;
 76:   else quad_tri = quad_tri_noreflect;
 77:   PetscCall(DMPlexTransformGetDM(tr, &dm));
 78:   PetscCall(DMGetDimension(dm, &dim));
 79:   if (dim == 2 && sct == DM_POLYTOPE_QUADRILATERAL) {
 80:     switch (tct) {
 81:     case DM_POLYTOPE_POINT:
 82:       break;
 83:     case DM_POLYTOPE_SEGMENT:
 84:       *rnew = quad_seg[(so + 4) * 8 + r * 2];
 85:       *onew = DMPolytopeTypeComposeOrientation(tct, o, quad_seg[(so + 4) * 8 + r * 2 + 1]);
 86:       break;
 87:     case DM_POLYTOPE_TRIANGLE:
 88:       *rnew = quad_tri[(so + 4) * 8 + r * 2];
 89:       *onew = DMPolytopeTypeComposeOrientation(tct, o, quad_tri[(so + 4) * 8 + r * 2 + 1]);
 90:       break;
 91:     default:
 92:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s is not produced by %s", DMPolytopeTypes[tct], DMPolytopeTypes[sct]);
 93:     }
 94:   } else {
 95:     PetscCall(DMPlexTransformGetSubcellOrientationIdentity(tr, sct, sp, so, tct, r, o, rnew, onew));
 96:   }
 97:   PetscFunctionReturn(PETSC_SUCCESS);
 98: }

100: static PetscErrorCode DMPlexTransformCellRefine_ToSimplex(DMPlexTransform tr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
101: {
102:   DM        dm;
103:   PetscInt  dim;
104:   PetscBool reflect;
105:   PetscInt *quadC, *quadO;
106:   /* Add 1 edge inside every quad, making 2 new triangles.
107:    3---2---2       +-------+      +-------+
108:    |       |       |      /|      |\      |
109:    |       |       |  1  / |      | \  1  |
110:    |       |       |    /  |      |  \    |
111:    3       1  -->  |   0   |  or  |   0   |
112:    |       |       |  /    |      |    \  |
113:    |       |       | /  0  |      |  0  \ |
114:    |       |       |/      |      |      \|
115:    0---0---1       +-------+      +-------+
116:   */
117:   static DMPolytopeType quadT[]           = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
118:   static PetscInt       quadS[]           = {1, 2};
119:   static PetscInt       quadC_noreflect[] = {/* Cone of edge 0, rising left to right */
120:                                              DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 0, 0,
121:                                              /* Cone of cell 0, anticlockwise from the new edge */
122:                                              DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0,
123:                                              /* Cone of cell 1, anticlockwise from the new edge */
124:                                              DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0};
125:   static PetscInt       quadC_reflect[]   = {/* Cone of edge 0, rising right to left */
126:                                              DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 2, 3, 0, 0,
127:                                              /* Cone of cell 0, anticlockwise from the new edge */
128:                                              DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0,
129:                                              /* Cone of cell 1, anticlockwise from the new edge */
130:                                              DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0};
131:   static PetscInt       quadO_noreflect[] = {
132:     0,  0,    /* Cone of edge 0 */
133:     -1, 0, 0, /* Cone of cell 0 */
134:     0,  0, 0, /* Cone of cell 1 */
135:   };
136:   static PetscInt quadO_reflect[] = {
137:     0,  0,    /* Cone of edge 0 */
138:     0,  0, 0, /* Cone of cell 0 */
139:     -1, 0, 0, /* Cone of cell 1 */
140:   };

142:   PetscFunctionBeginHot;
143:   if (rt) *rt = 0;
144:   PetscCall(DMPlexRefineToSimplexGetReflect(tr, &reflect));
145:   if (reflect) {
146:     quadC = quadC_reflect;
147:     quadO = quadO_reflect;
148:   } else {
149:     quadC = quadC_noreflect;
150:     quadO = quadO_noreflect;
151:   }
152:   PetscCall(DMPlexTransformGetDM(tr, &dm));
153:   PetscCall(DMGetDimension(dm, &dim));
154:   if (dim == 2 && source == DM_POLYTOPE_QUADRILATERAL) {
155:     *Nt     = 2;
156:     *target = quadT;
157:     *size   = quadS;
158:     *cone   = quadC;
159:     *ornt   = quadO;
160:   } else {
161:     PetscCall(DMPlexTransformCellTransformIdentity(tr, source, p, rt, Nt, target, size, cone, ornt));
162:   }
163:   PetscFunctionReturn(PETSC_SUCCESS);
164: }

166: static PetscErrorCode DMPlexTransformSetFromOptions_ToSimplex(DMPlexTransform tr, PetscOptionItems PetscOptionsObject)
167: {
168:   DMPlexRefine_ToSimplex *ts = (DMPlexRefine_ToSimplex *)tr->data;
169:   PetscBool               reflect, flg;

171:   PetscFunctionBegin;
172:   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlexRefine ToSimplex Options");
173:   PetscCall(PetscOptionsBool("-dm_plex_transform_tosimplex_reflect", "Reflect the transformation", "", ts->reflect, &reflect, &flg));
174:   if (flg) PetscCall(DMPlexRefineToSimplexSetReflect(tr, reflect));
175:   PetscOptionsHeadEnd();
176:   PetscFunctionReturn(PETSC_SUCCESS);
177: }

179: /*@
180:   DMPlexRefineToSimplexGetReflect - Get the flag to reflect the transform

182:   Not Collective

184:   Input Parameter:
185: . tr - The `DMPlexTransform`

187:   Output Parameter:
188: . reflect - Whether to reflect the transform

190:   Level: intermediate

192: .seealso: `DMPlexTransform`, `DMPlexRefineToSimplexSetReflect()`
193: @*/
194: PetscErrorCode DMPlexRefineToSimplexGetReflect(DMPlexTransform tr, PetscBool *reflect)
195: {
196:   DMPlexRefine_ToSimplex *ts = (DMPlexRefine_ToSimplex *)tr->data;

198:   PetscFunctionBegin;
200:   PetscAssertPointer(reflect, 2);
201:   *reflect = ts->reflect;
202:   PetscFunctionReturn(PETSC_SUCCESS);
203: }

205: /*@
206:   DMPlexRefineToSimplexSetReflect - Set the flag to reflect the transform

208:   Not Collective

210:   Input Parameters:
211: + tr      - The `DMPlexTransform`
212: - reflect - Whether to reflect the transform

214:   Level: intermediate

216: .seealso: `DMPlexTransform`, `DMPlexRefineToSimplexGetReflect()`
217: @*/
218: PetscErrorCode DMPlexRefineToSimplexSetReflect(DMPlexTransform tr, PetscBool reflect)
219: {
220:   DMPlexRefine_ToSimplex *ts = (DMPlexRefine_ToSimplex *)tr->data;

222:   PetscFunctionBegin;
224:   ts->reflect = reflect;
225:   PetscFunctionReturn(PETSC_SUCCESS);
226: }

228: static PetscErrorCode DMPlexTransformInitialize_ToSimplex(DMPlexTransform tr)
229: {
230:   PetscFunctionBegin;
231:   tr->ops->view                  = DMPlexTransformView_ToSimplex;
232:   tr->ops->setfromoptions        = DMPlexTransformSetFromOptions_ToSimplex;
233:   tr->ops->destroy               = DMPlexTransformDestroy_ToSimplex;
234:   tr->ops->setdimensions         = DMPlexTransformSetDimensions_Internal;
235:   tr->ops->celltransform         = DMPlexTransformCellRefine_ToSimplex;
236:   tr->ops->getsubcellorientation = DMPlexTransformGetSubcellOrientation_ToSimplex;
237:   tr->ops->mapcoordinates        = DMPlexTransformMapCoordinatesBarycenter_Internal;
238:   PetscFunctionReturn(PETSC_SUCCESS);
239: }

241: PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_ToSimplex(DMPlexTransform tr)
242: {
243:   DMPlexRefine_ToSimplex *ts;

245:   PetscFunctionBegin;
247:   PetscCall(PetscNew(&ts));
248:   tr->redFactor = 1.0;
249:   tr->data      = ts;
250:   ts->reflect   = PETSC_FALSE;
251:   PetscCall(DMPlexTransformInitialize_ToSimplex(tr));
252:   PetscFunctionReturn(PETSC_SUCCESS);
253: }