Homogenized geometric properties

This page documents the output produced by the geometry sub-package when querying the geometric properties of a GenericSection. All quantities are computed on the homogenized section (sometimes called ideal or transformed section). Mono-material sections are the natural degenerate case.

Note

Properties of this section are evaluated in the elastic regime, so no cracking or any other phenomena is accounted for. For ELS and ULS verifications, the non-linear solver must be used to compute the actual response of the section under the applied loads.

Homogenization convention

GenSec follows the EC2 / NTC 2018 convention for the homogenized section. Given a reference modulus \(E_{\mathrm{ref}}\), the polygon area is scaled by

\[n_{\mathrm{bulk}} = \frac{E_{\mathrm{bulk}}}{E_{\mathrm{ref}}},\]

and every point fiber (rebar, tendon, FRP strip) of area \(A_s\) and modulus \(E_s\) contributes with its differential area

\[\Delta A_{s,\mathrm{id}} = \bigl(n_s - n_{\mathrm{bulk}}\bigr)\, A_s,\qquad n_s = \frac{E_s}{E_{\mathrm{ref}}}.\]

The polygon therefore represents the continuous bulk region in full, and each rebar adds only the excess stiffness needed to avoid double-counting the substrate it physically displaces. This has three important consequences:

  • Mono-material degeneration. When every fiber has \(E_s = E_{\mathrm{bulk}}\), the factor \((n_s - n_{\mathrm{bulk}}) = 0\) and the result coincides with the pure polygon geometry.

  • Choice of reference. The default is \(E_{\mathrm{ref}} = E_{\mathrm{bulk}}\), giving \(n_{\mathrm{bulk}} = 1\) and the standard RC convention \(n_s = E_s / E_{\mathrm{cm}}\). A different reference can be selected by passing E_ref explicitly to compute_section_properties().

  • Schema stability. All output fields are always populated; no field is toggled by the presence or absence of rebars.

Method selection: polygon vs. fiber

GenSec uses two distinct integration machineries in two distinct parts of the pipeline:

  • the polygon method (closed-form ring integrals via Green’s theorem) for the purely geometric/inertial quantities of the SectionProperties dataclass — \(A\), \(S_x\), \(S_y\), \(I_x\), \(I_y\), \(I_{xy}\), extreme fiber distances, elastic and plastic section moduli, kern, and inertia ellipse;

  • the fiber method (domain discretization into small regions of approximately uniform stress) in the section solver, for the response integrals \(N, M_x, M_y\) under a given strain field and a non-linear constitutive law.

The separation is not arbitrary: each method is the right tool for one and only one of the two problems, and neither can replace the other cleanly.

Accuracy of the polygon method

For an integrand that is a polynomial in \(x\) and \(y\), Green’s theorem reduces a 2-D surface integral over a polygon \(\Omega\) to a 1-D circulation along its boundary:

\[\iint_{\Omega} P(x, y)\, \mathrm{d}A = \oint_{\partial\Omega} Q(x, y)\,\mathrm{d}\ell,\]

and on a polygonal boundary this circulation becomes a finite sum of monomials evaluated at the vertices. Every moment of order up to two — \(A\), \(S_x\), \(S_y\), \(I_{xx}\), \(I_{yy}\), \(I_{xy}\) — falls in this class. The result is therefore exact for a polygon with vertices at well-defined coordinates: no discretization error whatsoever, only the floating-point round-off of the summation.

The limitation is subtler. When the real section has curved boundaries (circles, annuli, fillets), the polygon is itself an approximation of the geometry, and the integrals are exact with respect to the polygon but approximate with respect to the true shape. For a circle discretized into \(N\) sides the relative error on the area scales as

\[\varepsilon_A \approx \frac{(2\pi)^2}{6\,N^2} = \frac{6.58}{N^2},\]

