SPRING — 3-D 2-node longitudinal spring ======================================= **Kinematics.** Two-node spring oriented along :math:`I \to J`; three translational DOFs per node; 6 DOFs per element. No bending, torsion, or mass — the longitudinal spring is stiffness-only. **Stiffness.** Closed-form :math:`K_e = K \begin{bmatrix} C & -C \\ -C & C \end{bmatrix}` with :math:`C = \hat{d} \hat{d}^\top`. **Mass.** Zero by convention (``me`` returns a 6 × 6 zero matrix so the assembler can dispatch uniformly). **Modes.** Only the longitudinal mode is implemented; torsional and 2-D planar variants are separate code paths and roadmap. .. contents:: On this page :local: :depth: 2 ---- Longitudinal spring ------------------- A spring is the discrete analogue of a truss whose only "material" property is the stiffness :math:`K` (force per length); compared to :doc:`TRUSS2 `, there is no cross-section area, no length in the :math:`E A / L` sense — just a scalar spring constant [Cook2001]_. Taking :math:`\hat{d} = (d_x, d_y, d_z)` as the unit vector along :math:`I \to J`, the axial displacement at each end projects onto :math:`\hat{d}` to give a 1-D spring acting in that direction. The element stiffness in global coordinates is .. math:: K_e = K \begin{bmatrix} \phantom{-}C & -C \\ -C & \phantom{-}C \end{bmatrix}, \qquad C_{jk} = d_j\, d_k, directly analogous to the :doc:`TRUSS2 ` formula with :math:`E A / L` replaced by :math:`K`. :math:`K_e` has rank 1 (the single stretching mode); five zero eigenvalues correspond to the allowed rigid-body / transverse translations. Real constants -------------- .. list-table:: :widths: 20 15 65 :header-rows: 1 * - Slot - Symbol - Meaning * - ``real[0]`` - :math:`K` - Spring stiffness (force / length). Mandatory. * - ``real[1]`` - ``CV1`` - Linear damping (force · time / length). Parsed but not used by :math:`K_e`; consumed by transient damping paths when available. * - ``real[2]`` - ``CV2`` - Non-linear cubic damping. Parsed but not used. * - ``real[3]`` - ``IL`` - Initial length. Parsed but ignored; the reference length is the nodal distance. Numpy walk-through ------------------ .. code-block:: python import numpy as np K_spring = 1.0e6 # N / m X = np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]]) d = X[1] - X[0] L = float(np.linalg.norm(d)) dhat = d / L Cproj = np.outer(dhat, dhat) # 3x3 K = K_spring * np.block([[ Cproj, -Cproj], [-Cproj, Cproj]]) # Eigvals: [0, 0, 0, 0, 0, 2 * K_spring] # Zero mass: M = np.zeros((6, 6)) Validation ---------- **Single-element stretch.** A 1-D spring of stiffness :math:`K` with one end pinned and a unit force on the other produces :math:`u = 1 / K`. Rotate the element to any orientation in 3-D; the analytic result is unchanged. API reference ------------- .. autoclass:: femorph_solver.elements.spring.Spring :members: References ---------- .. [Cook2001] Cook, R. D., Malkus, D. S., Plesha, M. E., and Witt, R. J. (2001). *Concepts and Applications of Finite Element Analysis*, 4th ed. Wiley. Ch. 2 (spring / bar elements). https://www.wiley.com/en-us/Concepts+and+Applications+of+Finite+Element+Analysis%2C+4th+Edition-p-9780471356059