Built-up steel section properties using some good old Python (Part 2)

In this part we cover welding a flat plate to a flange.

Firstly, a couple of housekeeping issues…..

Most people (and commercial software) approach the calculation of properties for built-up shapes by slapping a plate hard against the section resulting in intimate contact between the plate and section. Effectively the strengthening element becomes part of the flange of the section. They then read off the properties, job done….

But I propose this is incorrect with respect to the calculation of torsion properties. In reality the plate won’t ‘be one’ with the flange. The reality is the two elements are only joined at the location of any welds, not across the full surface of contact. This matters when it comes to the calculation of torsion properties as you’ll see.

Additionally, it hopefully goes without saying, for any strengthening of this nature that you will be wanting to weld, not bolt. Bolting allows for slip so the composite section you are hoping to make is no longer composite.

The mesh size and number of points around curves (such as root radii) have the most impact on accuracy, and also the time to run the code.

Use a consistent set of units for the inputs (millimetres usually or inches if you’re imperially challenged) and our properties will be in those units.

Lastly, be aware that the sectionproperties package output is based mostly on New Zealand & Australian nomenclature, the main difference from other international standards is the following: –

  1. Z is the elastic section properties
  2. S is the plastic section properties
  3. In other international standards the above is reversed … don’t get caught out.

You can check at the sectionproperties docs for other definitions if you’re struggling to figure out what some property is.

The code…

import copy
import sectionproperties.pre.sections as sections
from sectionproperties.analysis.cross_section import CrossSection

# -------------------------------------------------------------
# Inputs
# -------------------------------------------------------------
num_plates = 2  # number strengthening plates, 1 for single flange, 2 for both flanges

d = 612  # I section depth
b_f = 229  # I-section flange width
t_f = 19.6  # I-section flange thickness
t_w = 11.9  # I-section web thickness
r_1 = 14  # I-section root radii
n_r = 50  # number of points considered around root radii

d_p = 10  # strengthening plate thickness
b_p = 250  # strengthening plate width

gap = 0.5  # gap between plate and section

weld_size = 6  # weld size

mesh_area = 1  # max mesh size

# -------------------------------------------------------------
# Calculations
# -------------------------------------------------------------
# create constituent geometry
# weld base geometry
weld = sections.CustomSection(
    points=[[0, 0], [weld_size, 0], [0, weld_size]], facets=[[0, 1], [1, 2], [2, 0]], holes=[], control_points=[[weld_size / 3, weld_size / 3]]
)
if b_p > b_f and not gap == 0:
    weld_vert_move = -gap
else:
    weld_vert_move = 0

# I-Section beam
geometry1 = sections.ISection(d=d, b=b_f, t_f=t_f, t_w=t_w, r=r_1, n_r=n_r, shift=[-b_f / 2, 0])

# strengthening plate 1
geometry2 = sections.RectangularSection(d=d_p, b=b_p, shift=[-b_p / 2, -d_p - gap])

# weld 1 & 2
geometry3 = copy.deepcopy(weld)
geometry3.mirror_section(axis='y', mirror_point=[0, 0])
geometry3.shift = [-min(b_f, b_p) / 2, weld_vert_move]
geometry3.shift_section()

geometry4 = copy.deepcopy(weld)
geometry4.shift = [min(b_f, b_p) / 2, weld_vert_move]
geometry4.shift_section()

# mirror welds depending on wider plate
if b_f > b_p:
    geometry3.mirror_section(axis='x', mirror_point=[0, 0])
    geometry4.mirror_section(axis='x', mirror_point=[0, 0])

# create second plate and welds if specified
if num_plates == 2:
    # strengthening plate 2
    geometry5 = copy.deepcopy(geometry2)
    geometry5.mirror_section(axis='x', mirror_point=[0, d / 2])
    # weld 3 & 4
    geometry6 = copy.deepcopy(geometry3)
    geometry6.mirror_section(axis='x', mirror_point=[0, d / 2])
    geometry7 = copy.deepcopy(geometry4)
    geometry7.mirror_section(axis='x', mirror_point=[0, d / 2])
    # total number of individual geometry elements
    geo_number = 7
else:
    # total number of individual geometry elements
    geo_number = 4

# assemble geometry list
geo_list = [globals()[f'geometry{i}'] for i in range(1, geo_number + 1)]

# create merged section
geometry = sections.MergedSection(geo_list)

# add holes for gaps between I-Section and strengthening plates
if not gap == 0:
    if num_plates == 2:
        geometry.add_hole([0, d + gap / 2])
    geometry.add_hole([0, -gap / 2])

# clean geometry
geometry.clean_geometry(verbose=True)

# create mesh
mesh = geometry.create_mesh(mesh_sizes=[mesh_area] * geo_number)

# create section
section = CrossSection(geometry, mesh)

# calculate results
section.calculate_geometric_properties()
section.calculate_plastic_properties()
section.calculate_warping_properties()

