dragonfly_sim.core.shape_parameterization
Wall-shape parameterization built on lsdo_geo.
Maps shape design variables to the motion of the mesh wall nodes, and measures the deformed wall for geometric constraints. Three pieces:
WallFFD– anlsdo_geo.FFDBlockaround the wall nodes. Its output,wall_displacement(C), is the replicated(M_global, dim)array thatIDWarp_jax.evaluateconsumes.Shape layers that produce the block’s coefficients
C:SectionalShape(lsdo_geoSectionalParameterization: camber/thickness per chordwise station in 2D; twist/chord/sweep/dihedral/span per spanwise section in 3D) andWallFFD.apply_cp_motions(raw control-point motions). Compose them asC = apply_cp_motions(SectionalShape.apply(C0), cp_motions)– seeSectionalShapefor why the sectional layer must act on the constant baseline.WallGeometry– geometric constraint quantities of the deformed wall: enclosed area (2D) / volume (3D), thickness at stations, and 3D planform (section chords, span, planform area).
Everything here is csdl_alpha graph code on replicated arrays, so derivatives come from csdl’s autodiff and every rank computes identical values.
Classes
Sectional shape variables on a WallFFD, via lsdo_geo's SectionalParameterization. |
|
lsdo_geo FFD block embedding the mesh wall nodes. |
|
Geometric constraint quantities of the FFD-deformed wall. |
Functions
|
|
|
Axis-aligned FFD block corners around coords, widened by margin*extent. |
|
FFD block corners lofted between two rectangular end surfaces. |
|
Check and return the optimized control-point directions as an int array. |
Module Contents
- class dragonfly_sim.core.shape_parameterization.SectionalShape(ffd, principal_dim=0)
Sectional shape variables on a WallFFD, via lsdo_geo’s SectionalParameterization.
The block is seen as a stack of sections normal to
principal_dim: in 2D use principal_dim = 0 (chordwise stations, each a vertical column of control points); for a wing, the spanwise parametric direction. Each variable holds either one value per section, or – when it has fewer entries – the coefficients of a B-spline profile over the sections.The sectional layer must act on the constant baseline coefficients. lsdo_geo takes stretch and translation axes, and stretch origins, from the points’ values when the graph is built, so feeding it DV-dependent points would bake the initial DV values into the map. Add raw control-point motions afterwards (
WallFFD.apply_cp_motions).Named presets (
add), with lsdo_geo’s conventions: a stretch is the additive change in section extent along the axis (linear across the section, zero at the pivot); a rotation is in radians about the axis through the pivot; a translation is a length.kind
operation
dims
camber
translation along the vertical axis
2D
thickness
stretch along the vertical param. axis
2D, 3D
twist
rotation about the principal axis
3D
chord
stretch along parametric axis 0
3D
sweep
translation along x
3D
dihedral
translation along z
3D
span
translation along y
3D
- _check_size(values)
- _per_section(values, profile_degree=2)
- _section_pivot(pivot)
- add(kind, values, pivot=None, profile_degree=2)
Add a named sectional variable; see the class docstring.
- add_rotation(values, parametric_axis=None, pivot=None, profile_degree=2)
- add_stretch(values, parametric_axis, pivot=None, profile_degree=2)
- add_translation(values, direction, profile_degree=2)
- apply(coefficients)
Sectionally deformed coefficients. Pass
ffd.baseline_variable().
- _specs = []
- dim
- ffd
- num_sections
- principal_dim = 0
- class dragonfly_sim.core.shape_parameterization.WallFFD(comm, global_wall_coords, local_rows, shape, degree=2, ffd_block_corner_list=None, margin=0.0001, projection_newton_tol=1e-12, name='wall_ffd')
lsdo_geo FFD block embedding the mesh wall nodes.
Replicated across ranks: every rank evaluates the FFD at all
M_globalwall nodes and returns the full global array, rather than evaluating only the nodes it owns and having the pieces assembled afterwards.That is deliberate. A rank owning no wall nodes would otherwise return a
(0, dim)array, and the reverse chain back to the design variables would reduce an empty array – which XLA constant-folds at compile time. The downstream gradient reduction would then have no data dependence on anything on that rank, and sincejax.pure_callbackis declared effect-free, its collective could be scheduled arbitrarily early relative to the other ranks’. That is an ordering deadlock the ranks cannot recover from. Evaluating the full wall everywhere keeps every rank’s chain non-degenerate and lets the gradient reduction happen insideIDWarp_jax.compute_jacvec_product, on an array every rank genuinely computes.Only the projection is rank-local: each rank projects the wall nodes it owns (
local_rows) and the resulting parametric coordinates are gathered in rank order.- Parameters:
- commmpi4py communicator
- global_wall_coords(M_global, dim) array
All wall node coordinates, in the rank-block order of
Mesh.boundary_node_set((wall_tag,)).coords.- local_rowsint array
The contiguous rows of
global_wall_coordsthis rank owns (that node set’sglobal_idx).- shapesequence of int
Control points per parametric direction.
- degreeint or sequence of int
- ffd_block_corner_listoptional
Two-surface block definition, see
ffd_corners_from_corner_list. None wraps the wall’s bounding box.- marginfloat
Relative widening of the block beyond the wall / the given surfaces.
- projection_newton_tolfloat
Newton tolerance of the wall node projection into the block.
- _displacement_at(parametric_coordinates, coefficients)
- _project(points)
- add_probe_points(points)
Embed extra points (replicated input); returns their probe index.
Projected on rank 0 and broadcast, so every rank holds identical parametric coordinates.
- apply_cp_motions(coefficients, cp_motions, cp_coord_opt_idxs)
Add raw control-point motions to coefficients.
cp_motionshas shapeffd_shape + (len(cp_coord_opt_idxs),); column i moves spatial componentcp_coord_opt_idxs[i]and the other directions are left unchanged. The index tuples are built rather than written as literals so this works for any dimension.
- baseline_variable()
The baseline coefficients as a constant csdl Variable.
- probe_positions(coefficients, probe)
Deformed positions of probe set probe (index from add_probe_points).
- wall_displacement(coefficients)
Replicated
(M_global, dim)wall node displacement for coefficients.
- _probe_points = []
- baseline_coefficients
- baseline_wall_coords
- block
- comm
- corners
- degree
- projection_newton_tol = 1e-12
- shape
- wall_parametric_coordinates
- class dragonfly_sim.core.shape_parameterization.WallGeometry(ffd, wall_facets)
Geometric constraint quantities of the FFD-deformed wall.
- Parameters:
- ffdWallFFD
- wall_facets(n_facets, k) int array
Replicated wall facets as rows of wall node ids in
[0, M_global)(Mesh.wall_facets(wall_tag)): segments in 2D, triangles or quads (cyclic vertex order) in 3D. Their winding only needs to be consistent; the sign of the enclosed measure is fixed from the baseline.- In 3D the wall may be open on a symmetry plane through the origin (y = 0):
- that plane contributes nothing to the divergence-theorem volume, as long as
- the root section keeps y = 0.
- _chord_range(y0=None)
- _gather(X, j)
- _raw_measure_numpy(X)
- _section_leading_trailing_edges(y0)
Baseline (LE, TE) points of the 3D wall’s section at span y0: the min-x and max-x points where the plane y = y0 cuts the wall.
- _vertical_line_hits(x_in_plane)
Vertical-coordinate values where the vertical line through x_in_plane (x in 2D, (x, y) in 3D) crosses the baseline wall.
- add_planform_stations(span_stations)
Embed the LE and TE points of the wall sections at the given span stations (increasing y, root first); returns a handle.
handle['baseline']holds the undeformed chord, span and area as numbers, for constraint bounds (the csdl values are not available while the graph is recorded).
- add_thickness_stations(chord_fractions, span_stations=None)
Embed upper/lower wall points at chordwise stations; returns a handle.
2D: one station per chord fraction. 3D: the tensor product of chord fractions (of the local section chord) and span stations (y values).
- enclosed_measure(wall_displacement)
Enclosed area (2D) or volume (3D) of the deformed wall, positive.
- planform(coefficients, handle)
Deformed section chords, span and trapezoidal planform area.
Chords are LE-TE distances projected onto the xy plane; span and area use the y coordinates of the leading edges.
- thickness(coefficients, handle)
Deformed thickness at the stations of handle.
- thickness_ratio(coefficients, handle)
Deformed over baseline thickness at the stations of handle.
- _selectors
- _sign
- baseline_measure
- dim
- ffd
- dragonfly_sim.core.shape_parameterization._selection_matrix(ids, n_cols)
- dragonfly_sim.core.shape_parameterization.ffd_corners_from_bounding_box(coords, margin=0.0001)
Axis-aligned FFD block corners around coords, widened by margin*extent.
Returns the
(2,)*dim + (dim,)corner array thatlfs.create_b_spline_from_cornerstakes:corners[i0, i1, ..., d]is the min (i_d = 0) or max (i_d = 1) of coordinate d.
- dragonfly_sim.core.shape_parameterization.ffd_corners_from_corner_list(ffd_block_corner_list, margin=0.0001)
FFD block corners lofted between two rectangular end surfaces.
ffd_block_corner_listholds exactly two surfaces, each given by two opposite corners, e.g. the root and tip rectangles of a wing block. The “connecting” direction is the axis along which the surface midpoints differ most (spanwise for a wing); each surface spans the remaining axes. Each surface is widened by margin*extent along the axes it spans. The resulting block is tapered/swept, andlfs.create_b_spline_from_cornersfills it with the same trilinear lattice the pre-lsdo_geo construction produced.
- dragonfly_sim.core.shape_parameterization.validate_cp_coord_opt_idxs(cp_coord_opt_idxs, dim)
Check and return the optimized control-point directions as an int array.
Strictly increasing is required, not merely unique: the cp_motions design variable’s trailing axis is a compressed index into this array (see
WallFFD.apply_cp_motions), so a fixed order is what lets the bounds built byffd_dv_utils.build_cp_motion_dvline up with the DV columns without either side having to know how the other was written.