hermit.csdl_helpers =================== .. py:module:: hermit.csdl_helpers .. autoapi-nested-parse:: Native-CSDL preprocessing / postprocessing helpers. Everything here is ordinary CSDL (auto-differentiated) -- gathers, reshapes, the isotropic ABD assembly, the force->pressure L2 solve, stress aggregation, nodal extraction. No FEniCSx, no custom operations. .. !! processed by numpydoc !! Functions --------- .. autoapisummary:: hermit.csdl_helpers.aggregate hermit.csdl_helpers.assemble_abd_isotropic hermit.csdl_helpers.broadcast0 hermit.csdl_helpers.build_moment hermit.csdl_helpers.build_pressure hermit.csdl_helpers.extract_nodal hermit.csdl_helpers.orientation_angle hermit.csdl_helpers.reorder hermit.csdl_helpers.resolve_mesh_nodes hermit.csdl_helpers.rotate_abd Module Contents --------------- .. py:function:: aggregate(pnorm_stress, m, rho) Aggregated stress ``(1/m) * (pnorm + guard)**(1/rho)``. ``m`` is a problem-specific *scaling*, not a smoothing knob: the aggregate is mathematically invariant under ``m`` (it cancels), and only the finite exponent range of float64 breaks that invariance -- which it does violently once ``m*max(vm)`` strays far from 1. ``_warn_if_degenerate`` says so out loud. .. !! processed by numpydoc !! .. py:function:: assemble_abd_isotropic(E, nu, thickness) Isotropic single-layer A, B, D (n,3,3) and As (n,2,2) from E, nu, thickness (n,). Port of ``MaterialInputFactory.from_isotropic`` (femo dev_coupling). .. !! processed by numpydoc !! .. py:function:: broadcast0(var: csdl_alpha.Variable, n: int) -> csdl_alpha.Variable Broadcast ``var`` along axis 0 to length ``n``. A scalar (``()`` / ``(1,)``) or a leading axis of length 1 is expanded to ``n`` (differentiably); an axis already of length ``n`` is returned unchanged. Used to let material inputs be given as a single value instead of a per-node / per-cell array. .. !! processed by numpydoc !! .. py:function:: build_moment(loads, maps, vf_size: int) .. py:function:: build_pressure(loads, maps, vf_size: int) Combine nodal pressure + (force -> pressure) into the VF-dof RHS vector. .. !! processed by numpydoc !! .. py:function:: extract_nodal(disp_vec, sparse_map, geom_shape, reverse_node_idx) (state dof vec) -> (n_nodes, 3) nodal field, reordered back to user node ordering. .. !! processed by numpydoc !! .. py:function:: orientation_angle(direction, frames) -> numpy.ndarray Per-cell angle (rad) from each cell's local e0 to the tangent-plane projection of ``direction`` (a global ``(3,)`` vector or a per-cell ``(n, 3)`` field). ``frames``: ``(n, 3, 3)`` local frames, rows e0, e1, e2. Pure numpy -- fibre layout is fixed. .. !! processed by numpydoc !! .. py:function:: reorder(var: csdl_alpha.Variable, idx) -> csdl_alpha.Variable Gather ``var`` along axis 0 by integer index array ``idx`` (user -> FE ordering). .. !! processed by numpydoc !! .. py:function:: resolve_mesh_nodes(reference_nodes, node_disp=None, mesh_nodes=None) Return (mesh_nodes_variable, geometry_is_differentiable). .. !! processed by numpydoc !! .. py:function:: rotate_abd(A, B, D, As, theta) Rotate the ABD stiffness ``(n,3,3)`` and transverse shear ``As`` ``(n,2,2)`` by a per-cell in-plane angle ``theta`` ``(n,)``. ``theta`` may be numpy (fixed fibre layout) or a ``csdl.Variable`` (differentiable, e.g. a fibre-angle design field). ``X_rot = Tsig_inv(theta) @ X @ Teps(theta)`` -- LamAD's CLT transform. ``As`` is in the shell's standard (xz, yz) transverse-shear ordering (the CLT seam in ``hm.laminate`` permutes it there), so its rotation uses ``r2t @ As @ r2 == R(theta)^T As R(theta)`` -- the ``Teps``-consistent convention (``r2 == R(theta)``, ``r2t == R(theta)^T``), matching ``hermit.fenics.kinematics.shear_rotation`` / ``congruent_transform``. (``r2 @ As @ r2t`` would instead be correct for a swapped ``(yz, xz)`` ordering.) .. !! processed by numpydoc !!