# -------------------------------------------------------------
# Display results
# -------------------------------------------------------------
# plot results
section.plot_mesh()
section.plot_centroids()

# display all results
# check https://sectionproperties.readthedocs.io/en/latest/rst/post.html for definitions
section.display_results(fmt='.3f')

Just change the variables in the input section of the script, it should be self-explanatory.

The code will correctly orientate the welds based on whether the plate(s) are wider or narrower than your beam flange as demonstrated below.

Single plate wider than the flange
Dual plate narrower than the flange

Results are returned in your terminal as follows, cut and paste and use elsewhere.

Section Properties:
A = 20193.473
Perim. = 0.000
Qx = 6179202.829
Qy = 0.000
cx = 0.000
cy = 306.000
Ixx_g = 3296963464.803
Iyy_g = 45506857.933
Ixy_g = 0.000
Ixx_c = 1406127399.071
Iyy_c = 45506857.933
Ixy_c = 0.000
Zxx+ = 4360084.958
Zxx- = 4360084.958
Zyy+ = 397439.807
Zyy- = 397439.807
rx = 263.880
ry = 47.471
phi = 0.000
I11_c = 1406127399.071
I22_c = 45506857.933
Z11+ = 4360084.958
Z11- = 4360084.958
Z22+ = 397439.807
Z22- = 397439.807
r11 = 263.880
r22 = 47.471
J = 4499264.297
Iw = 4213150905708.065
x_se = 0.001
y_se = 306.000
x_st = 0.001
y_st = 306.000
x1_se = 0.001
y2_se = -0.000
A_sx = 11851.214
A_sy = 7218.252
A_s11 = 11851.214
A_s22 = 7218.252
betax+ = -0.000
betax- = 0.000
betay+ = 0.001
betay- = -0.001
beta11+ = -0.000
beta11- = 0.000
beta22+ = 0.001
beta22- = -0.001
x_pc = 0.000
y_pc = 306.000
Sxx = 5013210.893
Syy = 675752.706
SF_xx+ = 1.150
SF_xx- = 1.150
SF_yy+ = 1.700
SF_yy- = 1.700
x11_pc = 0.000
y22_pc = 306.000
S11 = 5013210.893
S22 = 675752.706
SF_11+ = 1.150
SF_11- = 1.150
SF_22+ = 1.700
SF_22- = 1.700

Demo

To demonstrate the unconservative estimate of section properties with full contact vs a discrete gap being provided, the following comparison of no gap vs gap for the two plate arrangement above should convince you to change your ways.

Basically all the other properties are within a fraction of a percent, however J is overestimated by 4.4% for the no gap condition. Bad J.

PROPERTYNO GAP PROVIDEDGAP PROVIDEDRATIO OF NO GAP PROVIDED TO GAP PROVIDED PROPERTIES
A20193.4720193.471.000
Perim.00
Qx617920361792031.000
Qy00
cx00
cy3063061.000
Ixx_g3.3E+093.3E+091.000
Iyy_g45506858455068581.000
Ixy_g00
Ixx_c1.4E+091.41E+090.999
Iyy_c45506858455068581.000
Ixy_c00
Zxx+436279543600851.001
Zxx-436279543600851.001
Zyy+397439.8397439.81.000
Zyy-397439.8397439.81.000
rx263.758263.881.000
ry47.47147.4711.000
phi00
I11_c1.4E+091.41E+090.999
I22_c45506858455068581.000
Z11+436279543600851.001
Z11-436279543600851.001
Z22+397439.8397439.81.000
Z22-397439.8397439.81.000
r11263.758263.881.000
r2247.47147.4711.000
J469720944992641.044
Iw4.22E+124.21E+121.003
x_se00.0010.000
y_se3063061.000
x_st00.0010.000
y_st3063061.000
x1_se00.0010.000
y2_se00
A_sx12040.9111851.211.016
A_sy7350.0997218.2521.018
A_s1112040.9111851.211.016
A_s227350.0997218.2521.018
betax+00
betax-00
betay+00.0010.000
betay-0-0.0010.000
beta11+00
beta11-00
beta22+00.0010.000
beta22-0-0.0010.000
x_pc00
y_pc3063061.000
Sxx501113150132111.000
Syy675752.7675752.71.000
SF_xx+1.1491.150.999
SF_xx-1.1491.150.999
SF_yy+1.71.71.000
SF_yy-1.71.71.000
x11_pc00
y22_pc3063061.000
S11501113150132111.000
S22675752.7675752.71.000
SF_11+1.1491.150.999
SF_11-1.1491.150.999
SF_22+1.71.71.000
SF_22-1.71.71.000

Does it really matter in terms of the end result of capacity, I’ll leave that to you to prove. But take away from this assessment that two separate plates should be treated as two separate plates and not magically fused together by poor judgement.

Until part 3, plate everything in sight.

One comment

  1. This is some really good insight and an excellent analysis. I haven’t heard anyone really deal with this aspect before (though I’m mostly a concrete guy), and leveraging section-properties this way is cool!

Leave a Reply