Loads and springs

Nodal and element loads, the fixed-end-force engine, and nodal spring supports.

Asap.AbstractLoadType
AbstractLoad{T<:Real}

Supertype of all loads. Loads are immutable, reference their target (node or element) directly, and carry a case::Symbol tag grouping them into a load case for later combination (default :LC1).

Two families:

  • NodeLoad: concentrated actions applied directly to nodal DOFs
  • ElementLoad: actions applied along an element, converted to equivalent (fixed-end) nodal forces during load assembly

The single extension point for new element load types is fixed_end_forces(load, section, ends, x1, x2, rollangle) returning the clamped-clamped local 12-vector — end-condition condensation and rotation to global coordinates are applied generically afterwards.

source
Asap.DistributedLoadType
DistributedLoad{T} <: ElementLoad{T}

The canonical distributed load: a piecewise-linear intensity along the element, in a fixed direction. Every distributed loading — uniform, trapezoidal, triangular, partial-span, tributary — lowers to this one type, and one fixed-end-force integration handles them all.

Fields

  • element: the loaded element
  • t::Vector{T}: sorted breakpoint positions as fractions ∈ [0, 1] of the element length. Intensity is zero outside [t[1], t[end]], so partial-span loads need no special casing.
  • w::Vector{T}: load intensity at each breakpoint [force/length], varying linearly between breakpoints
  • direction::SVector{3,T}: unit direction of the load
  • coords::Symbol: :global (direction fixed in space — gravity, wind) or :local (direction follows the element's local axes)
  • id, case: tags

Convenience constructors

LineLoad(element, wvec; id, case)              # uniform, full span, global
DistributedLoad(element, t, w, direction; coords = :global, id, case)

Examples

julia> LineLoad(beam, [0.0, 0.0, -2.0])                       # uniform gravity-direction

julia> DistributedLoad(beam, [0.2, 0.8], [0.0, 5.0], SVector(0.0, 0.0, -1.0))
       # partial-span triangular ramp between 20% and 80% of the span
source
Asap.NodeForceType
NodeForce{T} <: NodeLoad{T}

A concentrated force [Fx, Fy, Fz] [force] applied to a node in GLOBAL coordinates.

NodeForce(node, value; id = :force, case = :LC1)
source
Asap.NodeMomentType
NodeMoment{T} <: NodeLoad{T}

A concentrated moment [Mx, My, Mz] [force·length] applied to a node's rotational DOFs in GLOBAL coordinates.

NodeMoment(node, value; id = :moment, case = :LC1)
source
Asap.PointLoadType
PointLoad{T} <: ElementLoad{T}

A concentrated force [Px, Py, Pz] applied along an element at fraction position ∈ (0, 1) of its length.

PointLoad(element, position, value; coords = :global, id = :pointload, case = :LC1)
source
Asap.PointMomentType
PointMoment{T} <: ElementLoad{T}

A concentrated moment [Mx, My, Mz] [force·length] applied along an element at fraction position ∈ (0, 1) of its length — a capability the legacy library lacked. Its fixed-end forces pair the moment with the SLOPES of the shape functions (a moment does work through rotation), which is why the FEF kernel needs the Hermite derivatives.

PointMoment(element, position, value; coords = :global, id = :pointmoment, case = :LC1)
source
Asap.SelfWeightType
SelfWeight{T} <: ElementLoad{T}

Self-weight of an element: a distributed load of intensity ρA(section) · |g| in the direction of g, where ρA is the section's mass per unit length. There is exactly one source of truth for mass — the section accessor — so density lives on the Material/section, never on the load.

SelfWeight(element; g = SVector(0, 0, -9.80665), factor = 1, id, case)

g is the gravitational acceleration vector [length/time²] in global coordinates (default: SI standard gravity in −Z); factor is a plain multiplier (leave load-combination factors to LoadCombinations).

source
Asap.LineLoadMethod
LineLoad(element, wvec; id = :lineload, case = :LC1)

A uniform full-span distributed load given as a GLOBAL vector [wx, wy, wz] [force/length] — the legacy LineLoad signature, lowered to a DistributedLoad with magnitude |wvec| along normalize(wvec).

source
Asap.TrapezoidLoadMethod
TrapezoidLoad(element, t1, t2, w1, w2, direction;
              coords = :global, id = :trapezoidload, case = :LC1)

A partial-span trapezoidal distributed load: intensity varying linearly from w1 [force/length] at fraction t1 to w2 at fraction t2 of the element length, zero elsewhere, acting along the unit direction. A triangular load is the w1 = 0 (or w2 = 0) special case.

Lowered to the canonical DistributedLoad — one integration engine covers every distributed shape.

Examples

julia> TrapezoidLoad(beam, 0.0, 1.0, 2.0, 5.0, [0.0, 0.0, -1.0])   # full-span trapezoid

julia> TrapezoidLoad(beam, 0.3, 0.9, 0.0, 4.0, [0.0, -1.0, 0.0])   # partial triangular ramp
source
Asap.condense_fefMethod
condense_fef(q, section, L, ends::EndConditions) -> SVector{12}

Transform a clamped-clamped local fixed-end force vector q into the fixed-end forces consistent with the element's actual end conditions.

Physics: the beam's end rotations connect to the nodes through the end springs. Holding all nodal DOFs fixed, the beam-side rotations θb of each bending plane relax to

θb = −(Kθθ + diag(k))⁻¹ qθ

(where Kθθ is the clamped bending block's rotation–rotation part and k the end spring pair), and the nodal fixed-end forces become

q̃θ = qθ + Kθθ·θb          (rotations — zero at an ideal release)
q̃v = qv + Kvθ·θb          (translations pick up the redistributed shear)

Rigid springs (Inf) pass the clamped values through unchanged; zero springs reproduce the legacy release corrections exactly (characterization- tested); finite springs give the consistent semi-rigid redistribution. Axial and torsional FEF components pass through unchanged — no distributed axial-spring/torque load type exists yet (revisit when one does).

source
Asap.fixed_end_forcesMethod
fixed_end_forces(load, section, ends, x1, x2, rollangle) -> SVector{12}

Clamped-clamped fixed-end force vector in element LOCAL coordinates for an element load. THE extension point for new element load types: implement exactly this method; condensation for releases/semi-rigid ends and rotation to global coordinates are applied generically by the load assembler.

section, x1, x2, rollangle describe the element (positions passed explicitly so the pure AD path can differentiate through geometry); ends is accepted for interface uniformity but the returned vector is always the CLAMPED one.

source
Asap.NodalSpringType
NodalSpring{T<:Real}

An elastic (spring) support acting at a node — applicative data: the spring references its node the way a load references its target, and lives in the model's spring list. Nodes never know about their springs; multiple springs on one node compose additively.

Each of the node's six global DOFs gets an independent spring stiffness: translational stiffnesses [force/length] on (Tx, Ty, Tz), rotational stiffnesses [force·length/rad] on (Rx, Ry, Rz). Zero entries mean no spring on that DOF. During assembly the stiffnesses are added to the global stiffness diagonal; a sprung DOF is marked active (it participates in the solve even if nothing else touches it), and its spring reaction is recovered as −k·u in post-processing.

Use a NodalSpring for elastic foundations, soil springs, flexible supports, and partial restraints — anywhere a rigid fixity support is too stiff an idealization.

Fields

  • node::Node{T}: the supported node
  • stiffness::SVector{6,T}: spring stiffness per global DOF, ordered (Tx, Ty, Tz, Rx, Ry, Rz); entries ≥ 0
  • id::Symbol: user tag

Constructors

NodalSpring(node, stiffness::AbstractVector, id = :spring)   # 6 entries
NodalSpring(node, k_translation::Real, id = :spring)         # uniform Tx=Ty=Tz=k

Examples

julia> soil = NodalSpring(base, [0.0, 0.0, 5e4, 0.0, 0.0, 0.0], :soil)  # vertical only

julia> pad = NodalSpring(base, 1e5)   # equal translational springs, no rotational
source