13#ifndef CD_POLYHEDRALEBUTILSIMPLEM_H
14#define CD_POLYHEDRALEBUTILSIMPLEM_H
24#include <CD_NamespaceHeader.H>
26namespace PolyhedralEB {
45edgeOrigin(
const int a_edge,
int a_offset[SpaceDim])
noexcept
52 for (
int d = 0; d < SpaceDim; d++) {
60 a_offset[1 - dir] = local & 1;
78 for (
int d = 0; d < SpaceDim; d++) {
79 a_lo |= offset[d] << d;
82 a_hi = a_lo | (1 << dir);
90 RealVect x = RealVect::Zero;
92 for (
int d = 0; d < SpaceDim; d++) {
93 x[d] = -0.5 +
static_cast<Real
>((a_corner >> d) & 1);
100faceCorners(
const int a_dir,
const int a_side,
int a_corner[1 << (SpaceDim - 1)]) noexcept
102 CH_assert(a_dir >= 0 && a_dir < SpaceDim);
103 CH_assert(a_side == 0 || a_side == 1);
109 const int ring[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
111 for (
int i = 0; i < 4; i++) {
112 a_corner[i] = (a_side << a_dir) | (ring[i][0] << t0) | (ring[i][1] << t1);
115 const int t = 1 - a_dir;
117 for (
int i = 0; i < 2; i++) {
118 a_corner[i] = (a_side << a_dir) | (i << t);
124edgeIndex(
const int a_dir,
const int a_offset[SpaceDim])
noexcept
126 CH_assert(a_dir >= 0 && a_dir < SpaceDim);
128 for (
int d = 0; d < SpaceDim; d++) {
129 CH_assert(a_offset[d] == 0 || a_offset[d] == 1);
135 return 2 * a_dir + (a_offset[1 - a_dir] & 1);
143 CH_assert(a_surface.hasCrossing(a_edge));
144 CH_assert(a_tolerance >= 0.0 && a_tolerance < 0.5);
148 int offset[SpaceDim];
151 Real t = a_surface.m_crossing[a_edge];
157 if (t != 0.0 && t != 1.0) {
158 t = std::max(t, a_tolerance);
159 t = std::min(t, 1.0 - a_tolerance);
162 RealVect x = RealVect::Zero;
164 for (
int d = 0; d < SpaceDim; d++) {
165 x[d] = -0.5 +
static_cast<Real
>(offset[d]);
175faceEdges(
const int a_dir,
const int a_side,
int a_edge[4])
noexcept
177 CH_assert(a_dir >= 0 && a_dir < SpaceDim);
178 CH_assert(a_side == 0 || a_side == 1);
184 const int spec[4][3] = {{0, 0, t0}, {1, 0, t1}, {1, 1, t0}, {0, 1, t1}};
186 for (
int i = 0; i < 4; i++) {
187 int offset[SpaceDim];
189 for (
int d = 0; d < SpaceDim; d++) {
193 offset[a_dir] = a_side;
194 offset[t0] = spec[i][0];
195 offset[t1] = spec[i][1];
197 const int run = spec[i][2];
210 RealVect& a_centroid)
noexcept
212 CH_assert(a_num >= 0);
213 CH_assert(a_num == 0 || a_vertex !=
nullptr);
216 a_vector = RealVect::Zero;
217 a_centroid = RealVect::Zero;
223 for (
int i = 1; i < a_num - 1; i++) {
224 const RealVect u = a_vertex[i] - a_vertex[0];
225 const RealVect v = a_vertex[i + 1] - a_vertex[0];
227 a_vector += 0.5 * RealVect(u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]);
230 a_area = a_vector.vectorLength();
236 const RealVect unit = a_vector / a_area;
238 for (
int i = 1; i < a_num - 1; i++) {
239 const RealVect u = a_vertex[i] - a_vertex[0];
240 const RealVect v = a_vertex[i + 1] - a_vertex[0];
242 const RealVect n = RealVect(u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]);
244 const Real w = 0.5 * n.dotProduct(unit);
246 a_centroid += w * (a_vertex[0] + a_vertex[i] + a_vertex[i + 1]) / 3.0;
249 a_centroid /= a_area;
255 CH_assert(a_dir >= 0 && a_dir < SpaceDim);
256 CH_assert(a_side == 0 || a_side == 1);
267 for (
int i = 0; i < 4; i++) {
268 if (a_surface.hasCrossing(faceEdge[i])) {
278 a_pair[0][0] = faceEdge[hit[0]];
279 a_pair[0][1] = faceEdge[hit[1]];
288 const Real f00 = a_surface.m_corner[faceCorner[0]];
289 const Real f10 = a_surface.m_corner[faceCorner[1]];
290 const Real f11 = a_surface.m_corner[faceCorner[2]];
291 const Real f01 = a_surface.m_corner[faceCorner[3]];
293 const Real den = f00 + f11 - f10 - f01;
294 const Real saddle = (std::abs(den) > 0.0) ? (f00 * f11 - f10 * f01) / den : (f00 + f11);
297 a_pair[0][0] = faceEdge[0];
298 a_pair[0][1] = faceEdge[1];
299 a_pair[1][0] = faceEdge[2];
300 a_pair[1][1] = faceEdge[3];
303 a_pair[0][0] = faceEdge[3];
304 a_pair[0][1] = faceEdge[0];
305 a_pair[1][0] = faceEdge[1];
306 a_pair[1][1] = faceEdge[2];
319 int adjacent[numEdges][2];
320 int degree[numEdges] = {0};
322 for (
int d = 0; d < SpaceDim; d++) {
323 for (
int side = 0; side < 2; side++) {
325 const int numPairs =
facePairs(d, side, a_surface, pair);
331 for (
int k = 0; k < numPairs; k++) {
332 const int x = pair[k][0];
333 const int y = pair[k][1];
335 if (degree[x] > 1 || degree[y] > 1) {
339 adjacent[x][degree[x]++] = y;
340 adjacent[y][degree[y]++] = x;
345 int numCrossings = 0;
347 for (
int e = 0; e < numEdges; e++) {
351 if (degree[e] != 2) {
357 if (numCrossings < 3) {
361 bool used[numEdges] = {
false};
367 for (
int e = 0; e < numEdges; e++) {
372 const int begin = put;
378 CH_assert(put < numEdges);
380 used[current] =
true;
381 a_loop[put++] = current;
383 const int next = (adjacent[current][0] != previous) ? adjacent[current][0] : adjacent[current][1];
389 if (used[next] || put > numEdges) {
397 if (put - begin < 3) {
401 CH_assert(numLoops < numEdges);
403 a_start[++numLoops] = put;
419#include <CD_NamespaceFooter.H>
Declaration of the cell topology and polygon geometry the polyhedral cut cells are built from.
bool isFluid(const Real a_value) noexcept
Which side of the interface a value lies on.
Definition CD_PolyhedralEBUtilsImplem.H:29
The values a cut cell's embedded boundary is reconstructed from.
Definition CD_CutCellSurface.H:41
bool hasCrossing(const int a_edge) const noexcept
Whether the edge carries a crossing.
Definition CD_CutCellSurfaceImplem.H:37
static constexpr int s_numEdges
Number of cell edges a crossing can sit on.
Definition CD_CutCellSurface.H:46
static constexpr int s_numCorners
Number of cell corners.
Definition CD_CutCellSurface.H:51
void edgeOrigin(const int a_edge, int a_offset[SpaceDim]) noexcept
Corner offsets of a cell edge's low end.
Definition CD_PolyhedralEBUtilsImplem.H:45
void polygonMoments(const RealVect *a_vertex, const int a_num, Real &a_area, RealVect &a_vector, RealVect &a_centroid) noexcept
Area vector, area and centroid of a planar polygon given in circuit order.
Definition CD_PolyhedralEBUtilsImplem.H:206
constexpr int s_transverse[3][2]
The two directions transverse to each coordinate direction, in increasing order.
Definition CD_PolyhedralEBUtils.H:59
void faceEdges(const int a_dir, const int a_side, int a_edge[4]) noexcept
The edges of a cell face, edge i joining face corners i and i+1.
Definition CD_PolyhedralEBUtilsImplem.H:175
int facePairs(const int a_dir, const int a_side, const CutCellSurface &a_surface, int a_pair[2][2]) noexcept
The chords on a cell face, each an unordered pair of edge indices.
Definition CD_PolyhedralEBUtilsImplem.H:253
bool sameVertex(const RealVect &a_a, const RealVect &a_b) noexcept
Whether two positions are the same vertex.
Definition CD_PolyhedralEBUtilsImplem.H:411
RealVect cornerPosition(const int a_corner) noexcept
Position of a cell corner in the cell's own frame.
Definition CD_PolyhedralEBUtilsImplem.H:86
constexpr Real s_weldTolerance
Distance within which two vertices are taken to be the same one.
Definition CD_PolyhedralEBUtils.H:210
int edgeDirection(const int a_edge) noexcept
Direction a cell edge runs along.
Definition CD_PolyhedralEBUtilsImplem.H:37
void edgeCorners(const int a_edge, int &a_lo, int &a_hi) noexcept
The corners a cell edge joins, low end first.
Definition CD_PolyhedralEBUtilsImplem.H:67
void faceCorners(const int a_dir, const int a_side, int a_corner[1<<(SpaceDim - 1)]) noexcept
The corners of a cell face, in circuit order around the face.
Definition CD_PolyhedralEBUtilsImplem.H:100
int edgeIndex(const int a_dir, const int a_offset[SpaceDim]) noexcept
Index of the edge running along a_dir whose low corner has the given offsets.
Definition CD_PolyhedralEBUtilsImplem.H:124
RealVect crossingPosition(const CutCellSurface &a_surface, const int a_edge, const Real a_tolerance) noexcept
Position of an edge crossing in the cell's own frame.
Definition CD_PolyhedralEBUtilsImplem.H:140
int crossingLoops(const CutCellSurface &a_surface, int a_loop[CutCellSurface::s_numEdges], int a_start[CutCellSurface::s_numEdges+1]) noexcept
Order the crossings into closed loops, or fail if they do not form clean cycles.
Definition CD_PolyhedralEBUtilsImplem.H:313