giving \(\sim 0.16\%\) for \(N = 64\) and \(\sim 0.01\%\) for \(N = 256\). Second moments and the plastic modulus scale similarly. In GenSec the polygon resolution is a user choice driven by Shapely’s resolution parameter when buffering.

For \(Z\) (plastic modulus) the integrand \(|y - y_{\mathrm{pna}}|\) is not a polynomial because of the absolute value, but the plastic neutral axis is a straight line that splits \(\Omega\) into two half-plane intersections; each half is a new polygon on which Green’s theorem is again exact. The only numerical error in \(Z\) is the bisection tolerance on \(y_{\mathrm{pna}}\) itself (currently \(10^{-10}\) relative on the homogenized area), which is orders of magnitude below any physical uncertainty.

Accuracy of the fiber method

The fiber method discretizes \(\Omega\) into small sub-domains \(\Omega_f\) and replaces every integral with a midpoint quadrature:

\[\iint_{\Omega} g(x, y)\, \mathrm{d}A \approx \sum_f g\bigl(x_f, y_f\bigr)\, A_f,\]

where \((x_f, y_f)\) is the centroid of fiber \(f\) and \(A_f\) its area. For a smooth integrand \(g\) the error of each fiber is \(O(h_f^{2}\,\nabla^{2} g)\), so the global error scales as \(O(h^{2})\) with \(h\) the characteristic fiber size. As a concrete reference, for a rectangular section \(B \times H\) discretized in \(N\) horizontal strips the relative error on \(I_x\) is \(1/N^{2}\): \(\sim 1\%\) for \(N = 10\), \(\sim 0.04\%\) for \(N = 50\). With a practical target of a few tenths of a percent, fiber sizes of a few millimetres are appropriate for typical RC members.

Fibers thus introduce a genuine discretization error that is always present, but they work for any integrand — including integrands that are not polynomial in \((x, y)\). This is what makes them indispensable downstream.

Why the two methods are not interchangeable

The decisive distinction is between linear and non-linear integrands along the depth \(y\).

  1. Geometric and elastic moments are monomials in \(y\): \(1\), \(y\), \(y^{2}\). The polygon method is exact and fast — two or three orders of magnitude faster than a fiber sweep on a typical section, because it touches only the vertices, not the interior.

  2. Constitutive response integrals involve the stress \(\sigma\bigl(\varepsilon(y)\bigr)\). Under the kinematic assumption of plane sections \(\varepsilon(y) = \varepsilon_0 + \chi_x\, y - \chi_y\, x\) is linear in the coordinates, but \(\sigma(\cdot)\) is emphatically not linear in \(\varepsilon\): EC2 concrete is parabola–rectangle, confined concrete is Sargin / Mander, reinforcing steel is bilinear with strain hardening, prestressing steel follows a Ramberg–Osgood law. There is no closed-form antiderivative of \(\sigma\bigl(\varepsilon_0 + \chi_x\, y - \chi_y\, x\bigr)\) that can be turned into a boundary circulation. Fibers are the only practical choice, and their \(O(h^{2})\) discretization error is accepted as the price of admission.

  3. Cracking makes the integration domain itself depend on the strain field: the effective region is \(\{(x, y) \in \Omega \,:\, \varepsilon(x, y) > \varepsilon_{\mathrm{cr}}\}\). The polygon must be re-clipped at every iteration, and the integrand is already non-linear — so one is firmly in fiber territory.

Conversely, a fiber-based calculation of \(I_x\) or \(Z_x\) would waste precision: it would converge to the polygon-exact value only in the limit \(h \to 0\), at a cost growing as \(1/h^{2}\). For the quantities collected in SectionProperties, the polygon method is both faster and more accurate — an unusual combination that justifies keeping the two machineries strictly separate.

Where the two methods meet

