Load cases, combinations, envelopes

Tag loads with cases; solve every case against one factorization; get any factored combination by superposition — no re-solves, ever.

The example is a small portal frame with dead, live, and wind cases:

n1 = Node([0.0, 0.0, 0.0], :fixed)
n2 = Node([0.0, 0.0, 3.0], :free)
n3 = Node([5.0, 0.0, 3.0], :free)
n4 = Node([5.0, 0.0, 0.0], :fixed)
beam = FrameElement(n2, n3, wshape, :beam)
elements = AbstractElement{Float64}[
    FrameElement(n1, n2, wshape), beam, FrameElement(n4, n3, wshape)]

loads = AbstractLoad{Float64}[
    LineLoad(beam, [0.0, 0.0, -2.0]; case = :dead),
    PointLoad(beam, 0.4, [0.0, 0.0, -10.0]; case = :live),
    NodeForce(n2, [5.0, 0.0, 0.0]; case = :wind),
]
model = Model([n1, n2, n3, n4], elements, loads)

cr = solve_cases!(model)                    # one assembly, one factorization
CaseResults{Float64}([:dead, :live, :wind], LinearResults{Float64}[LinearResults(compliance=0.0013333996792688472), LinearResults(compliance=0.002805463970195059), LinearResults(compliance=0.0029239084942303665)], [0.0 0.0 0.0; 0.0 0.0 0.0; … ; 0.0 0.0 0.0; 0.0 0.0 0.0])

Combinations are exact, by superposition:

strength = LoadCombination(:LRFD, [:dead => 1.2, :live => 1.6, :wind => 0.5])
res = combine(cr, strength)
displacement(res, n2)
6-element StaticArraysCore.SVector{6, Float64} with indices SOneTo(6):
  0.00041553177981608173
  4.190662975148763e-20
 -2.2768228696123535e-5
 -6.943765511639179e-20
  0.0006838645746571335
  6.939883546446417e-20

Station-wise min/max over a combination set — what design checks consume:

env = envelope(model, beam, cr,
    [strength, LoadCombination(:service, [:dead => 1.0, :live => 1.0])])
env.x, env.lo, env.hi                       # rows: N, Vy, Mz, Vz, My, Mx
([0.0, 0.2631578947368421, 0.5263157894736842, 0.7894736842105263, 1.0526315789473684, 1.3157894736842104, 1.5789473684210527, 1.8421052631578947, 1.999999925494194, 2.000000074505806  …  2.631578947368421, 2.8947368421052633, 3.1578947368421053, 3.4210526315789473, 3.6842105263157894, 3.947368421052632, 4.2105263157894735, 4.473684210526316, 4.7368421052631575, 5.0], [-6.839662806539516 -6.839662806539516 … -6.839662806539516 -6.839662806539516; 11.103242664739321 10.576926875265636 … -12.189601921882556 -12.821180869250979; … ; 4.944824185866944e-16 3.1980105098132763e-16 … 3.2363309103262655e-16 4.627462633749899e-16; 5.749486495975891e-19 5.749486495975891e-19 … 5.749486495975891e-19 5.749486495975891e-19], [-3.895606267029973 -3.895606267029973 … -3.895606267029973 -3.895606267029973; 15.178819130749021 14.5472401833806 … -8.370441545786994 -8.896757335260679; … ; 6.228135307684508e-16 3.832929269179564e-16 … 5.498739934670374e-16 7.513619322457837e-16; 8.270983123103555e-19 8.270983123103555e-19 … 8.270983123103555e-19 8.270983123103555e-19])