Tube slenderness

During a pushover simulation last week, the jacket kept struggling at the set load increments. These had not changed from a previous such exercise, the difference being that a particular frame normal to the environmental attack direction had been revised.

Braces buckling when subjected to incremental increase in environmental loading.
Braces buckling when subjected to incremental increase in environmental loading.

When these braces, directly in the line of attack, continued to struggle — exhibiting excessive displacements in the revised model configuration causing negative matrix errors, I had to re-check their slenderness, even if they did not seem slender at all.

So back to basics. The criteria for a ductile design, recommended by §11.4, ISO 19902 is as follows:

$$ \frac{K L}{r} \leq 80 $$

$$ \lambda \leq \frac{80}{\pi} \sqrt{ \frac{f_{yc}}{E} } $$

$$ \frac{f_y D}{E t} \leq 0.069 $$

where,

From §13 of ISO 19902,

$$ \lambda = \frac{K L}{\pi r} \sqrt{ \frac{f_{yc}}{E} } $$

$$ \begin{aligned} f_{yc} &= f_y \;\;\; \text{for} \;\; \frac{fy}{f_{xe}} \leq 0.170 \cr &= \left( 1.047 - 0.274 \frac{f_y}{f_{xe}} \right) f_y \;\;\; \text{for} \;\; \frac{fy}{f_{xe}} > 0.170 \end{aligned} $$

$$ f_{xe} = \frac{2 C_x E t}{D} $$

Quick digression: While checking these above expressions for this note, I think I uncovered an error in the latest ISO 19902:2020 standard. Notice the conditional statements in equations 13.2-8 and 13.2-9 in the screenshot below.

Conditional statement error uncovered in Eq. 13.2-9, ISO 19902:2020.
Conditional statement error uncovered in Eq. 13.2-9, ISO 19902:2020.

The conditional statement in equation 13.2-9 should instead be (fy / fxe > 0.170), otherwise both conditionals (i.e., in 13.2-8 and 13.2-9) mean (about) the same. 🙃 It looks like an editorial mix-up.