The two methods communicate through the centroid and the principal axes reported in SectionProperties. The solver translates the reference point of the applied action \((N, M_x, M_y)\) to the centroid and aligns the strain field with the principal frame when needed; the fiber integration then proceeds in a frame where \(I_{xy} = 0\). Accuracy of the centroid — which comes from the polygon method — therefore propagates into the accuracy of every solver output. A mismatch of a few microns in \(y_G\) has negligible effect on an \(N\)\(M\) envelope, but it would be visible in a first-cracking computation where the governing quantity is \(\varepsilon_{\mathrm{cr}} = f_{\mathrm{ctm}} / E_{\mathrm{cm}}\) — a small strain is amplified by the lever arm, so the centroid must be right.

For the same reason, the kern and the inertia ellipse — both derived from SectionProperties — are honest exact surrogates of the elastic behaviour of the homogenized section and can be used as early-stage checks before running the non-linear solver.

API reference

class HomogenizedRebar(
x: float,
y: float,
area: float,
E: float,
)

Minimal description of a point fiber for homogenization.

Parameters:
  • x (float) – Location in the user frame \([\mathrm{mm}]\).

  • y (float) – Location in the user frame \([\mathrm{mm}]\).

  • area (float) – Cross-sectional area \(A_s\,[\mathrm{mm}^2]\).

  • E (float) – Elastic modulus \(E_s\,[\mathrm{MPa}]\).

class SectionProperties(
E_ref: float,
E_bulk: float,
n_bulk: float,
area: float,
Sx: float,
Sy: float,
xg: float,
yg: float,
Ixx_o: float,
Iyy_o: float,
Ixy_o: float,
Ix: float,
Iy: float,
Ixy: float,
I_xi: float,
I_eta: float,
alpha: float,
rho_x: float,
rho_y: float,
rho_xi: float,
rho_eta: float,
I_polar: float,
is_convex: bool,
c_y_top: float,
c_y_bot: float,
c_x_left: float,
c_x_right: float,
c_xi_pos: float,
c_xi_neg: float,
c_eta_pos: float,
c_eta_neg: float,
W_x_top: float,
W_x_bot: float,
W_y_left: float,
W_y_right: float,
W_xi_pos: float,
W_xi_neg: float,
W_eta_pos: float,
W_eta_neg: float,
Z_x: float,
Z_y: float,
Z_xi: float,
Z_eta: float,
I_t: float | None = None,
)

Bundle of homogenized geometric properties of a cross-section.

All second-moment quantities are reported in \(\mathrm{mm}^4\), areas in \(\mathrm{mm}^2\), lengths in \(\mathrm{mm}\), and the principal-axis orientation angle in radians. All integral quantities (A, S, I, Z) are computed on the homogenized section, using the convention

\[\mathrm{d}A_{\mathrm{id}} = n_{\mathrm{bulk}}\,\mathrm{d}A \quad\text{(on the polygon)},\qquad \Delta A_{s,\mathrm{id}} = (n_s - n_{\mathrm{bulk}})\,A_s \quad\text{(per point fiber)},\]

with \(n_i = E_i / E_{\mathrm{ref}}\).

Variables:
  • E_ref (float) – Reference modulus used for homogenization.

  • E_bulk (float) – Elastic modulus of the polygon material.

  • n_bulk (float) – \(E_{\mathrm{bulk}} / E_{\mathrm{ref}}\) (= 1 by default).

  • area (float) – Homogenized area \(A_{\mathrm{id}}\).

  • Sy (Sx,) – Static moments about the user \(x, y\) axes through the origin.

  • yg (xg,) – Centroid of the homogenized section.

  • Ixy_o (Ixx_o, Iyy_o,) – Homogenized second-moments about the user origin.

  • Ixy (Ix, Iy,) – Homogenized centroidal second-moments in the user frame.

  • I_eta (I_xi,) – Homogenized principal centroidal second-moments \(I_\xi \ge I_\eta\).

  • alpha (float) – Rotation (CCW, radians) from the user \(x\) axis to the principal \(\xi\) axis, in \((-\pi/2, +\pi/2]\).

  • rho_eta (rho_x, rho_y, rho_xi,) – Radii of gyration.

  • I_polar (float) – \(I_p = I_x + I_y = I_\xi + I_\eta\).

  • is_convex (bool) – Whether the exterior ring is convex.

  • c_y_bot (c_y_top,) – Distances from the centroid to the extreme \(y\) fibers (always \(\ge 0\)). Polygon vertices and point-fiber positions are both considered.

  • c_x_right (c_x_left,) – Same for \(x\).

  • c_xi_neg (c_xi_pos,) – Distances to the extreme fibers along \(\xi\).

  • c_eta_neg (c_eta_pos,) – Distances to the extreme fibers along \(\eta\).

  • W_x_bot (W_x_top,) – Elastic section moduli for bending about \(x\): \(W_x^{\mathrm{top}} = I_x / c_y^{\mathrm{top}}\), \(W_x^{\mathrm{bot}} = I_x / c_y^{\mathrm{bot}}\).

  • W_y_right (W_y_left,) – Analogous for bending about \(y\).

  • W_xi_neg (W_xi_pos,) – Elastic moduli about the principal \(\xi\) axis: \(W_\xi = I_\xi / c_\eta\).

  • W_eta_neg (W_eta_pos,) – Elastic moduli about the principal \(\eta\) axis: \(W_\eta = I_\eta / c_\xi\).

  • Z_eta (Z_x, Z_y, Z_xi,) – Plastic section moduli of the homogenized section about the four reference axes through the centroid. The plastic neutral axis is the line that splits \(A_{\mathrm{id}}\) in two equal halves; \(Z\) is the sum of the absolute first moments of the two halves about the PNA.

  • I_t (float or None) – Torsional constant. Not yet computed (deferred to a future St.-Venant solver); kept in the schema so that JSON export and the future GUI have a stable layout.

compute_section_properties(
polygon: Polygon,
rebars: Sequence[HomogenizedRebar] | None = None,
E_bulk: float = 1.0,
E_ref: float | None = None,
compute_plastic: bool = False,
) SectionProperties

Compute the homogenized geometric properties of a section.

Every polygon area element contributes as \(n_{\mathrm{bulk}}\,\mathrm{d}A\), and every point fiber contributes as \((n_s - n_{\mathrm{bulk}}) A_s\). In the typical RC case one takes \(E_{\mathrm{ref}} = E_{\mathrm{bulk}} = E_{\mathrm{cm}}\), giving \(n_{\mathrm{bulk}} = 1\) and \(n_s = E_s / E_{\mathrm{cm}}\).

Parameters:
  • polygon (shapely.geometry.Polygon) – Section outline with any number of holes.

  • rebars (sequence of HomogenizedRebar, optional) – Point fibers. If None or empty, the section is treated as pure bulk material.

  • E_bulk (float, optional) – Elastic modulus of the polygon material. Default 1.0.

  • E_ref (float or None, optional) – Reference modulus. If None, defaults to E_bulk.

  • compute_plastic (bool, optional) – Whether to compute the plastic moduli. Default False.

Return type:

SectionProperties

Raises:

ValueError – If the polygon is empty / invalid / has non-positive area, or if any modulus is non-positive.

compute_inertia_ellipse(
props,
n_points=240,
)

Sample points on the central inertia ellipse (Culmann).

In the centroidal principal frame \((\xi, \eta)\),

\[\frac{\xi^2}{\rho_\eta^2} + \frac{\eta^2}{\rho_\xi^2} = 1.\]
Parameters:
Return type:

numpy.ndarray of shape (n_points, 2)

compute_kern_polygon(
polygon,
props,
)

Compute the central kern (core) of the cross-section.

Parameters:
Return type:

numpy.ndarray of shape (N+1, 2) or (0, 2)

Area, centroid and second-moments

The area of the homogenized section is

\[A_{\mathrm{id}} = n_{\mathrm{bulk}}\!\int_{\Omega}\!\mathrm{d}A + \sum_i \bigl(n_{s,i} - n_{\mathrm{bulk}}\bigr) A_{s,i},\]

