hermit.loads ============ .. py:module:: hermit.loads .. autoapi-nested-parse:: ``Loads`` -- distributed, edge and point loads; ``a + b`` composes them. Each builder returns a :class:`Loads` carrying one term. ``pressure`` / ``traction`` / ``moment`` are distributed over the shell surface; ``edge_pressure`` / ``edge_traction`` / ``edge_moment`` act on selected exterior facets; ``point_load`` is a consistent (weak Dirac) point load; ``load_vector`` is a direct generalised RHS in ``domain.W`` dof ordering. Every term reaches :func:`hermit.solve` as its own residual and compliance contribution, on its own space, with no interpolation between terms. ``pressure`` follows the live, shape-differentiable ``ufl.CellNormal``. ``combined_traction`` / ``combined_moment`` reduce several terms onto one shared space. They are not part of the solve path -- they exist for callers that drive the raw FEniCSx operations directly. .. !! processed by numpydoc !! Classes ------- .. autoapisummary:: hermit.loads.Loads Functions --------- .. autoapisummary:: hermit.loads.edge_moment hermit.loads.edge_pressure hermit.loads.edge_traction hermit.loads.load_vector hermit.loads.moment hermit.loads.point_load hermit.loads.pressure hermit.loads.traction Module Contents --------------- .. py:class:: Loads(domain, *, traction_terms=(), moment_terms=(), pressure_terms=(), edge_traction_terms=(), edge_moment_terms=(), edge_pressure_terms=(), direct=None) A composable bundle of load terms. Build one with :func:`pressure`, :func:`traction`, :func:`moment`, :func:`edge_pressure`, :func:`edge_traction`, :func:`edge_moment`, :func:`point_load` or :func:`load_vector` rather than calling this constructor directly. ``a + b`` merges two ``Loads`` on the same domain, concatenating the term lists and summing the direct right-hand sides. :Parameters: **domain** : ShellDomain .. **traction_terms, moment_terms** : sequence of Field, optional Distributed ``(3,)`` vector fields. **pressure_terms** : sequence of Field, optional Distributed scalar fields, acting along the shell normal. **edge_traction_terms, edge_moment_terms, edge_pressure_terms** : sequence, optional Edge terms, each pairing a field with the exterior-facet measure it acts on. **direct** : csdl.Variable, optional A generalised right-hand side in ``domain.W`` dof ordering. .. rubric:: Examples >>> loads = hm.pressure(domain, 2.0) + hm.point_load(domain, at=tip, force=[0, 0, -1]) .. !! processed by numpydoc !! .. py:method:: combined_moment(space=('Lagrange', 1, (3, ))) -> hermit._field.Field | None Sum the distributed moment terms onto one space. :Parameters: **space** : tuple, optional Target space. Exact when every term is already on it. :Returns: Field or None ``None`` when there are no moment terms. .. !! processed by numpydoc !! .. py:method:: combined_traction(space=('Lagrange', 1, (3, ))) -> hermit._field.Field | None Sum the traction and pressure terms onto one space. Pressure is converted to a traction with a numpy snapshot of the reference normal. :func:`~hermit.solve` does not use this -- it takes each term directly, with the live normal. :Parameters: **space** : tuple, optional Target space. Exact when every term is already on it. :Returns: Field or None ``None`` when there are no such terms. .. !! processed by numpydoc !! .. py:method:: direct_vector(ndof=None) -> csdl_alpha.Variable The combined point-load and load-vector right-hand side. :Parameters: **ndof** : int, optional Length to use when there is no direct term. Defaults to the number of ``domain.W`` dofs. :Returns: csdl.Variable Shape ``(ndof,)`` in ``domain.W`` dof order; zeros when there is no point load or load vector. .. !! processed by numpydoc !! .. py:attribute:: direct :value: None .. py:attribute:: domain .. py:attribute:: edge_moment_terms :value: [] .. py:attribute:: edge_pressure_terms :value: [] .. py:attribute:: edge_traction_terms :value: [] .. py:attribute:: moment_terms :value: [] .. py:attribute:: pressure_terms :value: [] .. py:attribute:: traction_terms :value: [] .. py:function:: edge_moment(domain, m, *, where, space=('Lagrange', 1)) -> Loads Moment per unit length on selected exterior facets. :Parameters: **domain** : ShellDomain .. **m** : Field or array_like A ``(3,)`` global vector, or a ``Field`` of ``(3,)`` vectors. **where** : callable Coordinate predicate selecting the loaded edge; see :func:`edge_traction`. **space** : tuple, optional Space for a non-``Field`` value. Default ``("Lagrange", 1)``. :Returns: Loads .. :Raises: ValueError If ``m`` does not resolve to a ``(3,)`` vector field. .. !! processed by numpydoc !! .. py:function:: edge_pressure(domain, p, *, where, space=('DG', 0)) -> Loads Pressure per unit length along the shell normal, on selected exterior facets. :Parameters: **domain** : ShellDomain .. **p** : Field, float or array_like Scalar pressure; positive acts along ``+n``. **where** : callable Coordinate predicate selecting the loaded edge; see :func:`edge_traction`. **space** : tuple, optional Space for a non-``Field`` value. Default ``("DG", 0)``. :Returns: Loads .. :Raises: ValueError If ``space`` is not scalar, or if the domain's cell normals are not consistently oriented. .. !! processed by numpydoc !! .. py:function:: edge_traction(domain, t, *, where, space=('Lagrange', 1)) -> Loads Force per unit length on selected exterior facets. :Parameters: **domain** : ShellDomain .. **t** : Field or array_like A ``(3,)`` global vector, or a ``Field`` of ``(3,)`` vectors. **where** : callable Coordinate predicate selecting the loaded edge, with the same contract as :func:`~hermit.clamp`: it receives a ``(3, N)`` coordinate array and returns an ``(N,)`` boolean mask. Only exterior facets are selected. **space** : tuple, optional Space for a non-``Field`` value. Default ``("Lagrange", 1)``. :Returns: Loads .. :Raises: ValueError If ``t`` does not resolve to a ``(3,)`` vector field. .. rubric:: Examples >>> tip = hm.edge_traction(domain, [0.0, 0.0, -1.0], where=hm.near("x", 10.0)) .. !! processed by numpydoc !! .. py:function:: load_vector(domain, vec) -> Loads A generalised right-hand side given directly in state-space dof order. :Parameters: **domain** : ShellDomain .. **vec** : csdl.Variable or array_like One entry per ``domain.W`` dof, in that space's dof ordering. :Returns: Loads .. :Raises: ValueError If ``vec`` does not have exactly ``domain.W``'s dof count. .. !! processed by numpydoc !! .. py:function:: moment(domain, m, *, space=('Lagrange', 1)) -> Loads Distributed moment per unit area, in global components. Contributes ``int m . dtheta dx`` to the residual. :Parameters: **domain** : ShellDomain .. **m** : Field or array_like A ``(3,)`` global vector, or a ``Field`` of ``(3,)`` vectors. **space** : tuple, optional Space for a non-``Field`` value. Default ``("Lagrange", 1)``. :Returns: Loads .. :Raises: ValueError If ``m`` does not resolve to a ``(3,)`` vector field. .. !! processed by numpydoc !! .. py:function:: point_load(domain, *, at, force=None, moment=None) -> Loads A consistent point force and/or moment at a physical coordinate. The cell containing ``at`` is located, the state-space basis is evaluated there, and the result is scattered into the direct right-hand side -- the weak form of a Dirac delta, ``int F . delta(x - at) . du dx = F . du(at)``. The point need not be a mesh vertex. :Parameters: **domain** : ShellDomain .. **at** : array_like Physical coordinate, shape ``(3,)``. **force** : csdl.Variable or array_like, optional ``(3,)`` point force. **moment** : csdl.Variable or array_like, optional ``(3,)`` point moment. :Returns: Loads .. :Raises: ValueError If neither ``force`` nor ``moment`` is given, or if ``at`` lies in no cell. .. rubric:: Notes Differentiable in ``force`` and ``moment``, but **not** in ``at`` or the mesh coordinates: the containing cell is fixed at construction. .. !! processed by numpydoc !! .. py:function:: pressure(domain, p, *, space=('DG', 0)) -> Loads Scalar pressure acting along the shell normal. Positive ``p`` acts along ``+n``. The residual uses the live ``ufl.CellNormal``, so the load is differentiable with respect to the mesh coordinates. :Parameters: **domain** : ShellDomain .. **p** : Field, float or array_like Scalar pressure. **space** : tuple, optional Space for a non-``Field`` value. Default ``("DG", 0)``. :Returns: Loads .. :Raises: ValueError If ``space`` is not scalar, or if the domain's cell normals are not consistently oriented. On a badly-wound imported mesh a uniform pressure would otherwise become a sign-alternating load with no other symptom. .. seealso:: :obj:`traction` an explicit global vector, independent of the normal. .. !! processed by numpydoc !! .. py:function:: traction(domain, t, *, space=('Lagrange', 1)) -> Loads Distributed force per unit area, in global components. Contributes ``int t . du dx`` to the residual. Unlike :func:`pressure` this never touches the shell normal, so it is the right choice for a body force such as self weight on a curved surface. :Parameters: **domain** : ShellDomain .. **t** : Field or array_like A ``(3,)`` global vector, or a ``Field`` of ``(3,)`` vectors. **space** : tuple, optional Space for a non-``Field`` value. Default ``("Lagrange", 1)``. :Returns: Loads .. :Raises: ValueError If ``t`` does not resolve to a ``(3,)`` vector field. .. seealso:: :obj:`pressure` a scalar load following the shell normal. :obj:`edge_traction` the same load on selected exterior facets. .. !! processed by numpydoc !!