Long before structural fire analysis became an OpenSees side hustle, the elasticBeamColumn element was able to handle thermal loads. The -alpha and -depth options are not really Easter eggs so much as undocumented features.
Back in 2002, when OpenSees source control used CVS, Scott Hamilton modified the elasticBeamColumn element with two optional parameters for the coefficient of thermal expansion and beam depth. He also defined Beam2dTempLoad to apply temperatures as element loads. The options are for two-dimensional models only.
To confirm the implementation still works today, I used Example 7.3 from J.C. Smith’s Structural Analysis. The model is a two-span continuous steel beam heated 60 degrees Fahrenheit more on the top than on the bottom.

The beam section is W21x68 with depth d=21.13 inch, A= 20 inch2, and I=1480 inch4. The elastic modulus is E=29000 ksi and the coefficient of thermal expansion is α=6.5e-6 / degF.
The reported reactions due to the thermal loading are 4.95 kip (up) at A, 7.43 kip (down) at B, and 2.48 kip (up) at C.
The OpenSees Python script below confirms the expected reactions using the elasticBeamColumn element and a beamTemp element load.
import openseespy.opensees as ops
from numpy import isclose
kip = 1.0
ft = 1.0
degF = 1.0
inch = ft/12
ksi = kip/inch**2
E = 29000*ksi
alpha = 6.5e-6/degF
# W21x68
A = 20*inch**2
I = 1480*inch**4
d = 21.13*inch # Recent editions of the Steel Manual show d=21.1 inch
ops.wipe()
ops.model('basic','-ndm',2,'-ndf',3)
ops.node(1,0,0); ops.fix(1,1,1,0)
ops.node(2,20*ft,0); ops.fix(2,0,1,0)
ops.node(3,60*ft,0); ops.fix(3,0,1,0)
ops.geomTransf('Linear',1)
ops.element('elasticBeamColumn',1,1,2,A,E,I,1,'-alpha',alpha,'-depth',d)
ops.element('elasticBeamColumn',2,2,3,A,E,I,1,'-alpha',alpha,'-depth',d)
dT = 60*degF # Change in temperature
ops.timeSeries('Constant',1)
ops.pattern('Plain',1,1)
ops.eleLoad('-ele',1,2,'-type','-beamTemp',dT,0) # top,bottom
ops.analysis('Static','-noWarnings')
ops.analyze(1)
ops.reactions()
assert isclose( 4.95,ops.nodeReaction(1,2)/kip,atol=0.5e-2)
assert isclose(-7.43,ops.nodeReaction(2,2)/kip,atol=0.5e-2)
assert isclose( 2.48,ops.nodeReaction(3,2)/kip,atol=0.5e-2)
The assertions should pass.
Remember that the beamTemp temperatures refer to the “top” and “bottom” of the basic system, so swapping the element nodes also swaps the thermal loading, no different from mechanical element loads that follow the local axes.