where \(\Omega\) is the polygon and the sum runs over all point fibers. Static moments and second-moments follow the same additive structure. In practice the polygon integrals are evaluated in closed form via Green’s theorem on every ring (exterior CCW, holes CW):

\[\begin{split}A &= \tfrac{1}{2}\sum_i c_i, \qquad S_x = \tfrac{1}{6}\sum_i (y_i + y_{i+1})\, c_i,\\[2pt] S_y &= \tfrac{1}{6}\sum_i (x_i + x_{i+1})\, c_i,\\[2pt] I_{xx,O} &= \tfrac{1}{12}\sum_i (y_i^2 + y_i y_{i+1} + y_{i+1}^2)\, c_i,\\[2pt] I_{yy,O} &= \tfrac{1}{12}\sum_i (x_i^2 + x_i x_{i+1} + x_{i+1}^2)\, c_i,\\[2pt] I_{xy,O} &= \tfrac{1}{24}\sum_i (x_i y_{i+1} + 2 x_i y_i + 2 x_{i+1} y_{i+1} + x_{i+1} y_i)\, c_i,\end{split}\]

with \(c_i = x_i y_{i+1} - x_{i+1} y_i\).

Centroidal quantities are obtained by Huygens’ translation:

\[I_x = I_{xx,O} - A y_G^2,\qquad I_y = I_{yy,O} - A x_G^2,\qquad I_{xy} = I_{xy,O} - A x_G y_G.\]

Principal axes and radii of gyration

The principal centroidal second-moments and their rotation angle are the eigenvalues/eigenvectors of the centroidal inertia tensor:

\[I_{\xi,\eta} = \frac{I_x + I_y}{2} \pm \sqrt{\!\left(\frac{I_x - I_y}{2}\right)^{2} + I_{xy}^{2}},\qquad \alpha = \tfrac{1}{2}\operatorname{atan2}\bigl( -2 I_{xy},\, I_x - I_y\bigr),\]

with \(I_\xi \ge I_\eta\) and \(\alpha \in (-\pi/2, +\pi/2]\). Radii of gyration are \(\rho_\bullet = \sqrt{I_\bullet / A_{\mathrm{id}}}\).

Note

When \(I_x \approx I_y\) and \(I_{xy} \approx 0\) (isotropic inertia tensor — circle, annulus, square, regular polygons), \(\alpha\) is mathematically indeterminate. GenSec detects this case by checking that the Mohr radius is below \(10^{-10}\) times the mean of \(I_x, I_y\), and snaps \(\alpha = 0\) so the principal axes coincide with the user axes.

Extreme-fiber distances and elastic section moduli

For each of the four reference axes — user \(x, y\) and principal \(\xi, \eta\) — GenSec reports the two extreme fiber distances from the centroid:

\[c_y^{\mathrm{top}} = \max_i (y_i - y_G)^+,\qquad c_y^{\mathrm{bot}} = \max_i -(y_i - y_G)^-,\]

and analogously for \(x, \xi, \eta\). Both polygon vertices (exterior and interior rings) and point fibers are included in the maximum, so that a rebar sitting outside the polygon contour is correctly picked up as the outermost fiber.

The elastic section moduli follow the convention \(W = I / c\):

\[W_x^{\mathrm{top}} = \frac{I_x}{c_y^{\mathrm{top}}}, \qquad W_x^{\mathrm{bot}} = \frac{I_x}{c_y^{\mathrm{bot}}}, \qquad W_\xi^{\pm} = \frac{I_\xi}{c_\eta^{\pm}}, \qquad W_\eta^{\pm} = \frac{I_\eta}{c_\xi^{\pm}}.\]

Both sides are reported separately: asymmetric sections have distinct top/bottom moduli, and engineering practice normally selects the smaller of the two for resistance verifications.

Plastic section moduli

The plastic modulus \(Z\) of the homogenized section is computed about each of the four reference axes through the centroid by locating the plastic neutral axis (PNA) — the line that splits the homogenized area in two equal halves — and then summing the absolute first moments of the two halves about it:

\[A_{\mathrm{id}}^+(t_{\mathrm{pna}}) = A_{\mathrm{id}}^-(t_{\mathrm{pna}}) = \frac{A_{\mathrm{id}}}{2}, \qquad Z = \bigl|S_{\mathrm{id}}^+\bigr| + \bigl|S_{\mathrm{id}}^-\bigr|.\]

The PNA is found numerically by bisection on the offset \(t_{\mathrm{pna}}\). The polygon contribution is evaluated via Shapely intersection with a half-plane, and rebar contributions are summed analytically according to which side of the PNA each rebar falls on.

Important

The homogenized plastic modulus is a purely geometric quantity; it has direct engineering meaning only for mono-material sections (steel, timber, aluminium), where it combines with a uniform yield stress to give the plastic bending moment \(M_{\mathrm{pl}} = Z \sigma_y\). For reinforced concrete and other composite sections the actual ultimate moment must be evaluated with the fiber solver — the two constitutive laws of concrete and steel are not proportional, so the plastic-modulus approach no longer applies. GenSec still reports \(Z\) in all cases because it is a useful diagnostic quantity.

Torsional constant

The attribute SectionProperties.I_t is a placeholder that is currently always None. Computing \(I_t\) for an arbitrary shape requires solving the St.-Venant warping problem

\[\nabla^{2}\psi = -2 \quad\text{in }\Omega,\qquad \psi = 0 \quad\text{on }\partial\Omega,\qquad I_t = 2\int_{\Omega}\!\psi\,\mathrm{d}A,\]

which in turn requires a 2-D FEM mesher and a Poisson solver. The solver is planned for a future development phase; the field is kept in the dataclass now so that JSON exports and downstream consumers (including the future GUI) have a stable schema.

For common shapes closed-form formulas are available (rectangle: \(I_t = k_1\,b t^3\); circle: \(I_t = \pi R^4 / 2\); thin-walled closed: Bredt; thin-walled open: \(I_t = \tfrac{1}{3}\sum_i b_i t_i^3\)). These will be provided as helper functions callable by name once the main solver lands.

Kern of the cross-section

The central kern is the antipolar dual of the exterior’s convex hull with respect to the central inertia ellipse. For each edge of the hull with outward unit normal \(\mathbf{n}\) and signed distance \(d > 0\) from the centroid, the associated kern vertex in the principal frame is

\[\xi_p = -\rho_\eta^{2}\, n_\xi / d,\qquad \eta_p = -\rho_\xi^{2}\, n_\eta / d.\]

Warning

When the exterior is non-convex, the algorithm returns the kern of the convex hull — this is an upper bound of the true kern and may be noticeably too large. The SectionProperties.is_convex flag is provided so that the plot and the report can warn the user explicitly.

Example

from shapely.geometry import box
from gensec.geometry.properties import (
    compute_section_properties, HomogenizedRebar,
)

# RC rectangle 300×500 with 4φ20 symmetric rebars.
poly = box(0, 0, 300, 500)
As = 3.14159 * 20 ** 2 / 4.0
rebars = [
    HomogenizedRebar( 40,  40, As, 200_000.0),
    HomogenizedRebar(260,  40, As, 200_000.0),
    HomogenizedRebar( 40, 460, As, 200_000.0),
    HomogenizedRebar(260, 460, As, 200_000.0),
]
props = compute_section_properties(
    poly, rebars=rebars,
    E_bulk=30_000.0,   # E_cm of concrete [MPa]
)
print(f"A_id = {props.area:.1f} mm^2")
print(f"Ix   = {props.Ix:.3e} mm^4")
print(f"Z_x  = {props.Z_x:.3e} mm^3")