EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
Public Member Functions | Friends | List of all members
EBGeometry::DCEL::ReconcileSchedule Class Reference

Which faces touch each vertex of a mesh, checked and stored once, for DCEL::reconcile(). More...

#include <EBGeometry_DCEL_Reconcile.hpp>

Public Member Functions

template<class T >
 ReconcileSchedule (Pool &a_pool, const MeshT< T > &a_mesh)
 Check the topology of a_mesh and store which faces touch each vertex.
 

Friends

template<class T >
void reconcile (Pool &a_pool, const MeshT< T > &a_mesh, const ReconcileSchedule &a_schedule)
 DCEL::reconcile() reads the arrays.
 

Detailed Description

Which faces touch each vertex of a mesh, checked and stored once, for DCEL::reconcile().

Opt-in: only a mesh that is reconciled with DCEL::reconcile() needs one. Build it on the host after the mesh is built and before its pool is frozen: its arrays are reserved from the mesh's pool, so a mirror of the pool carries them along, and one schedule serves the mesh in its own pool and in every mirror of it. Moving vertices never changes which faces touch a vertex, so a schedule is built once; a mesh whose vertices, half-edges or faces are added, removed or relinked needs a new one. The schedule belongs to the mesh in that pool and its mirrors: a deepCopy() of the mesh into another pool needs its own schedule, and the pool must outlive the schedule as it does the mesh.

The constructor checks the topology as MeshT::reconcile() does, with its messages (every face has a half-edge, its loop closes, has at least three vertices, names existing vertices and visits each of them once), so that DCEL::reconcile() has only the geometry left to check.

Per vertex, the schedule stores where its corners start (4 bytes), and per face corner, the face and the two vertices next to the corner (12 bytes), in the order MeshT::reconcile() visits them: a vertex's faces in face order, and the neighbors in the order a walk of the face's loop from its half-edge finds them. Storing the neighbors spares the vertex pass a walk of every face's loop: without them (4 bytes per corner instead of 12) the pass measured 2.6 to 4 times slower in float and 10-20% slower in double on a device (100,000 and 250,000 faces, RTX 3080). The schedule also holds one status word, which the vertex pass sets on coincident positions.

Constructor & Destructor Documentation

◆ ReconcileSchedule()

template<class T >
EBGeometry::DCEL::ReconcileSchedule::ReconcileSchedule ( Pool &  a_pool,
const MeshT< T > &  a_mesh 
)

Check the topology of a_mesh and store which faces touch each vertex.

Aborts, in every build, if a_mesh does not live in a_pool, the pool is frozen, or the topology check fails.

Template Parameters
TFloating-point precision.
Parameters
[in,out]a_poolThe pool a_mesh lives in, which the schedule's arrays are reserved from. It must not be frozen.
[in]a_meshThe mesh, on the host.

Friends And Related Symbol Documentation

◆ reconcile

template<class T >
void reconcile ( Pool &  a_pool,
const MeshT< T > &  a_mesh,
const ReconcileSchedule &  a_schedule 
)
friend

DCEL::reconcile() reads the arrays.

For vertices that move without changing the mesh's topology. Runs where a_pool's memory is, in three passes, one per face, per half-edge and per vertex: on a device-accessible pool, each pass is one GPU::parallelFor() (device kernels in a CUDA or HIP build, host loops over emulated device memory in a host build); on a host pool, each is a host loop. a_pool is the mesh's own pool or any mirror of it.

In host memory the result is MeshT::reconcile()'s, byte for byte. On a device it agrees to rounding: device compilers fuse multiplies and adds by default, and the device's std::acos differs from the host's in the last bits.

How the vertices were moved is the caller's business (any kernel, any library, a copy from the host), as long as that work has finished: the passes run on the default stream, and reconcile() returns once they are done. One reconcile at a time per schedule and pool: the passes share the schedule's status word in that pool, so two reconciles of the same pool's mesh running at once (from two host threads, say) would race on it. A mesh SDF over the mesh also needs its BVH refitted (BVH::refit()) before it is queried again.

Aborts, in every build, on a schedule built in a pool of another mirror chain or for another mesh, and on the geometry MeshT::reconcile() aborts on, with its message: a vertex and its two neighbors on a face (of non-zero area) with coincident positions. The status word the vertex pass sets is read back after the passes (4 bytes from a device), and only when it is set is the vertex found on the host (in place when the host can read the pool, in a host mirror otherwise). With several such vertices, the message names the first in vertex order, as MeshT::reconcile() does, whatever order the device's threads found them in.

Template Parameters
TFloating-point precision.
Parameters
[in,out]a_poolThe pool whose copy of the mesh is reconciled: the mesh's own pool or a mirror.
[in]a_meshThe mesh, as built (a handle to its own pool).
[in]a_scheduleThe schedule built for a_mesh.

The documentation for this class was generated from the following file: