Analysis and results

Build a model, solve it, query the results:

steel  = Material(200e6, 80.0, 0.3)
column = Section(steel, 1e-2, 8e-5, 3e-5, 5e-7)

n1 = Node([0.0, 0.0, 0.0], :fixed)
n2 = Node([0.0, 0.0, 3.0], :free)
el = FrameElement(n1, n2, column)

model = Model([n1, n2], [el], [NodeForce(n2, [10.0, 0.0, 0.0])])
solve!(model)                     # process! runs automatically the first time
Model
  2 nodes, 1 elements (1 frame, 0 truss)
  1 loads, 0 nodal springs
  processed: 6 free / 6 fixed / 0 inactive DOFs
  solved (see model.results)

Results are read through accessor functions — they never live on nodes or elements:

res = model.results
displacement(res, n2)             # SVector{6} at a node
6-element StaticArraysCore.SVector{6, Float64} with indices SOneTo(6):
  0.005624999999999996
  5.740531871003215e-19
  0.0
 -2.870265935501607e-19
  0.0028124999999999986
  0.0
reaction(res, n1)                 # support reactions (incl. moment reactions)
6-element StaticArraysCore.SVector{6, Float64} with indices SOneTo(6):
  -9.999999999999991
  -4.834792538857486e-31
   0.0
   8.904880127524264e-32
 -29.999999999999975
   0.0
element_forces(res, el)           # local end-force 12-vector
12-element Vector{Float64}:
  0.0
  9.999999999999991
  6.123233995736765e-16
  0.0
 -1.8369701987210284e-15
 29.999999999999975
  0.0
 -9.999999999999991
 -6.123233995736765e-16
  0.0
  1.850583789636163e-31
 -1.2372325386422741e-14
axial_force(res, el)              # tension-positive scalar
0.0
res.compliance                    # external work Fᵀu
0.05624999999999997

Repeated solves

Repeated solves — geometry or section values changed, topology unchanged — reuse the frozen sparsity pattern and refactorize numerically: just call solve!(model) again. After topology changes (elements added, releases toggled, supports changed): solve!(model; reprocess = true).