Strain and stress recovery ========================== femorph-solver recovers elastic strain from a displacement field via :meth:`femorph_solver.Model.eel`. The evaluation uses .. math:: \varepsilon(\xi) = B(\xi) \, u_e at each element's **own node positions** :math:`\xi_\text{node}` — i.e. direct nodal evaluation of :math:`\varepsilon = B u_e`, not Gauss-point sampling followed by extrapolation. For uniform-strain fields the two approaches agree exactly; for general fields they converge with mesh refinement. Voigt convention ---------------- Every strain tensor returned by femorph-solver is **6-component Voigt with engineering shears**: .. math:: \varepsilon = \bigl[\varepsilon_{xx},\ \varepsilon_{yy},\ \varepsilon_{zz}, \ \gamma_{xy},\ \gamma_{yz},\ \gamma_{xz}\bigr] with :math:`\gamma_{xy} = 2\varepsilon_{xy}`, matching MAPDL's ``S,EPEL`` output layout. API --- .. code-block:: python u = static.displacement # from solve_static / Model.solve eps = m.eel(u) # (n_nodes_global, 6), nodal-averaged eps_x = eps[:, 0] # ε_xx at every node gamma_xy = eps[:, 3] # engineering shear Per-element (unaveraged) ------------------------ ``nodal_avg=False`` returns the un-averaged per-element dict — use it when you want to see gradient discontinuities between elements: .. code-block:: python eps_per_elem = m.eel(u, nodal_avg=False) # {elem_num: (n_nodes_in_elem, 6)} This is the MAPDL ``S,EPEL,UNAV`` / ``AVRES,2`` equivalent. From a mode shape ----------------- Strain can be recovered from any valid displacement vector, including an eigenvector column from a modal solve: .. code-block:: python modal = solve_modal(K, M, prescribed=fixed, n_modes=10, eigen_solver="arpack", sigma=-1.0) eps_mode7 = m.eel(modal.mode_shapes[:, 7]) Stress recovery --------------- Stress :math:`\sigma = C \varepsilon` is not yet exposed as a direct accessor — call it explicitly from the elastic moduli. For an isotropic Hooke's law: .. code-block:: python from femorph_solver.elements.solid185 import _elastic_matrix C = _elastic_matrix(E=2.1e11, nu=0.30) # 6x6 isotropic sigma = eps @ C.T # (n_nodes, 6) A first-class stress API (``Model.s()`` matching MAPDL's ``S,S``) is on the roadmap but not yet in the public surface. Element-specific notes ---------------------- - **Solids (SOLID185/186/187)** return 3-D Voigt as described above. - **Shells (SHELL181)** return membrane + bending + transverse-shear components; details on the :doc:`/user-guide/pre-processing/elements/shell181` reference page. - **Beams, trusses, springs** — currently return placeholder arrays; their strain / stress output is on the roadmap. See also -------- - :doc:`result-objects` — source ``displacement`` / ``mode_shapes`` vectors. - :doc:`visualisation` — attaching the strain array to the model grid for a pyvista colour plot.