|
1 | 1 | ---
|
2 |
| -title: "Linearized Buckling" |
3 |
| -tags: ["Python", "Tcl", "Frame"] |
| 2 | +#title: "Linearized Buckling" |
| 3 | +title: "Column Buckling" |
| 4 | +meta: |
| 5 | + title: "A nonlinear buckling simulation of a column with varied boundary conditions and finite element formulations" |
| 6 | +tags: ["Frame"] |
4 | 7 | #render: ./model.glb
|
5 |
| -description: Corotational frame elements are used to approximate Euler's buckling load. |
| 8 | +description: >- |
| 9 | + This example performs a nonlinear buckling analysis of a column under axial load, |
| 10 | + using various element formulations and end conditions. |
6 | 11 | downloads:
|
7 | 12 | Python: ["buckling.py"]
|
8 | 13 | Tcl: ["buckling.tcl"]
|
| 14 | +weight: 20 |
9 | 15 | ---
|
10 | 16 |
|
11 | 17 |
|
12 | 18 | ## Problem
|
13 | 19 |
|
14 |
| -Corotational frame elements are used to approximate Euler's buckling load which is given by: |
| 20 | +This example analyzes a column subject to axial loading until buckling occurs. |
| 21 | +Different element types, shear deformation settings, and boundary conditions are compared |
| 22 | +by computing the critical load and comparing it to the theoretical Euler load which is given by: |
15 | 23 |
|
16 | 24 | \[
|
17 | 25 | P_{\mathrm{euler}} = \frac{\pi^2 EI}{L^2}
|
|
57 | 65 | $$
|
58 | 66 | \tan \lambda_{\text {cr }}=\chi \lambda_{\text {cr }}=\frac{\lambda_{\text {cr }}}{1+\lambda_{\text {cr }} 2 \varphi / 12}
|
59 | 67 | $$
|
| 68 | + |
| 69 | +## Implementation |
| 70 | + |
| 71 | + |
| 72 | +## Model |
| 73 | + |
| 74 | +We begin by importing the required modules and defining some material and section properties. |
| 75 | + |
| 76 | +{{< tabs tabTotal="2" >}} |
| 77 | +{{% tab name="Python" %}} |
| 78 | +```python |
| 79 | +import opensees.openseespy as ops |
| 80 | +import numpy as np |
| 81 | +from math import pi |
| 82 | + |
| 83 | +FACTORS = { |
| 84 | + "pin-pin": 1, |
| 85 | + "fix-roll": 1, |
| 86 | + "fix-fix": 0.5, |
| 87 | + "fix-pin": 0.7, |
| 88 | + "fix-free": 2, |
| 89 | + "pin-roll": 2, |
| 90 | +} |
| 91 | +``` |
| 92 | +{{% /tab %}} |
| 93 | +{{< /tabs >}} |
| 94 | + |
| 95 | +We define a function `create_column` that constructs the finite element model of the column |
| 96 | +based on options like element type, shear deformation flag, and spatial dimension: |
| 97 | + |
| 98 | +{{< tabs tabTotal="2" >}} |
| 99 | +{{% tab name="Python" %}} |
| 100 | +```python |
| 101 | +def create_column(boundary="pin-pin", elem_data=None, ndm=2): |
| 102 | + if elem_data is None: |
| 103 | + elem_data = {} |
| 104 | + |
| 105 | + elem_type = elem_data.get("type", "forceBeamColumnCBDI") |
| 106 | + geom_type = elem_data.get("transform", "Corotational") |
| 107 | + use_shear = elem_data.get("shear", False) |
| 108 | + kinematics = elem_data.get("order", 0) |
| 109 | + |
| 110 | + E = 29000.0 |
| 111 | + G = 11200.0 |
| 112 | + A = 112.0 |
| 113 | + I = 110.0 |
| 114 | + Ay = 3/6*A |
| 115 | + Az = 3/6*A |
| 116 | + L = 60.0 |
| 117 | + ne = 10 |
| 118 | + nIP = 5 |
| 119 | + |
| 120 | + model = ops.Model(ndm=ndm) |
| 121 | + |
| 122 | + for i in range(1, ne+2): |
| 123 | + y = (i-1)/float(ne)*L |
| 124 | + location = (0.0, y, 0.0) if ndm == 3 else (0.0, y) |
| 125 | + model.node(i, location) |
| 126 | + model.mass(i, *[1.0]*model.getNDF()) |
| 127 | + |
| 128 | + fix_node(model, 1, boundary.split("-")[0]) |
| 129 | + fix_node(model, ne+1, boundary.split("-")[1]) |
| 130 | +``` |
| 131 | +{{% /tab %}} |
| 132 | +{{< /tabs >}} |
| 133 | + |
| 134 | +The section is defined as an `ElasticFrame` and assigned to each element in the column: |
| 135 | + |
| 136 | +{{< tabs tabTotal="2" >}} |
| 137 | +{{% tab name="Python" %}} |
| 138 | +```python |
| 139 | + sec_tag = 1 |
| 140 | + properties = [E, A, I] |
| 141 | + if ndm == 3: |
| 142 | + properties += [2*I, "-J", 100*I, "-G", G] |
| 143 | + if use_shear: |
| 144 | + properties += ["-Ay", Ay, "-G", G] |
| 145 | + if ndm == 3: |
| 146 | + properties += ["-Az", Az] |
| 147 | + model.section("ElasticFrame", sec_tag, *properties) |
| 148 | + |
| 149 | + geo_tag = 1 |
| 150 | + vector = (0, 0, 1) if ndm == 3 else () |
| 151 | + model.geomTransf(geom_type, geo_tag, *vector) |
| 152 | + |
| 153 | + for i in range(1, ne+1): |
| 154 | + model.element(elem_type, i, (i, i+1), |
| 155 | + section=sec_tag, |
| 156 | + transform=geo_tag, |
| 157 | + order=kinematics, |
| 158 | + shear=int(use_shear)) |
| 159 | +``` |
| 160 | +{{% /tab %}} |
| 161 | +{{< /tabs >}} |
| 162 | + |
| 163 | +The axial load is applied at the top node, using the Euler buckling expression as a reference: |
| 164 | + |
| 165 | +{{< tabs tabTotal="2" >}} |
| 166 | +{{% tab name="Python" %}} |
| 167 | +```python |
| 168 | + if use_shear: |
| 169 | + phi = 12*E*I/(Ay*G*L**2) |
| 170 | + lam = buckle_factor(boundary, phi) |
| 171 | + kL = L/lam |
| 172 | + euler_load = E*I/kL**2 / (1 + lam**2*phi/12) |
| 173 | + else: |
| 174 | + kL = L / buckle_factor(boundary) |
| 175 | + euler_load = E*I/kL**2 |
| 176 | + |
| 177 | + model.pattern("Plain", 1, "Linear") |
| 178 | + load = (0.0, -euler_load, 0.0) if ndm == 2 else (0.0, -euler_load, 0.0, 0, 0, 0) |
| 179 | + model.load(ne+1, *load, pattern=1) |
| 180 | + |
| 181 | + return model, euler_load |
| 182 | +``` |
| 183 | +{{% /tab %}} |
| 184 | +{{< /tabs >}} |
| 185 | + |
| 186 | +## Buckling Analysis |
| 187 | + |
| 188 | +A nonlinear static analysis is performed to determine the limit load. The first |
| 189 | +eigenvalue of the tangent stiffness matrix is tracked and interpolated to find the |
| 190 | +load factor at which it reaches zero. |
| 191 | + |
| 192 | +{{< tabs tabTotal="2" >}} |
| 193 | +{{% tab name="Python" %}} |
| 194 | +```python |
| 195 | +def buckling_analysis(model, peak_load): |
| 196 | + load_step = 0.01 |
| 197 | + PeakLoadRatio = 1.5 |
| 198 | + |
| 199 | + model.system('UmfPack') |
| 200 | + model.test("EnergyIncr", 1e-8, 20, 9) |
| 201 | + model.algorithm("Newton") |
| 202 | + model.integrator("LoadControl", load_step) |
| 203 | + model.analysis("Static") |
| 204 | + |
| 205 | + lam_0 = model.getTime() |
| 206 | + eig_0 = model.eigen("-fullGenLapack", 1)[0] |
| 207 | + |
| 208 | + limit_load = None |
| 209 | + for i in range(1, int(PeakLoadRatio/load_step)+1): |
| 210 | + if model.analyze(1) != 0: |
| 211 | + break |
| 212 | + lam = model.getTime() |
| 213 | + eig = model.eigen("-fullGenLapack", 1)[0] |
| 214 | + if eig <= 0.0: |
| 215 | + lam_i = lam_0 + (lam - lam_0)*eig_0/(eig_0-eig) |
| 216 | + limit_load = lam_i * peak_load |
| 217 | + break |
| 218 | + lam_0 = lam |
| 219 | + eig_0 = eig |
| 220 | + |
| 221 | + return limit_load |
| 222 | +``` |
| 223 | +{{% /tab %}} |
| 224 | +{{< /tabs >}} |
| 225 | + |
| 226 | +## Results |
| 227 | + |
| 228 | +The following script compares element formulations and boundary conditions in 3D with and without shear deformation: |
| 229 | + |
| 230 | +{{< tabs tabTotal="2" >}} |
| 231 | +{{% tab name="Python" %}} |
| 232 | +```python |
| 233 | +if __name__ == "__main__": |
| 234 | + for ndm in (3,): |
| 235 | + for shear in (False, True): |
| 236 | + for elem in ("PrismFrame", "ForceFrame", "ExactFrame"): |
| 237 | + print(f"\n{elem:10} Shear Order Theory Computed Error") |
| 238 | + for boundary in FACTORS: |
| 239 | + orders = (0,) |
| 240 | + for order in orders: |
| 241 | + if not shear and "Exact" in elem: |
| 242 | + continue |
| 243 | + elem_data = { |
| 244 | + "type": elem, |
| 245 | + "shear": shear, |
| 246 | + "order": order, |
| 247 | + "transform": "Corotational" |
| 248 | + } |
| 249 | + model, euler_load = create_column(boundary, elem_data, ndm=ndm) |
| 250 | + limit_load = buckling_analysis(model, euler_load) |
| 251 | + model.wipe() |
| 252 | + del model |
| 253 | + print(f" {boundary:10} {shear:8} {order:8} ", end="") |
| 254 | + if limit_load is None: |
| 255 | + print("No singularity found.") |
| 256 | + else: |
| 257 | + err = 100*(limit_load/euler_load - 1) |
| 258 | + print(f"{euler_load:10.2f} {limit_load:10.2f} {err:10.3f} %") |
| 259 | +``` |
| 260 | +{{% /tab %}} |
| 261 | +{{< /tabs >}} |
| 262 | + |
| 263 | + |
| 264 | +### Euler |
| 265 | + |
| 266 | +| Boundary | Critical Load | |
| 267 | +|-------------|---------------| |
| 268 | +| pin-pin | 8745.57 | |
| 269 | +| fix-roll | 8745.57 | |
| 270 | +| fix-fix | 34982.26 | |
| 271 | +| fix-pin | 17891.23 | |
| 272 | +| fix-free | 2186.39 | |
| 273 | +| pin-roll | 2186.39 | |
| 274 | + |
| 275 | +PrismFrame |
| 276 | + |
| 277 | +| Boundary | Computed | Error | |
| 278 | +|-------------|---------------|-----------| |
| 279 | +| pin-pin | 8841.80 | 1.100 % | |
| 280 | +| fix-roll | 8841.80 | 1.100 % | |
| 281 | +| fix-fix | 36559.09 | 4.507 % | |
| 282 | +| fix-pin | 18296.87 | 2.267 % | |
| 283 | +| fix-free | 2192.37 | 0.273 % | |
| 284 | +| pin-roll | 2192.37 | 0.273 % | |
| 285 | + |
| 286 | +ForceFrame |
| 287 | + |
| 288 | +| Boundary | Computed | Error | |
| 289 | +|-------------|------------|----------| |
| 290 | +| pin-pin | 8841.80 | 1.100 % | |
| 291 | +| fix-roll | 8841.80 | 1.100 % | |
| 292 | +| fix-fix | 36559.09 | 4.507 % | |
| 293 | +| fix-pin | 18296.87 | 2.267 % | |
| 294 | +| fix-free | 2192.37 | 0.273 % | |
| 295 | +| pin-roll | 2192.37 | 0.273 % | |
| 296 | + |
| 297 | +### Shear |
| 298 | + |
| 299 | +PrismFrame |
| 300 | + |
| 301 | +| Boundary | Computed | Error | |
| 302 | +|-----------|------------|-----------| |
| 303 | +| pin-pin | 8718.89 | 1.085 % | |
| 304 | +| fix-roll | 8718.88 | 1.085 % | |
| 305 | +| fix-fix | 34545.22 | 4.259 % | |
| 306 | +| fix-pin | 17727.65 | 2.192 % | |
| 307 | +| fix-free | 2184.73 | 0.272 % | |
| 308 | +| pin-roll | 2184.73 | 0.273 % | |
| 309 | + |
| 310 | +ForceFrame |
| 311 | + |
| 312 | +| Boundary | Computed | Error | |
| 313 | +|-----------|------------|-----------| |
| 314 | +| pin-pin | 8718.89 | 1.085 % | |
| 315 | +| fix-roll | 8718.88 | 1.085 % | |
| 316 | +| fix-fix | 34545.22 | 4.259 % | |
| 317 | +| fix-pin | 17727.65 | 2.192 % | |
| 318 | +| fix-free | 2184.73 | 0.272 % | |
| 319 | +| pin-roll | 2184.73 | 0.273 % | |
| 320 | + |
| 321 | +ExactFrame |
| 322 | + |
| 323 | +| Boundary | Computed | Error | |
| 324 | +|-----------|------------|-----------| |
| 325 | +| pin-pin | 8792.02 | 1.933 % | |
| 326 | +| fix-roll | 8792.01 | 1.933 % | |
| 327 | +| fix-fix | 35773.31 | 7.965 % | |
| 328 | +| fix-pin | 18068.91 | 4.159 % | |
| 329 | +| fix-free | 2189.24 | 0.480 % | |
| 330 | +| pin-roll | 2189.25 | 0.480 % | |
| 331 | + |
| 332 | + |
| 333 | +| Boundary | Critical Load | |
| 334 | +|-----------|------------| |
| 335 | +| pin-pin | 8625.30 |
| 336 | +| fix-roll | 8625.30 |
| 337 | +| fix-fix | 33134.20 |
| 338 | +| fix-pin | 17347.40 |
| 339 | +| fix-free | 2178.80 |
| 340 | +| pin-roll | 2178.80 |
0 commit comments