Anyway, back to my braces. For a set of brace sizes (selecting one in each bay), the script lets me check their slenderness. And sure enough, three out of the four braces exceed the criteria for ductile design, resulting in premature buckling, as the figure above shows.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Determine tube slenderness
slenderness.py -- 2021 ckunte
"""
import numpy as np


# Tube section properties (A, I, r)
def secprop(D, t):
    # Area of cross section
    A = list(map(lambda x, y: np.round(np.pi * (x - y) * y, 1), D, t))
    # Moment of Inertia
    I = list(
        map(
            lambda x, y: np.round((np.pi / 64.0) * (x ** 4 - (x - 2 * y) ** 4), 1), D, t
        )
    )
    # Radius of gyration
    r = list(map(lambda x, y: np.round(np.sqrt(x / y), 3), I, A))
    return A, I, r


# Representative elastic local buckling strength (fxe)
def rep_elastic_local_buckling_strength(Cx, D, E, t):
    return list(map(lambda x, y: np.round((2.0 * Cx * E * y / x), 1), D, t))


# Representative local buckling strength (fyc)
def rep_local_buckling_strength(fy, fxe):
    fyc_all = []
    for i in fxe:
        if (fy / i) <= 0.170:
            fyc_all.append(fy)
        elif (fy / i) > 0.170:
            fyc_all.append(np.round((1.047 - 0.274 * fy / i) * fy), 1)
        else:
            print("Condition not satisfied.")
    return fyc_all


# Slenderness parameters
def slenderness_param(fyc, fy, D, E, t, K, L, r):
    # D/t
    d_over_t = list(map(lambda x, y: (x / y), D, t))
    # Get tube slenderness results
    klr = list(map(lambda x, y: np.round((K * x / y), 1), L, r))
    # Column buckling parameter lmbda, see 13.2.3.2, ISO 19902
    lmbda = list(map(lambda x, y: np.round((x / np.pi) * np.sqrt(y / E), 3), klr, fyc))
    # Limiting parameter 1 as per ISO 19902, Sec. 11.4
    p1 = list(map(lambda x: np.round((80.0 / np.pi) * np.sqrt(x / E), 3), fyc))
    # Limiting parameter 2 as per ISO 19902, Sec. 11.4
    p2 = list(map(lambda x, y: np.round(fy * x / (E * y), 3), D, t))
    return d_over_t, klr, lmbda, p1, p2


def main():
    # -- BEGIN USER INPUTS --
    # Yield strength of steel (S420) in MPa
    fy = 400.0
    # Modulus of elasticity (Young's modulus) for structural steel (N/mm^2)
    E = 2.05e5
    # Tube diameters (mm)
    D = [1300.0, 900.0, 1000.0, 1200.0]
    # Tube wall thicknesses (mm)
    t = [50.0, 20.0, 20.0, 30.0]
    # Tube lengths (mm)
    L = [20518.0, 52151.0, 59685.0, 77500.0]
    # Effective length factor (Table 13.5-1, ISO 19902)
    K = 0.7
    # Elastic critical buckling coefficient
    Cx = 0.3  # Recommended value in Sec. 13.2.3.3, ISO 19902
    # -- END of USER INPUTS --
    A, I, r = secprop(D, t)
    fxe = rep_elastic_local_buckling_strength(Cx, D, E, t)
    fyc = rep_local_buckling_strength(fy, fxe)
    sp = slenderness_param(fyc, fy, D, E, t, K, L, r)
    # Labels list
    labels = [
        'D (mm)            ',
        't (mm)            ',
        'L (mm)            ',
        'A (mm^2)          ',
        'I (mm^4)          ',
        'r (mm)            ',
        'fy (MPa)          ',
        'fxe (MPa)         ',
        'fyc (MPa)         ',
        'D/t               ',
        'KL/r (NTE 80)     ',
        'lambda            ',
        'lambda (NTE)      ',
        'fyD/Et (NTE 0.069)',
    ]
    # Data and results list
    data_res = [D, t, L, A, I, r, fy, fxe, fyc, sp[0], sp[1], sp[2], sp[3], sp[4]]
    # Print results
    for i, j in zip(labels, data_res):
        print(i + " =", j)
        pass
    pass


if __name__ == "__main__":
    main()

Producing the following:

D (mm)             = [1300.0, 900.0, 1000.0, 1200.0]
t (mm)             = [50.0, 20.0, 20.0, 30.0]
L (mm)             = [20518.0, 52151.0, 59685.0, 77500.0]
A (mm^2)           = [196349.5, 55292.0, 61575.2, 110269.9]
I (mm^4)           = [38410878928.7, 5355033173.6, 7395183442.8, 18880963994.1]
r (mm)             = [442.295, 311.207, 346.555, 413.793]
fy (MPa)           = 400.0
fxe (MPa)          = [4730.8, 2733.3, 2460.0, 3075.0]
fyc (MPa)          = [400.0, 400.0, 400.0, 400.0]
D/t                = [26.0, 45.0, 50.0, 40.0]
KL/r (NTE 80)      = [32.5, 117.3, 120.6, 131.1]
lambda             = [0.457, 1.649, 1.696, 1.843]
lambda (NTE)       = [1.125, 1.125, 1.125, 1.125]
fyD/Et (NTE 0.069) = [0.051, 0.088, 0.098, 0.078]

From above results, clearly the only member that is not considered slender is the one with size, 1,300×50×20518. The last three tubes exhibit some form of slenderness — mostly on account of length, and may warrant suitable resizing.

The lambda (in programming) is python’s built-in anonymous function I use to power through lists, which should not be confused with λ – the column buckling parameter, the latter corresponds to lmbda in the script — note the intentional spelling change to avoid the built-in function clashing with the formula.