--- jupyter: description: 'Open and closed sections in torsion with planex2d and NGSolve: a thin tube and the same tube slit along its length, the torsion constant against pi (Ro^4 - Ri^4)/2, Bredt''s formula and s t^3/3, the stiffness ratio 3 (R/t)^2 and the shear stress, from the warping function of each section.' --- # Open and closed sections in torsion Why does a slit tube twist so much more easily than a closed one? A thin tube slit along its length keeps almost all of its material but loses almost all of its torsional stiffness. In the closed tube, the shear stress runs around the wall as one shear flow, and Bredt's formula gives the torsion constant $J \approx 2\pi R^3 t$, for the mean radius $R$ and the wall thickness $t$. In the slit tube, the stress runs along one face of the wall and back along the other, and $J \approx s t^3/3$, for the length $s$ of the wall's midline. The closed tube is about $3(R/t)^2$ times as stiff, which is why closed box sections carry torsion in frames and bridges, and why a slit tube can serve as a flexure hinge that twists easily. The example solves Saint-Venant torsion for a tube with a mean radius of 25 and walls of 5, 2.5 and 1.25, closed and slit. The closed tube's $J$ must equal $\pi (R_o^4 - R_i^4)/2$ exactly, the slit tube's must approach the thin-walled value, and the ratios of their stiffness and of their largest shear stress must approach $3(R/t)^2$ and $3R/t$. ![The shear stress in a closed tube and in the same tube slit, under the same torque](../_static/gallery/torsion-open-closed.png){.result} ```python import math import ngsolve as ngs import planex as px import planex.measurements as pm ``` ```python nbsphinx="hidden" import matplotlib.pyplot as plt from docs_figures import Row ``` ## The sections A tube is a disc less a smaller disc, and the slit tube is the same tube less a rectangle across its wall, as wide as the wall is thick (Figure 1): ```python R = 25 # the mean radius def tube(t, slit=False): """the section of a tube of wall thickness t, closed or slit along its length""" section = px.Circle((0, 0), R + t / 2).Face() - px.Circle((0, 0), R - t / 2).Face() if slit: section = section - px.QuickSketch((R - t, -t / 2)).Rectangle(2 * t, t).Face() return section print("closed", tube(2.5).mass, "| slit", tube(2.5, slit=True).mass, "| the slit keeps", tube(2.5, True).mass / tube(2.5).mass) ``` ```python nbsphinx="hide-input" Row((tube(2.5), "Closed"), (tube(2.5, slit=True), "Slit"), caption="A tube with a wall of 2.5, closed and slit") ``` ## The torsion constant `pm.TorsionConstant()` solves for the warping function of a section, the axial displacement of its points per unit of twist, and integrates $J$ from it, holes included. The circular tube is the one hollow section that does not warp, and its $J$ is exactly $\pi (R_o^4 - R_i^4)/2$, where Bredt's formula $4A^2 t/s$, for the area $A$ inside the midline, gives $2\pi R^3 t$. The slit tube's $J$ is that of a thin curved strip of length $s = 2\pi R - t$, $s t^3/3$, less the share of its two ends, which a thin rectangle has as the factor $1 - 0.630\,t/s$. Both are compared with these values, and their ratio with $3(R/t)^2$: ```python J = {} for t in (5, 2.5, 1.25): J[t] = tube(t).Measure(pm.TorsionConstant()), tube(t, slit=True).Measure(pm.TorsionConstant()) s = 2 * math.pi * R - t print("t", t, "| closed", round(J[t][0], 1), "exact", round(math.pi / 2 * ((R + t / 2) ** 4 - (R - t / 2) ** 4), 1), "Bredt", round(2 * math.pi * R**3 * t, 1)) print(" | slit", round(J[t][1], 2), "thin-walled", round(s * t**3 / 3 * (1 - 0.630 * t / s), 2), "| ratio", round(J[t][0] / J[t][1], 1), "3(R/t)²", 3 * (R / t) ** 2) ``` The thinner the wall, the closer the ratio comes to $3(R/t)^2$. At a wall of a twentieth of the radius, the closed tube is over a thousand times as stiff as the slit one. ## The shear stress The shear stress follows from the warping function $\omega$ as $\tau = G\theta\,(\partial\omega/\partial x - y, \partial\omega/\partial y + x)$, about the section's centroid, where $\theta$ is the twist per unit length. Under a torque $T$, $G\theta = T/J$. `shear` solves Laplace's equation for $\omega$ with the boundary condition $\partial\omega/\partial n = y\,n_x - x\,n_y$ on every edge, as `pm.TorsionConstant` does, and returns the magnitude of $\tau$ for a unit torque. In the closed tube, the stress is about $T/(2At)$, almost the same across the wall. In the slit tube, it changes sign across the wall and reaches about $T t/J$ at its faces, $3R/t$ times as much. The largest stress in each is printed, and their ratio is compared with $3R/t$: ```python def shear(section, t, order=4): """the shear stress for a unit torque, its mesh and its largest value""" mesh = ngs.Mesh(px.OCCGeometry(section).GenerateMesh(maxh=t / 2)) mesh.Curve(order) area = ngs.Integrate(1, mesh) X = ngs.x - ngs.Integrate(ngs.x, mesh) / area Y = ngs.y - ngs.Integrate(ngs.y, mesh) / area fes = ngs.H1(mesh, order=order) u, v = fes.TnT() n = ngs.specialcf.normal(2) a = ngs.BilinearForm(ngs.grad(u) * ngs.grad(v) * ngs.dx + 1e-10 * u * v * ngs.dx).Assemble() f = ngs.LinearForm((Y * n[0] - X * n[1]) * v * ngs.ds).Assemble() w = ngs.GridFunction(fes) w.vec.data = a.mat.Inverse(fes.FreeDofs(), inverse="sparsecholesky") * f.vec dx, dy = ngs.grad(w) J = ngs.Integrate(X * X + Y * Y + X * dy - Y * dx, mesh) tau = ngs.sqrt((dx - Y) ** 2 + (dy + X) ** 2) / J points = mesh.MapToAllElements(ngs.IntegrationRule(ngs.TRIG, 2 * order), mesh.Materials(".*")) return tau, mesh, tau(points).flatten().max() stresses = {} for t in (5, 2.5, 1.25): stresses[t] = shear(tube(t), t), shear(tube(t, slit=True), t) closed, slit = stresses[t][0][2], stresses[t][1][2] print("t", t, "| closed", closed, "Bredt", 1 / (2 * math.pi * R**2 * t), "| slit", slit, "| ratio", round(slit / closed, 2), "3R/t", 3 * R / t) ``` For the wall of 5, under the same torque and on the same color scale, the closed tube's stress hardly shows. In the slit tube, the stress runs along the inner face one way and along the outer face the other way, through zero in the middle of the wall: ```python nbsphinx="hide-input" top = stresses[5][1][2] fig, axes = plt.subplots(1, 2, figsize=(11, 5)) for ax, (tau, mesh, peak), name, section in zip(axes, stresses[5], ("Closed", "Slit"), (tube(5), tube(5, slit=True))): px.PlotField(tau, mesh, section, ax=ax, min=0, max=top, colormap="default_r") ax.set_title(f"{name}, largest shear stress {peak:.2e} per unit torque") plt.show() ``` See [Part analysis](../core/measuring/analysis.md) for `pm.TorsionConstant` among the other measurements and [Field solvers as measurements](../integrations/netgen/field-solvers.md) for measurements that solve a field. ```python nbsphinx="hidden" import sys sys.path.insert(0, "..") from gallery import save_figure fig, axes = plt.subplots(1, 2, figsize=(6.4, 3.3)) for ax, (tau, mesh, peak), section in zip(axes, stresses[5], (tube(5), tube(5, slit=True))): px.PlotField(tau, mesh, section, ax=ax, min=0, max=top, colormap="default_r") save_figure(fig, "torsion-open-closed", bare=True, panels=[0, 1], bars={3: "shear stress / torque (1/mm³)"}) plt.close(fig) ```