Triangle Grouping and Regrouping¶
Before pressures can be reduced to force, moment or shape coefficients, the mesh triangles have to be partitioned into meaningful groups – one group per body, per facade, per floor, per zoning cell. cfdmod treats grouping as a first-class, composable step, and provides two disk-level companions that act on the result: regroup (rewrite a mesh + its timeseries around a new grouping) and remesh (coarsen a grouped mesh).
The Python surface is documented in the API reference (grouping, regroup and remesh sections); this page explains when to reach for which.
The grouping model¶
A grouping pipeline partitions or selects the triangles of a parent
LnasFormat mesh into named groups. Specs are Pydantic models in a
discriminated union (GroupingSpec), composed left-to-right
with apply_groupings(), and a triangle may belong to zero, one,
or many groups. Each spec carries a restrict_to field so a later step can
scope its work to triangles already placed by an earlier one – this is how a
surface -> sub-body nesting is reproduced.
The built-in kinds fall into a few intents:
By named geometry –
BySurfaceGroupingcollects named LNAS surfaces into groups.By a regular grid –
ByZoningGroupingbins centroids into a Cartesian grid;ByDivisionsGrouping(n cells per axis) andBySizeGrouping(fixed cell size) are convenience wrappers over it.By orientation / geometry –
ByNormalGrouping(windward / leeward / roof / sidewall by outward normal),ByPlaneGrouping(signed distance from an oriented plane),ByCylindricalGrouping(r, theta, axial bins – towers, silos, chimneys).By connectivity –
ByConnectivityGroupingputs each shared-edge connected component in its own group (one physical body per component, no axis projection).By statistics –
ByPercentileGroupingmakes equal-count quantile bins along an axis, for stable per-cell statistics when triangle density is uneven.Escape hatch –
CustomGroupingruns a user callback when none of the built-ins express the partition.
The force / moment / shape recipes are built on this abstraction: the
body_grouping / zoning_grouping / connectivity_grouping ops attach
a grouping to a SurfaceDataSource, and per-group series are
aggregated onto a GroupsDataSource.
Regroup: a new mesh + aligned series¶
run_regroup() (module cfdmod.regroup, runnable as
python -m cfdmod.regroup) takes a geometry plus a per-triangle HDF5
timeseries (Cp-style: rows are timesteps, columns are parent triangle ids),
applies a chain of grouping specs, and writes two aligned outputs:
a new
LnasFormatmesh with one named surface per group, anda new HDF5 timeseries whose columns line up with the new triangle order (
per_triangle) or whose values are area-weighted per-group aggregates broadcast over each group’s triangles (area_weighted_mean).
Reach for regroup when a downstream tool needs the grouping baked into the
mesh on disk (one surface per region) rather than applied on the fly – for
example to hand a regrouped, per-facade mesh to ParaView or to a separate
coefficient run. It adds one regroup-local spec,
BySizeRoundedPerComponent, that fans out per-component
target-size subdivisions.
Remesh: coarsen a grouped mesh¶
remesh_per_group() (module cfdmod.remesh) coarsens a grouped
LnasFormat – typically regroup output, where a group holds many triangles
from sliced cuts. Two paths:
Exact coplanar-fan collapse (default) – within each group, adjacent coplanar triangles are replaced by the minimum triangulation of their joined region. Lossless, deterministic, numpy-only: a flat NxN-subdivided square collapses to 2 triangles, a curved patch is left unchanged.
QEM decimation (
decimate_qem()) – opt-in Quadric Error Metrics decimation via theremeshextra, for curved groups where coplanar merge cannot reduce the count further.
Use remesh to shrink a mesh for faster rendering or downstream I/O once the grouping is fixed; keep the default coplanar path unless a group is curved.
See also
The grouping, regroup and remesh API sections in
API Reference, and the Cf / Cm / Ce recipes in
Pressure that consume groupings directly.