civilpy.structural.aashto.lrfd package

AASHTO LRFD Bridge Design Specifications calculations: section resistance (steel, concrete, prestressed, timber), live-load distribution, splices, columns, railing, losses, and load rating (LRFR).

Submodules

civilpy.structural.aashto.lrfd.appendix_a6 module

AASHTO LRFD Appendix A6 — flexural resistance of straight composite I-sections in negative flexure with compact or noncompact webs.

Where 6.10.8 caps resistance at Rb*Rh*Fyc (stress format), A6 lets stockier sections reach up to Mp (moment format) through the web plastification factors Rpc/Rpt. Applicable when Fy <= 70 ksi, the web is not slender, and Iyc/Iyt >= 0.3. Units: kip, inch, ksi; moments kip-in.

civilpy.structural.aashto.lrfd.appendix_a6.a6_flange_local_buckling(b_fc: float, t_fc: float, d_web: float, t_w: float, f_yc: float, f_yw: float, f_yt: float, s_xc: float, s_xt: float, r_pc: float, m_yc: float, m_u: float | None = None, r_h: float = 1.0) CheckResult[source]

Compression-flange local buckling resistance Mnc in moment format (A6.3.2): the plateau Rpc*Myc for compact flanges, interpolated toward Fyr*Sxc using kc = 4/sqrt(D/tw) (0.35 <= kc <= 0.76) for noncompact.

civilpy.structural.aashto.lrfd.appendix_a6.a6_lateral_torsional_buckling(l_b: float, r_t: float, j_torsion: float, h_depth: float, f_yc: float, f_yw: float, f_yt: float, s_xc: float, s_xt: float, r_pc: float, m_yc: float, c_b: float = 1.0, m_u: float | None = None, r_h: float = 1.0) CheckResult[source]

Lateral torsional buckling resistance Mnc in moment format (A6.3.3), which credits the St. Venant stiffness J that 6.10.8.2.3 neglects.

r_t is the effective radius of gyration (in), j_torsion from st_venant_j(), h_depth the distance between flange centroids (in).

civilpy.structural.aashto.lrfd.appendix_a6.a6_tension_flange_yielding(r_pt: float, m_yt: float, m_u: float | None = None) CheckResult[source]

Tension-flange yielding resistance (A6.4-1): Mnt = Rpt*Myt.

civilpy.structural.aashto.lrfd.appendix_a6.st_venant_j(d_web: float, t_w: float, b_fc: float, t_fc: float, b_ft: float, t_ft: float) float[source]

St. Venant torsional constant (A6.3.3-9): J = D*tw^3/3 + sum(bf*tf^3/3 * (1 - 0.63*tf/bf)), in^4.

civilpy.structural.aashto.lrfd.appendix_a6.web_plastification_factors(d_c: float, d_cp: float, t_w: float, m_p: float, m_yc: float, m_yt: float, f_yc: float, r_h: float = 1.0) CheckResult[source]

Web plastification factors Rpc and Rpt (A6.2).

Compact webs (2*Dcp/tw within lambda_pw(Dcp), A6.2.1) reach the full plastic moment: Rpc = Mp/Myc, Rpt = Mp/Myt. Noncompact webs (A6.2.2) interpolate between Rh and Mp/My. d_c/d_cp are the elastic and plastic depths of web in compression (in). capacity holds Rpc; Rpt and the slenderness parameters are in details.

civilpy.structural.aashto.lrfd.appendix_b6 module

AASHTO LRFD Appendix B6 — moment redistribution from interior-pier sections of continuous-span steel I-girders.

Instead of designing every pier section for the full elastic envelope, B6 lets a limited share of the pier moment shift to the spans when the section can sustain inelastic rotation: the redistribution moment Mrd is the amount by which the elastic moment exceeds the effective plastic moment Mpe, capped at 20% of the elastic moment.

Scope (B6.2): straight continuous I-girders with Fy <= 70 ksi and web/flange/bracing limits enforced by the checks below. Units: kips, inches, ksi; moments kip-in.

civilpy.structural.aashto.lrfd.appendix_b6.b6_bracing_limit(r_t: float, f_yc: float, m1: float, m2: float, l_b: float | None = None) CheckResult[source]

Unbraced length limit adjacent to the pier (B6.2.4-1): Lb <= (0.1 - 0.06*(M1/M2)) * rt*E/Fyc.

m1/m2 are the smaller and larger moments at the brace points bounding the unbraced length (kip-in, signed — same sign for single curvature); r_t is the effective LTB radius of gyration (6.10.8.2.3-9, in). capacity is the allowed Lb (in).

civilpy.structural.aashto.lrfd.appendix_b6.b6_effective_plastic_moment(m_n: float, b_fc: float, t_fc: float, d: float, f_yc: float, limit_state: str = 'strength', stiffener_within_d_over_2: bool = False, d_cp: float | None = None, t_w: float | None = None) CheckResult[source]

Effective plastic moment Mpe of an interior-pier section (B6.5).

m_n is the section’s nominal negative-flexure resistance as a moment (min of the flange capacities from 6.10.8 or Appendix A6, kip-in). Sections with enhanced moment-rotation characteristics — a transverse stiffener within D/2 of the pier, or an ultracompact web with 2Dcp/tw <= 2.3*sqrt(E/Fyc) (B6.5.1-1) — reach Mpe = Mn at the service limit state (B6.5.1-2) and the 2.78-coefficient reduction at strength (B6.5.1-3); all other sections use the 2.90 (service, B6.5.2-1) or 2.63 (strength, B6.5.2-2) coefficient.

Pass d_cp (plastic depth of web in compression) and t_w to evaluate the ultracompact-web alternative; capacity is Mpe.

civilpy.structural.aashto.lrfd.appendix_b6.b6_flange_proportions(b_fc: float, t_fc: float, d: float, f_yc: float) CheckResult[source]

Compression flange limits for redistribution sections (B6.2.2): bfc/2tfc <= 0.38*sqrt(E/Fyc) (B6.2.2-1) and bfc >= D/4.25 (B6.2.2-2).

civilpy.structural.aashto.lrfd.appendix_b6.b6_redistribution_moment(m_e: float, m_pe: float, limit_state: str = 'strength', f_l: float = 0.0, s_x: float = 0.0) CheckResult[source]

Redistribution moment Mrd at an interior-pier section.

At the service limit state (B6.3.3.1): Mrd = |Me| - Mpe. At strength (B6.4.2.1): Mrd = |Me| + fl*Sx/3 - phi_f*Mpe, evaluated for each flange (pass the governing f_l/s_x; zero when flange lateral bending is negligible). In both cases 0 <= Mrd <= 0.2|Me| — when the computed Mrd exceeds the 20% cap, redistribution is not permitted and the section must satisfy the ordinary elastic checks (details["permitted"] is False).

m_e is the elastic pier moment from the factored envelope (kip-in, sign ignored); capacity is the usable Mrd (kip-in).

civilpy.structural.aashto.lrfd.appendix_b6.b6_web_proportions(d: float, t_w: float, d_c: float, d_cp: float, f_yc: float) CheckResult[source]

Web proportion limits for redistribution sections (B6.2.1): D/tw <= 150 (B6.2.1-1), 2Dc/tw <= 6.8*sqrt(E/Fyc) (B6.2.1-2), and Dcp <= 0.75D (B6.2.1-3). d_c/d_cp are the elastic and plastic depths of web in compression (in). capacity/demand report the governing utilization (limit and actual for the worst ratio); details["satisfied"] is the overall verdict.

civilpy.structural.aashto.lrfd.bolted_field_splice module

AASHTO LRFD 6.13.6.1 — bolted field-splice designer for steel plate girders.

Given the girder section on each side of a splice, the splice-centerline loads, and the bolt / splice-plate / clearance selections, this module sizes the flange and web bolt counts, lays out the bolt pattern (gage, pitch, edge, end) and splice-plate lengths, and runs the AASHTO limit-state checks by feeding the article-level primitives in civilpy.structural.aashto.lrfd.steel and civilpy.structural.aashto.lrfd.splices.

Units are kip, inch, ksi throughout (moments are supplied in kip-ft and converted internally). The design procedure follows the 8th/9th Edition simplified flange-force method (C6.13.6.1.3b, 6.13.6.1.3c); the bolt shear coefficient is the 8th-Edition value (0.56/0.45) via design_year.

The web bolt group is sized for the design shear combined with the horizontal force Hw from the portion of the moment the flanges cannot carry (6.13.6.1.3c): the excess of the factored moment over the flange moment resistance acts on a D/4 lever arm, Hw = (|Mu| - Mflange)/(D/4), and the web bolts resist the resultant of Hw and the shear. When the flanges carry the whole moment Hw is zero and the web is governed by the maximum-pitch (sealing) layout.

Known limitations mirrored from the reference procedure: AASHTO 6.10.1.8 (tension flanges with holes) is not checked; two-row seal-gage edge cases and rolled-beam splices with >10% inner/outer plate-area difference are flagged rather than resolved.

class civilpy.structural.aashto.lrfd.bolted_field_splice.BoltSpec(bolt_type: 'str' = 'A325', diameter: 'float' = 0.875, flange_threads_excluded: 'bool' = True, web_threads_excluded: 'bool' = False, surface_class: 'str' = 'B', hole_type: 'str' = 'standard')[source]

Bases: object

bolt_type: str = 'A325'
diameter: float = 0.875
flange_threads_excluded: bool = True
hole_type: str = 'standard'
surface_class: str = 'B'
web_threads_excluded: bool = False
class civilpy.structural.aashto.lrfd.bolted_field_splice.ComponentDesign(name: 'str', bolt_rows: 'int', total_bolts: 'int', strength_bolts: 'int', slip_bolts: 'int', controlling_bolts: 'int', design_force: 'float', gage_bolts: 'float' = 0.0, gage_groups: 'float' = 0.0, pitch: 'float' = 0.0, pitch_groups: 'float' = 0.0, edge: 'float' = 0.0, end: 'float' = 0.0, plate_thickness: 'float' = 0.0, plate_width: 'float' = 0.0, plate_length: 'float' = 0.0, long_joint: 'bool' = False, checks: 'list[CheckResult]' = <factory>, extra: 'dict' = <factory>)[source]

Bases: object

bolt_rows: int
checks: list[CheckResult]
controlling_bolts: int
design_force: float
edge: float = 0.0
end: float = 0.0
extra: dict
gage_bolts: float = 0.0
gage_groups: float = 0.0
long_joint: bool = False
name: str
property ok: bool
pitch: float = 0.0
pitch_groups: float = 0.0
plate_length: float = 0.0
plate_thickness: float = 0.0
plate_width: float = 0.0
slip_bolts: int
strength_bolts: int
total_bolts: int
class civilpy.structural.aashto.lrfd.bolted_field_splice.Flange(material: str, thickness: float, width: float)[source]

Bases: object

One flange of one girder side.

property area: float
material: str
thickness: float
width: float
class civilpy.structural.aashto.lrfd.bolted_field_splice.GirderSide(top_flange: Flange, bottom_flange: Flange, web_material: str, web_thickness: float, web_depth: float, haunch: float = 0.0, stiffener_spacing_ft: float | None = None, stiffened: bool = True)[source]

Bases: object

The plate-girder cross section on one side of the splice.

bottom_flange: Flange
haunch: float = 0.0
stiffened: bool = True
stiffener_spacing_ft: float | None = None
top_flange: Flange
web_depth: float
web_material: str
web_thickness: float
class civilpy.structural.aashto.lrfd.bolted_field_splice.PlatePair(material: str, inner_thickness: float, inner_width: float, outer_thickness: float, outer_width: float, shear_planes: int = 2)[source]

Bases: object

Inner + outer splice plates for a flange (user-selected, then checked).

property inner_area: float
inner_thickness: float
inner_width: float
material: str
property outer_area: float
outer_thickness: float
outer_width: float
shear_planes: int = 2
class civilpy.structural.aashto.lrfd.bolted_field_splice.SpliceDesign(factored_moments: 'dict', factored_shears: 'dict', top_flange: 'ComponentDesign', bottom_flange: 'ComponentDesign', web: 'ComponentDesign', spec: 'SpliceInput | None' = None)[source]

Bases: object

bottom_flange: ComponentDesign
property checks: list[CheckResult]
property components: list[ComponentDesign]
factored_moments: dict
factored_shears: dict
property ok: bool
spec: SpliceInput | None = None
top_flange: ComponentDesign
web: ComponentDesign
class civilpy.structural.aashto.lrfd.bolted_field_splice.SpliceInput(left: 'GirderSide', right: 'GirderSide', loads: 'SpliceLoads', bolts: 'BoltSpec', top_plates: 'PlatePair', bottom_plates: 'PlatePair', web_plate: 'WebPlate', deck_composite: 'bool' = True, deck_thickness: 'float' = 0.0, deck_eff_width: 'float' = 0.0, fc: 'float' = 4.0, top_flange_rows: 'int' = 4, bottom_flange_rows: 'int' = 4, web_rows: 'int' = 2, bolt_spacing: 'float' = 3.0, flange_edge: 'float' = 2.0, flange_end: 'float' = 1.5, web_edge: 'float' = 2.0, web_end: 'float' = 1.5, web_weld_size: 'float' = 0.3125, web_weld_clearance: 'float' = 0.375, girder_gap: 'float' = 0.75, entering_tightening: 'float' = 3.0, design_year: 'int' = 2020, method: 'str' = 'nsba', fcf_top: 'float | None' = None, fcf_bot: 'float | None' = None, r_h: 'float' = 1.0, alpha: 'float' = 1.0)[source]

Bases: object

alpha: float = 1.0
bolt_spacing: float = 3.0
bolts: BoltSpec
bottom_flange_rows: int = 4
bottom_plates: PlatePair
deck_composite: bool = True
deck_eff_width: float = 0.0
deck_thickness: float = 0.0
design_year: int = 2020
entering_tightening: float = 3.0
fc: float = 4.0
fcf_bot: float | None = None
fcf_top: float | None = None
flange_edge: float = 2.0
flange_end: float = 1.5
girder_gap: float = 0.75
left: GirderSide
loads: SpliceLoads
method: str = 'nsba'
r_h: float = 1.0
right: GirderSide
top_flange_rows: int = 4
top_plates: PlatePair
web_edge: float = 2.0
web_end: float = 1.5
web_plate: WebPlate
web_rows: int = 2
web_weld_clearance: float = 0.375
web_weld_size: float = 0.3125
class civilpy.structural.aashto.lrfd.bolted_field_splice.SpliceLoads(dc1_m: float = 0.0, dc1_v: float = 0.0, dc2_m: float = 0.0, dc2_v: float = 0.0, dw_m: float = 0.0, dw_v: float = 0.0, ll_pos_m: float = 0.0, ll_pos_v: float = 0.0, ll_neg_m: float = 0.0, ll_neg_v: float = 0.0, deck_cast_m: float = 0.0, deck_cast_v: float = 0.0)[source]

Bases: object

Unfactored moment (kip-ft) and shear (kip) at the splice centerline.

dc1_m: float = 0.0
dc1_v: float = 0.0
dc2_m: float = 0.0
dc2_v: float = 0.0
deck_cast_m: float = 0.0
deck_cast_v: float = 0.0
dw_m: float = 0.0
dw_v: float = 0.0
ll_neg_m: float = 0.0
ll_neg_v: float = 0.0
ll_pos_m: float = 0.0
ll_pos_v: float = 0.0
class civilpy.structural.aashto.lrfd.bolted_field_splice.WebPlate(material: 'str', thickness: 'float', shear_planes: 'int' = 2)[source]

Bases: object

material: str
shear_planes: int = 2
thickness: float
civilpy.structural.aashto.lrfd.bolted_field_splice.design_splice(inp: SpliceInput) SpliceDesign[source]

Design a bolted field splice: size bolts, lay out the pattern, and run the AASHTO limit-state checks for both flanges and the web.

civilpy.structural.aashto.lrfd.bolted_field_splice.girder_side_from_w(label: str, grade: str = 'Grade 50', *, haunch: float = 0.0, stiffener_spacing_ft: float | None = None, stiffened: bool = False) GirderSide[source]

Build a GirderSide from a rolled AISC W-shape label (G7).

Reads depth, flange_width, flange_thickness, and web_thickness from civilpy.structural.steel.W (the AISC database); the web depth is the clear distance between flanges (d - 2*tf). Top and bottom flanges are identical for a rolled shape. grade names the steel (mapped to Fy/Fu by the splice designer’s STEEL_GRADES).

civilpy.structural.aashto.lrfd.columns module

AASHTO LRFD 5.6.4 / 4.5.3.2.2 — reinforced concrete compression members.

Axial resistance, reinforcement limits, spiral steel, strain-compatibility P-M interaction (uniaxial and Bresler biaxial), and the approximate moment-magnification treatment of slenderness. Units: kip, inch, ksi.

class civilpy.structural.aashto.lrfd.columns.PMPoint(p_n: float, m_n: float, eps_t: float, phi: float, c: float)[source]

Bases: object

One point on the nominal interaction diagram.

c: float
eps_t: float
m_n: float
p_n: float
phi: float
property phi_mn: float
property phi_pn: float
class civilpy.structural.aashto.lrfd.columns.RebarLayer(area: float, depth: float)[source]

Bases: object

One layer of longitudinal bars: total area (in^2) at depth from the extreme compression fiber (in).

area: float
depth: float
civilpy.structural.aashto.lrfd.columns.moment_magnification(p_u: float, p_e: float, m_1: float = 0.0, m_2: float = 1.0, braced: bool = True, sum_p_u: float | None = None, sum_p_e: float | None = None, phi_k: float = 0.75) CheckResult[source]

Approximate slenderness treatment (4.5.3.2.2b): magnify the factored moment by delta_b = Cm/(1 - Pu/(phi_K*Pe)) >= 1.0 for the braced (no-sway) portion, with Cm = 0.6 + 0.4*(M1/M2) >= 0.4 for members without transverse loads; the sway portion uses delta_s = 1/(1 - sum(Pu)/(phi_K*sum(Pe))).

m_1/m_2 are the smaller/larger end moments (signed positive for single curvature). capacity holds the governing magnifier.

civilpy.structural.aashto.lrfd.columns.rc_biaxial_check(p_u: float, m_ux: float, m_uy: float, m_rx: float, m_ry: float, p_rx: float | None = None, p_ry: float | None = None, phi_p_o: float | None = None, f_c: float | None = None, a_g: float | None = None) CheckResult[source]

Biaxial flexure (5.6.4.5). Below the low-axial threshold 0.10*phi*f’c*Ag the moment-contour form applies: Mux/Mrx + Muy/Mry <= 1.0. Above it, the reciprocal (Bresler) load method: 1/Prxy = 1/Prx + 1/Pry - 1/(phi*Po) and Prxy >= Pu.

m_rx/m_ry are the factored uniaxial moment resistances at Pu (from rc_pm_capacity_check()); p_rx/p_ry the factored axial resistances at eccentricities ey and ex. capacity/demand carry the governing pair (resistance/applied).

civilpy.structural.aashto.lrfd.columns.rc_column_axial_resistance(a_g: float, a_st: float, f_c: float, f_y: float, p_u: float | None = None, spiral: bool = False) CheckResult[source]

Nominal axial resistance of a nonprestressed column (5.6.4.4): Po = 0.85*f’c*(Ag - Ast) + fy*Ast, with Pn = 0.85*Po for spiral columns and 0.80*Po for tied columns; phi = 0.75.

civilpy.structural.aashto.lrfd.columns.rc_column_reinforcement_limits(a_g: float, a_st: float, f_c: float, f_y: float) CheckResult[source]

Longitudinal reinforcement limits for columns (5.6.4.2): maximum Ast/Ag <= 0.08 and minimum Ast*fy/(Ag*f’c) >= 0.135.

Pass/fail check — per-limit booleans in details.

civilpy.structural.aashto.lrfd.columns.rc_pm_capacity_check(p_u: float, m_u: float, layers: list[RebarLayer], f_c: float, f_y: float, h: float | None = None, b: float | None = None, diameter: float | None = None, spiral: bool = False) CheckResult[source]

Uniaxial column adequacy: interpolate the factored interaction diagram at the factored axial load p_u (kip, compression positive) and compare the available phi*Mn against m_u (kip-in).

capacity holds the factored moment resistance at Pu; phi on the result is 1.0 because phi is baked into the diagram point by point (it varies with eps_t along the curve).

civilpy.structural.aashto.lrfd.columns.rc_pm_interaction_diagram(layers: list[RebarLayer], f_c: float, f_y: float, h: float | None = None, b: float | None = None, diameter: float | None = None, spiral: bool = False, n_points: int = 60) list[PMPoint][source]

Nominal P-M interaction diagram for a rectangular (b x h) or circular (diameter) reinforced section by strain compatibility, sweeping the neutral axis from pure tension to pure compression.

Returns points ordered from pure tension (negative Pn) to the maximum axial point, with phi per 5.5.4.2 attached; Pn is capped at the 5.6.4.4 tied/spiral maximum. Moments are about the section mid-depth (symmetric sections assumed for the axial-load point of application).

civilpy.structural.aashto.lrfd.columns.rc_spiral_reinforcement(a_g: float, a_c: float, f_c: float, f_yh: float = 60.0, rho_s_provided: float | None = None) CheckResult[source]

Minimum volumetric spiral reinforcement ratio (5.6.4.6-1): rho_s >= 0.45*(Ag/Ac - 1)*f’c/fyh.

a_c is the core area to the outside of the spiral (in^2); the provided ratio (4*Asp/(d_core*pitch)) is the capacity side.

civilpy.structural.aashto.lrfd.concrete module

AASHTO LRFD Chapter 5 — reinforced concrete design checks.

Article numbers follow the 8th Edition reorganization (5.6.3.2 flexure, 5.6.3.3 minimum reinforcement, 5.7.3.3 shear). Units: kip, inch, ksi.

class civilpy.structural.aashto.lrfd.concrete.FlexuralRebarDesign(a_s_required: float, a_s_provided: float, n_bars: int, bar_size: int, governing: str, check: CheckResult)[source]

Bases: object

Result of size_flexural_rebar().

a_s_required (in^2) is the tension-steel area that just reaches the governing target; a_s_provided is what the selected whole n_bars of bar_size actually supply. governing is "strength" or "minimum reinforcement". check is the flexural CheckResult evaluated with the provided steel against m_u (so check.ratio >= 1 confirms the selection works).

a_s_provided: float
a_s_required: float
bar_size: int
check: CheckResult
governing: str
n_bars: int
class civilpy.structural.aashto.lrfd.concrete.MCFTParams(beta: float, theta_deg: float, eps_s: float, s_xe: float | None = None)[source]

Bases: object

beta/theta from the 5.7.3.4.2 general procedure, ready to feed rc_shear_resistance().

beta: float
eps_s: float
s_xe: float | None = None
theta_deg: float
civilpy.structural.aashto.lrfd.concrete.beta1(f_c: float) float[source]

Stress-block factor beta1 (5.6.2.2).

civilpy.structural.aashto.lrfd.concrete.box_culvert_slab_shear(b: float, d_e: float, f_c: float, a_s: float, v_u: float, m_u: float, fill_ft: float = 2.0, single_cell: bool = False, monolithic: bool = True, lam: float = 1.0) CheckResult[source]

Concrete shear resistance of box-culvert slabs under 2.0 ft or more of fill (5.12.7.3; numbered 5.14.5.3 before the 8th Edition):

Vc = (0.0676*lam*sqrt(f’c) + 4.6*(As/(b*de))*(Vu*de/Mu))*b*de

with Vu*de/Mu taken <= 1.0 (5.12.7.3-1), capped at 0.126*lam*sqrt(f’c)*b*de (5.12.7.3-2). Slabs of single-cell boxes need not take Vc less than 0.0948*lam*sqrt(f’c)*b*de when monolithic with the walls, or 0.0791*lam*sqrt(f’c)*b*de when simply supported.

a_s is the area of flexural reinforcement in the design width b (in^2, in); v_u/m_u the concurrent factored shear and moment (kip, kip-in); lam the lightweight-concrete factor. Slabs under less than 2.0 ft of fill are outside this article — use rc_shear_resistance() (details["applicable"] flags it). phi_v = 0.90.

civilpy.structural.aashto.lrfd.concrete.deflection_limit(span: float, deflection: float | None = None, pedestrian: bool = False, cantilever: bool = False) CheckResult[source]

Optional live-load deflection limits (2.5.2.6.2): span/800 (vehicular), span/1000 (with pedestrian use); cantilevers span/300 and span/375 respectively. Same length unit in and out.

civilpy.structural.aashto.lrfd.concrete.modulus_of_rupture(f_c: float) float[source]

fr = 0.24*sqrt(f’c), normal-weight concrete (5.4.2.6), ksi.

civilpy.structural.aashto.lrfd.concrete.phi_flexure(eps_t: float, eps_cl: float = 0.002, eps_tl: float = 0.005) float[source]

Resistance factor for flexure from net tensile strain (5.5.4.2).

Varies linearly from 0.75 (compression-controlled, eps_t <= eps_cl) to 0.90 (tension-controlled, eps_t >= eps_tl) for nonprestressed sections.

civilpy.structural.aashto.lrfd.concrete.rc_crack_control_spacing(d_c: float, h: float, f_ss: float, f_y: float = 60.0, spacing: float | None = None, exposure_class_2: bool = False) CheckResult[source]

Maximum bar spacing for crack control (5.6.7, 2005 interim onward): s <= 700*gamma_e/(beta_s*fss) - 2*dc, the standard deck and tension-face check.

d_c is cover to center of nearest bar (in), h overall thickness (in), f_ss service-level steel stress (ksi, capped at 0.6*fy per the article), spacing the actual bar spacing (demand). Class 2 exposure (gamma_e = 0.75) is for decks/substructure exposed to chlorides; Class 1 (1.00) otherwise.

civilpy.structural.aashto.lrfd.concrete.rc_crack_control_z_factor(d_c: float, a_bar: float, f_ss: float | None = None, f_y: float = 60.0, z: float = 170.0) CheckResult[source]

Crack control for designs before the 2005 interim revisions, when the article (then 5.7.3.4) limited steel stress to z/(dc*A)^(1/3) rather than limiting bar spacing.

a_bar is the concrete tension area per bar A = 2*dc*s/n (in^2), z the crack-width parameter (kip/in): 170 moderate exposure, 130 severe, 100 buried. f_ss is the service steel stress (demand, ksi); the allowable is also capped at 0.6*fy.

civilpy.structural.aashto.lrfd.concrete.rc_effective_moment_of_inertia(i_g: float, i_cr: float, m_cr: float, m_a: float) float[source]

Branson effective moment of inertia for deflections (5.6.3.5.2): Ie = (Mcr/Ma)^3*Ig + (1 - (Mcr/Ma)^3)*Icr, capped at Ig and equal to Ig when the section is uncracked (Ma <= Mcr). in^4.

civilpy.structural.aashto.lrfd.concrete.rc_effective_shear_depth(h: float, a: float, a_ps: float = 0.0, f_ps: float = 0.0, d_p: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, d_s: float = 0.0) CheckResult[source]

Effective shear depth dv (5.7.2.8): the lever arm between the flexural tension and compression resultants,

dv = max(de - a/2, 0.9*de, 0.72*h)

with the effective depth combining strands and mild steel (5.7.2.8-2): de = (Aps*fps*dp + As*fy*ds) / (Aps*fps + As*fy). a is the equivalent stress-block depth at the section. capacity holds dv (in). Segmental box girders use 5.12.5.3.8c instead (the greater of 0.8h and the depth to the prestressing centroid) – not implemented here.

civilpy.structural.aashto.lrfd.concrete.rc_interface_shear(a_cv: float, f_c: float, case: str = 'roughened', v_ui: float | None = None, a_vf: float = 0.0, f_y: float = 60.0, p_c: float = 0.0) CheckResult[source]

Interface (horizontal) shear resistance (5.7.4.3-3): Vni = c*Acv + mu*(Avf*fy + Pc), capped at min(K1*f’c, K2)*Acv.

case selects the 5.7.4.4 cohesion/friction set (see INTERFACE_SHEAR_CASES); a_cv is the interface area (in^2), a_vf the reinforcement crossing it (in^2), p_c permanent net compressive force (kip); v_ui the factored interface shear demand (kip) checked against phi_v = 0.9 times Vni. details includes the 5.7.4.2 minimum Avf.

civilpy.structural.aashto.lrfd.concrete.rc_longitudinal_reinforcement(m_u: float, v_u: float, d_v: float, theta_deg: float, a_s_f_y: float = 0.0, a_ps_f_ps: float = 0.0, n_u: float = 0.0, v_s: float = 0.0, v_p: float = 0.0, phi_f: float = 0.9, phi_v: float = 0.9, phi_c: float = 0.75) CheckResult[source]

Tension demand on longitudinal reinforcement from combined moment, axial, and shear (5.7.3.5-1):

Aps*fps + As*fy >= |Mu|/(dv*phi_f) + 0.5*Nu/phi_c
                   + (|Vu/phi_v - Vp| - 0.5*Vs)*cot(theta)

v_s is capped at Vu/phi_v per the article. capacity is the tension the reinforcement can develop (pass the products As*fy and Aps*fps), demand the required tension.

civilpy.structural.aashto.lrfd.concrete.rc_max_stirrup_spacing(v_u: float, b_v: float, d_v: float, f_c: float, s: float | None = None, v_p: float = 0.0, phi_v: float = 0.9) CheckResult[source]

Maximum stirrup spacing (5.7.2.6): with the shear stress vu = |Vu - phi*Vp|/(phi*bv*dv), smax = min(0.8*dv, 24in) when vu < 0.125*f’c, else min(0.4*dv, 12in). capacity is smax and demand the actual spacing s.

civilpy.structural.aashto.lrfd.concrete.rc_mcft_beta_theta(m_u: float, v_u: float, d_v: float, e_s_a_s: float, n_u: float = 0.0, v_p: float = 0.0, a_ps: float = 0.0, f_po: float = 0.0, e_p_a_ps: float = 0.0, has_min_transverse_reinf: bool = True, s_x: float | None = None, a_g_agg: float = 0.75, e_c_a_ct: float = 0.0) MCFTParams[source]

Longitudinal strain, beta, and theta per the general (MCFT-based) procedure (5.7.3.4.2).

e_s_a_s and e_p_a_ps are the stiffness products Es*As and Ep*Aps (kip) on the flexural tension side; f_po is normally 0.7*fpu for bonded strand. With minimum transverse reinforcement, beta = 4.8/(1 + 750*eps_s); without it the crack-spacing penalty 51/(39 + sxe) applies, where s_x (in) and the max aggregate size a_g_agg (in) set sxe. When eps_s comes out negative (section uncracked), the concrete stiffness e_c_a_ct = Ec*Act may be added to the denominator; eps_s is bounded to [-0.40e-3, 6.0e-3].

civilpy.structural.aashto.lrfd.concrete.rc_min_transverse_reinforcement(b_v: float, s: float, f_c: float, f_y: float = 60.0, a_v: float | None = None, lam: float = 1.0) CheckResult[source]

Minimum transverse reinforcement where shear reinforcement is required (5.7.2.5-1): Av >= 0.0316*lam*sqrt(f’c)*bv*s/fy.

capacity is the provided a_v (in^2) and demand the required minimum, so ratio >= 1 passes.

civilpy.structural.aashto.lrfd.concrete.rc_minimum_reinforcement(m_n: float, phi: float, f_c: float, s_c: float, m_u: float | None = None, gamma_1: float = 1.6, gamma_3: float = 0.67, design_year: int | None = None, f_cpe: float = 0.0, gamma_2: float = 1.1, m_dnc: float = 0.0, s_nc: float | None = None, f_r: float | None = None) CheckResult[source]

Minimum flexural reinforcement check (5.6.3.3): Mr = phi*Mn must exceed the lesser of Mcr and 1.33*Mu, with the full 5.6.3.3-1 cracking moment:

Mcr = gamma_3 * [(gamma_1*fr + gamma_2*f_cpe)*Sc
  • M_dnc*(Sc/Snc - 1)]

s_c is the section modulus of the extreme tension fiber (in^3); f_cpe the compressive stress there from effective prestress (ksi, 0 for nonprestressed); for composite sections m_dnc is the unfactored dead-load moment carried by the noncomposite section (kip-in) and s_nc its section modulus (the deduction vanishes for monolithic/noncomposite sections, s_nc = None). gamma_1 = 1.6 flexural cracking variability (1.2 precast segmental), gamma_2 = 1.1 prestress variability (bonded; 1.0 unbonded), gamma_3 = 0.67 for A615 Grade 60, 0.75 for A706, 1.0 for prestressed structures. Designs before the 2012 6th Edition used 1.2*Mcr instead of the gamma factors — pass design_year for historical designs (gamma_1/gamma_3 overrides are ignored; gamma_2 becomes 1.0).

f_r overrides the 5.4.2.6 modulus of rupture (0.24*sqrt(f’c)) – e.g. 0.37*sqrt(f’c) to reproduce Midas Civil (or the 2008-2016 editions whose conservatism the gamma_1 = 1.6 factor replaced).

civilpy.structural.aashto.lrfd.concrete.rc_rectangular_flexural_resistance(a_s: float, f_y: float, f_c: float, b: float, d_s: float, m_u: float | None = None, a_s_prime: float = 0.0, d_s_prime: float = 0.0, f_y_prime: float | None = None) CheckResult[source]

Nominal flexural resistance of a rectangular (or rectangular-behaving) reinforced section (5.6.3.2.3), with phi per 5.5.4.2.

Parameters: tension steel a_s (in^2) at depth d_s (in), compression steel a_s_prime at d_s_prime, section width b (in), f_y/f_c (ksi), optional factored moment demand m_u (kip-in). Compression steel is assumed yielding only if the computed strain supports it; otherwise it is ignored (conservative).

civilpy.structural.aashto.lrfd.concrete.rc_shear_resistance(b_v: float, d_v: float, f_c: float, v_u: float | None = None, a_v: float = 0.0, s: float = 1.0, f_y: float = 60.0, beta: float = 2.0, theta_deg: float = 45.0, v_p: float = 0.0, lam: float = 1.0, alpha_deg: float = 90.0) CheckResult[source]

Nominal shear resistance Vn (5.7.3.3) with phi_v = 0.9 (5.5.4.2).

Vc = 0.0316*lam*beta*sqrt(f’c)*bv*dv (5.7.3.3-3) and Vs per 5.7.3.3-4 with stirrups a_v (in^2) at spacing s (in), inclined at alpha_deg to the longitudinal axis (90 = vertical, where the (cot theta + cot alpha)*sin alpha term reduces to cot theta). Defaults beta = 2.0 / theta = 45 deg correspond to the 5.7.3.4.1 simplified procedure; pass values from the 5.7.3.4.2 general (MCFT) procedure for sections that qualify for it.

civilpy.structural.aashto.lrfd.concrete.rc_torsion_longitudinal(t_u: float, p_h: float, a_o: float, f_y: float = 60.0, a_lt: float | None = None, phi_t: float = 0.9) CheckResult[source]

Additional longitudinal reinforcement for torsion in box sections (5.7.3.6.3-2): Alt >= (Tu/phi)*ph / (2*Ao*fy).

p_h is the perimeter of the centerline of the closed transverse reinforcement (in). capacity is the provided a_lt (in^2, if given) and demand the required area.

civilpy.structural.aashto.lrfd.concrete.rc_torsion_resistance(a_o: float, a_t: float, s: float, theta_deg: float = 45.0, f_y: float = 60.0, t_u: float | None = None, lam_duct: float = 1.0) CheckResult[source]

Nominal torsional resistance (5.7.3.6.2-1): Tn = 2*Ao*At*fy*cot(theta)/s * lam_duct, with phi_t = 0.9 (5.5.4.2.1).

a_t is the area of ONE leg of closed transverse torsion reinforcement (in^2) at spacing s (in); theta_deg from the shear MCFT procedure; lam_duct the duct-reduction factor (5.7.3.6.2, 1.0 with no ducts in the web).

civilpy.structural.aashto.lrfd.concrete.rc_torsion_threshold(a_cp: float, p_c: float, f_c: float, t_u: float | None = None, f_pc: float = 0.0, lam: float = 1.0, phi_t: float = 0.9, a_o: float | None = None, b_e: float | None = None) CheckResult[source]

Whether torsion must be considered (5.7.2.1): Tu > 0.25*phi*Tcr.

Solid sections (5.7.2.1-4): Tcr = 0.126*lam*sqrt(f’c)*(Acp^2/pc)*sqrt(1 + fpc/(0.126*lam*sqrt(f’c))); cellular/box sections (5.7.2.1-5, pass a_o and b_e): Tcr = 0.126*lam*sqrt(f’c)*2*Ao*be*sqrt(same term).

a_cp is the area enclosed by the outside perimeter (in^2), p_c that perimeter (in), a_o the area enclosed by the shear flow path (in^2), b_e its effective width (min wall, <= Acp/pc), f_pc the prestress at the centroid – or at the web/flange junction when the centroid falls in the flange (ksi). capacity is the 0.25*phi*Tcr threshold (kip-in); ok True means torsion may be neglected.

civilpy.structural.aashto.lrfd.concrete.rc_transverse_reinf_required(v_u: float, v_c: float, v_p: float = 0.0, phi_v: float = 0.9) CheckResult[source]

Whether transverse reinforcement is required (5.7.2.3-1): Vu > 0.5*phi*(Vc + Vp). Below that threshold the transverse reinforcement checks may be skipped. capacity is the threshold (kips), demand is Vu; details['required'] gives the verdict.

civilpy.structural.aashto.lrfd.concrete.rebar_development_length(d_b: float, f_y: float = 60.0, f_c: float = 4.0, top_bar: bool = False, epoxy_coated: bool = False, cover_lt_3db: bool = False, lambda_rc: float = 1.0, lam: float = 1.0, available: float | None = None) CheckResult[source]

Tension development length of deformed bars (5.10.8.2.1, current edition): ld = ldb * modifiers, ldb = 2.4*db*fy/sqrt(f’c), >= 12 in.

Modifiers: 1.3 for top bars (>12 in of fresh concrete below), epoxy coating 1.5 when cover < 3db or clear spacing < 6db else 1.2 (their product with the top-bar factor need not exceed 1.7), confinement reduction lambda_rc (0.4 <= lambda_rc <= 1.0) from 5.10.8.2.1c. capacity is the available embedment when given (ok means it exceeds ld); otherwise ld itself.

civilpy.structural.aashto.lrfd.concrete.size_flexural_rebar(m_u: float, b: float, d_s: float, *, f_c: float = 4.0, f_y: float = 60.0, bar_size: int = 8, h: float | None = None, design_year: int | None = None, rho_max: float = 0.08) FlexuralRebarDesign[source]

Select tension reinforcement for a singly reinforced rectangular RC section to carry a factored moment m_u (kip-in).

The area is found by bisecting rc_rectangular_flexural_resistance() until the factored resistance phi*Mn reaches the governing target, then the whole number of bar_size (ASTM #) bars that supplies it is chosen. When the total depth h (in) is given, the minimum-reinforcement provision (5.6.3.3) can raise the target above the strength demand – the lesser of Mcr and 1.33*Mu – and governing records which controlled.

This stops at a checked design: it returns the bars and the governing CheckResult; detailing (bar spacing, layers, development, crack control via rc_crack_control_spacing()) is the engineer’s. b, d_s, h in inches; f_c, f_y in ksi; m_u kip-in.

civilpy.structural.aashto.lrfd.core module

Shared result type and article registry for AASHTO LRFD checks.

Units convention for the whole package: kip, inch, ksi (US customary, matching the dimensional form of the LRFD equations). All checks are pure functions — no I/O, no global state — so they can be vectorized or looped over candidate member sizes.

class civilpy.structural.aashto.lrfd.core.CheckResult(article: str, name: str, capacity: float, demand: float | None = None, phi: float = 1.0, details: dict = <factory>)[source]

Bases: object

Outcome of a single spec-article check.

capacity and demand are in the article’s governing unit (stress, moment, or force); details carries the intermediate values an engineer would show in hand calcs, keyed by the symbol used in the spec.

article: str
capacity: float
demand: float | None = None
details: dict
property factored_capacity: float
name: str
property ok: bool | None
phi: float = 1.0
property ratio: float | None

Capacity/demand ratio (>= 1.0 passes); None when no demand given.

civilpy.structural.aashto.lrfd.core.article(number: str, name: str)[source]

Register a check function under its LRFD article number.

civilpy.structural.aashto.lrfd.creep_shrinkage module

AASHTO LRFD 5.4.2.3 — concrete creep and shrinkage material models.

These feed the refined prestress-loss estimates (5.9.3.4) and time-dependent deflections. Units: ksi, inch, days; humidity in percent.

The time-development factor ktd was revised in the 2015 interim — pass design_year for designs between 2007 and 2014 to get the earlier form. (The pre-2007 creep/shrinkage model is a different formulation entirely and is not implemented.)

civilpy.structural.aashto.lrfd.creep_shrinkage.creep_coefficient(t: float, t_i: float, f_ci: float, humidity_pct: float = 70.0, v_s: float = 3.5, design_year: int | None = None) float[source]

Creep coefficient psi(t, ti) (5.4.2.3.2-1): 1.9 * ks * khc * kf * ktd * ti^-0.118.

t is concrete age at the time of interest (days), t_i age at loading. Returns a plain float since this is a material model, not a pass/fail check.

civilpy.structural.aashto.lrfd.creep_shrinkage.factor_concrete_strength(f_ci: float) float[source]

kf, concrete strength factor (5.4.2.3.2-4): 5/(1 + f’ci).

civilpy.structural.aashto.lrfd.creep_shrinkage.factor_humidity_creep(humidity_pct: float) float[source]

khc, humidity factor for creep (5.4.2.3.2-3): 1.56 - 0.008*H.

civilpy.structural.aashto.lrfd.creep_shrinkage.factor_humidity_shrinkage(humidity_pct: float) float[source]

khs, humidity factor for shrinkage (5.4.2.3.3-2): 2.00 - 0.014*H.

civilpy.structural.aashto.lrfd.creep_shrinkage.factor_time_development(t: float, f_ci: float, design_year: int | None = None) float[source]

ktd, time-development factor (5.4.2.3.2-5).

Current (2015 interim onward): t / (12*(100 - 4*f’ci)/(f’ci + 20) + t). 2007-2014 designs used t / (61 - 4*f’ci + t). t is the maturity of the concrete in days from loading (creep) or end of curing (shrinkage).

civilpy.structural.aashto.lrfd.creep_shrinkage.factor_vs_ratio(v_s: float) float[source]

ks, volume-to-surface ratio factor (5.4.2.3.2-2): 1.45 - 0.13*(V/S), not less than 1.0. v_s in inches.

civilpy.structural.aashto.lrfd.creep_shrinkage.shrinkage_strain(t: float, f_ci: float, humidity_pct: float = 70.0, v_s: float = 3.5, design_year: int | None = None) float[source]

Shrinkage strain eps_sh (5.4.2.3.3-1): ks * khs * kf * ktd * 0.48e-3 (in/in, returned positive for shortening). t is drying time in days from the end of curing.

civilpy.structural.aashto.lrfd.distribution module

AASHTO LRFD 4.6.2.2 — approximate live-load distribution factors.

Implemented for the most common cross-section: concrete deck on steel or precast concrete I-girders (Table 4.6.2.2.1-1 types (a), (e), (k)). The formulas return lanes/girder with multiple presence already embedded.

Units here follow the tables: S and de in ft, L in ft, ts in inches, Kg in in^4. Results carry the table’s range-of-applicability flags in details — outside those ranges the spec requires refined analysis or the lever rule, it does not extrapolate.

class civilpy.structural.aashto.lrfd.distribution.DistributionFactor(one_lane: float, multi_lane: float, applicability: dict = <factory>)[source]

Bases: object

A distribution factor (lanes/girder) with its applicability flags.

applicability: dict
property applicable: bool
property governing: float
multi_lane: float
one_lane: float
civilpy.structural.aashto.lrfd.distribution.dynamic_load_allowance(component: str = 'general', fatigue: bool = False) float[source]

IM (Table 3.6.2.1-1) as a multiplier on the truck portion of live load: 1.33 generally, 1.15 for fatigue, 1.75 for deck joints.

civilpy.structural.aashto.lrfd.distribution.effective_flange_width(s_ft: float, span_ft: float | None = None, t_s: float | None = None, t_w: float | None = None, b_f: float | None = None, design_year: int | None = None) float[source]

Effective deck width acting with an interior girder (4.6.2.6.1), in inches.

Since the 2008 interim revisions this is simply the girder spacing. Earlier designs used the lesser of L/4, 12*ts + max(tw, bf/2), and S — pass design_year (with span_ft, t_s, t_w, b_f) for those.

civilpy.structural.aashto.lrfd.distribution.lever_rule_exterior(s_ft: float, d_e_ft: float, apply_multiple_presence: bool = True) float[source]

One-lane exterior-girder DF by the lever rule (C4.6.2.2.1): deck assumed hinged at the first interior girder, one truck with wheel lines 6 ft apart, the nearer one 2 ft from the barrier face. Wheels landing inboard of the interior girder contribute nothing.

Returns lanes/girder including the 1.2 single-lane multiple presence unless apply_multiple_presence is False.

civilpy.structural.aashto.lrfd.distribution.longitudinal_stiffness_kg(n_modular: float, i_girder: float, a_girder: float, e_g: float) float[source]

Kg = n*(I + A*eg^2) (4.6.2.2.1-1), in^4. e_g is the distance between girder and deck centroids (in); n_modular the girder/deck modular ratio.

civilpy.structural.aashto.lrfd.distribution.moment_df_exterior(interior_df: DistributionFactor, d_e_ft: float, one_lane_lever_rule: float | None = None) DistributionFactor[source]

Moment DF for exterior I-girders (Table 4.6.2.2.2d-1): multi-lane g = e * g_interior with e = 0.77 + de/9.1; the one-lane value comes from the lever rule (pass it in — it depends on the actual overhang and wheel placement). d_e_ft is the distance from exterior web to the inside face of the barrier (ft, -1.0 <= de <= 5.5).

civilpy.structural.aashto.lrfd.distribution.moment_df_interior(s_ft: float, l_ft: float, t_s: float, k_g: float, n_beams: int = 4) DistributionFactor[source]

Moment DF for interior I-girders (Table 4.6.2.2.2b-1, type a/e/k):

one lane: 0.06 + (S/14)^0.4 * (S/L)^0.3 * (Kg/(12*L*ts^3))^0.1 multi: 0.075 + (S/9.5)^0.6 * (S/L)^0.2 * (Kg/(12*L*ts^3))^0.1

civilpy.structural.aashto.lrfd.distribution.moment_df_interior_box(b_in: float, l_ft: float, i_beam: float, j_beam: float, n_beams: int) DistributionFactor[source]

Moment DF for interior precast box beams used in multibeam decks (Table 4.6.2.2.2b-1, cross-section type g):

one lane: k*(b/33.3L)^0.5 * (I/J)^0.25 multi: k*(b/305)^0.6 * (b/12L)^0.2 * (I/J)^0.06 k = 2.5*(Nb)^-0.2 >= 1.5

b_in is the beam width (in), i_beam/j_beam the moment of inertia and St. Venant constant (in^4).

civilpy.structural.aashto.lrfd.distribution.moment_df_interior_multicell(s_ft: float, l_ft: float, n_cells: int) DistributionFactor[source]

Moment DF for an interior web of a cast-in-place multicell box (Table 4.6.2.2.2b-1, cross-section type d):

one lane: (1.75 + S/3.6) * (1/L)^0.35 * (1/Nc)^0.45 multi: (13/Nc)^0.3 * (S/5.8) * (1/L)^0.25

s_ft is the web spacing; n_cells the number of cells (use 8 in the formula when Nc > 8, per the table note).

civilpy.structural.aashto.lrfd.distribution.moment_df_interior_spread_box(s_ft: float, l_ft: float, d_in: float, n_beams: int = 4) DistributionFactor[source]

Moment DF for interior precast spread box beams (Table 4.6.2.2.2b-1):

one lane: (S/3.0)^0.35 * (S*d/(12*L^2))^0.25 multi: (S/6.3)^0.6 * (S*d/(12*L^2))^0.125

d_in is the beam depth (in). Beyond S = 18 ft the table sends you to the lever rule (applicable goes False).

civilpy.structural.aashto.lrfd.distribution.multiple_presence_factor(n_lanes: int) float[source]

m (Table 3.6.1.1.2-1): 1.20 / 1.00 / 0.85 / 0.65 for 1/2/3/>3 loaded lanes. Already embedded in the 4.6.2.2 DF equations — apply only with the lever rule or refined analysis.

civilpy.structural.aashto.lrfd.distribution.shear_df_exterior(interior_df: DistributionFactor, d_e_ft: float, one_lane_lever_rule: float | None = None) DistributionFactor[source]

Shear DF for exterior I-girders (Table 4.6.2.2.3b-1): multi-lane g = e * g_interior with e = 0.6 + de/10.

civilpy.structural.aashto.lrfd.distribution.shear_df_interior(s_ft: float, l_ft: float = 80.0, t_s: float = 8.0, n_beams: int = 4) DistributionFactor[source]

Shear DF for interior I-girders (Table 4.6.2.2.3a-1, type a/e/k): one lane 0.36 + S/25; multi 0.2 + S/12 - (S/35)^2.

civilpy.structural.aashto.lrfd.distribution.shear_df_interior_box(b_in: float, l_ft: float, i_beam: float, j_beam: float) DistributionFactor[source]

Shear DF for interior precast box beams used in multibeam decks (Table 4.6.2.2.3a-1, cross-section type g):

one lane: (b/130L)^0.15 * (I/J)^0.05 multi: (b/156)^0.4 * (b/12L)^0.1 * (I/J)^0.05 * (b/48), b/48 >= 1

b_in is the beam width (in); the b/48 term never reduces the multi-lane factor.

civilpy.structural.aashto.lrfd.distribution.shear_df_interior_multicell(s_ft: float, l_ft: float, d_in: float) DistributionFactor[source]

Shear DF for an interior web of a cast-in-place multicell box (Table 4.6.2.2.3a-1, type d):

one lane: (S/9.5)^0.6 * (d/12L)^0.1 multi: (S/7.3)^0.9 * (d/12L)^0.1

d_in is the section depth (in).

civilpy.structural.aashto.lrfd.distribution.shear_df_interior_spread_box(s_ft: float, l_ft: float, d_in: float, n_beams: int = 4) DistributionFactor[source]

Shear DF for interior precast spread box beams (Table 4.6.2.2.3a-1):

one lane: (S/10)^0.6 * (d/12L)^0.1 multi: (S/7.4)^0.8 * (d/12L)^0.1

civilpy.structural.aashto.lrfd.distribution.skew_correction_moment(skew_deg: float, s_ft: float, l_ft: float, t_s: float, k_g: float) float[source]

Reduction of moment DF on skewed supports (Table 4.6.2.2.2e-1): 1 - c1*(tan(theta))^1.5, with c1 = 0.25*(Kg/(12*L*ts^3))^0.25*(S/L)^0.5. No reduction below 30 degrees; theta capped at 60.

civilpy.structural.aashto.lrfd.distribution.skew_correction_shear(skew_deg: float, l_ft: float, t_s: float, k_g: float) float[source]

Increase of shear DF at the obtuse corner of skewed spans (Table 4.6.2.2.3c-1): 1 + 0.20*(12*L*ts^3/Kg)^0.3 * tan(theta).

civilpy.structural.aashto.lrfd.distribution.slab_equivalent_strip(span_ft: float, width_ft: float, n_lanes: int, multi_lane: bool = True, skew_deg: float = 0.0) float[source]

Equivalent strip width E (in) carrying one wheel line of live load in a cast-in-place slab bridge (4.6.2.3):

one lane: E = 10.0 + 5.0*sqrt(L1*W1), W1 capped at 30 ft multi: E = 84.0 + 1.44*sqrt(L1*W1) <= 12.0*W/NL, W1 capped at 60 ft

with L1 = min(span, 60 ft). Skewed bridges may reduce the force effects by r = 1.05 - 0.25*tan(theta) <= 1.00 — the reduction is applied to E here (wider strip = lower demand per ft).

civilpy.structural.aashto.lrfd.editions module

Design-year / spec-edition handling for historical bridge designs.

Checks in this package implement the current LRFD edition by default. Bridges are long-lived, so checks whose governing values changed between editions accept an optional design_year; passing the year the bridge was designed selects the values in force at that time. Checks without a design_year parameter are value-stable across the editions this package tracks (equation renumbering alone doesn’t matter — functions are keyed to current numbering).

Known value changes wired into checks so far:

Year

Article (current num.)

Change

2005

5.6.7

z-factor crack check replaced by the max-spacing method (use rc_crack_control_z_factor for pre-2005 designs)

2008

4.6.2.6

effective flange width became simply S

2012

5.6.3.3

1.2*Mcr replaced by gamma_1*gamma_3

2015

5.4.2.3

ktd time-development factor revised

2015

6.9.4.1.1

phi_c for steel columns 0.90 -> 0.95

2016

5.9.2.3.1a

transfer compression 0.60 -> 0.65 f’ci

civilpy.structural.aashto.lrfd.editions.lrfd_edition(design_year: int | None = None) str[source]

Label of the LRFD edition in force for a given design year (the latest edition published in or before that year). None means current.

civilpy.structural.aashto.lrfd.lrfr module

AASHTO Manual for Bridge Evaluation (MBE) Section 6A — LRFR load rating.

The general rating equation composes any of the capacity checks in this package into a load rating:

RF = (C - gamma_DC*DC - gamma_DW*DW +/- gamma_P*P) / (gamma_LL*(LL+IM))

where C = phi_c * phi_s * phi * Rn at strength limit states (with phi_c*phi_s >= 0.85) or the allowable stress fR at service limit states.

Factors default to the published MBE values but every one is overridable — agencies routinely customize them. Consistent force/moment units in = same units out; RF is dimensionless.

civilpy.structural.aashto.lrfd.lrfr.legal_load_factor(adtt: float | None = None) float[source]

Generalized live load factor for legal-load ratings (Table 6A.4.4.2.3a-1): 1.30 at one-direction ADTT <= 1000, 1.45 at ADTT >= 5000 (or unknown), linearly interpolated between.

civilpy.structural.aashto.lrfd.lrfr.permit_load_factor(permit_type: str = 'routine', adtt: float | None = None, gvw_kips: float | None = None, axle_length_ft: float | None = None, gvw_over_al: float | None = None, factors: dict | None = None) float[source]

Live load factor for permit ratings (Table 6A.4.5.4.2a-1).

permit_type is "routine" (annual, mixed with traffic, two or more lanes) or one of the special/limited-crossing types: "single_trip_escorted", "single_trip_mixed", "multiple_trip_mixed" (fewer than 100 crossings).

Routine permits need the one-direction adtt and the permit weight intensity GVW/AL — pass gvw_over_al directly (kips/ft) or gvw_kips with axle_length_ft (distance between the extreme axles). Factors interpolate linearly on ADTT between 100 and 5000 within each GVW/AL band; ADTT above 5000 (or unknown) uses the top row. factors overrides the published table for agency customizations (same shapes as PERMIT_ROUTINE_FACTORS / PERMIT_SPECIAL_FACTORS).

civilpy.structural.aashto.lrfd.lrfr.posting_load(rf: float, vehicle_weight_tons: float) float[source]

Safe posting load for a legal vehicle (6A.8.3-1): W*(RF - 0.3)/0.7 for 0.3 <= RF < 1.0; the full vehicle weight when RF >= 1.0; 0 (close the bridge to that vehicle) when RF < 0.3.

civilpy.structural.aashto.lrfd.lrfr.rating_factor(nominal_capacity: float, dc: float, ll_im: float, dw: float = 0.0, phi: float = 1.0, level: str = 'inventory', gamma_ll: float | None = None, gamma_dc: float = 1.25, gamma_dw: float = 1.5, condition: str = 'good', system: str = 'other_girder_slab', permanent_other: float = 0.0, gamma_p: float = 1.0, service: bool = False) CheckResult[source]

General LRFR rating factor (MBE 6A.4.2.1-1).

nominal_capacity is Rn from any capacity check in this package (pass the check’s capacity and its phi); dc/dw/ll_im are the unfactored force effects, with ll_im already including the distribution factor and dynamic load allowance. level selects the design-load gamma_LL (1.75 inventory / 1.35 operating) unless gamma_ll is given (legal/permit ratings). At service limit states pass service=True to skip the condition/system factors.

capacity on the result holds RF; ok means RF >= 1.0.

civilpy.structural.aashto.lrfd.plots module

Notebook plotting helpers for the LRFD check results.

The check functions themselves stay pure (no matplotlib import on the calculation path); these helpers render their outputs following the package-wide convention (optional ax, figure returned).

civilpy.structural.aashto.lrfd.plots.plot_column_curve(f_y, *, q_slender: float = 1.0, design_year: int | None = None, kl_over_r: float | None = None, f_u_ksi: float | None = None, max_kl_over_r: float = 200.0, ax=None)[source]

Column curve: loop the 6.9.4.1.1 buckling check over KL/r and plot the nominal axial stress Pn/Ag, marking the inelastic/elastic transition at Pe = 0.44 Po.

f_y may be a single yield strength (ksi) or an iterable to compare grades on one chart. An optional demand point (kl_over_r, f_u_ksi = Pu/Ag) is starred. Returns the figure.

civilpy.structural.aashto.lrfd.plots.plot_mn_vs_lb(b_fc, t_fc, d_c, t_w, f_yc, f_yw, *, c_b: float = 1.0, r_b: float = 1.0, r_h: float = 1.0, s_xc: float | None = None, l_b: float | None = None, f_bu: float | None = None, l_b_max: float | None = None, show_flb: bool = True, ax=None)[source]

Capacity-vs-unbraced-length chart: loop the 6.10.8.2.3 LTB check over Lb and draw the classic three-regime curve with the Lp/Lr anchor points.

Inputs match lateral_torsional_buckling_resistance() (inches and ksi). The y-axis is flange stress Fnc (ksi) unless s_xc (in^3) is given, which converts to moment Mn = Fnc*Sxc in kip-ft. show_flb overlays the 6.10.8.2.2 flange local buckling cap so the governing envelope is visible; an optional demand point (l_b, f_bu) is starred. Lengths plot in feet. Returns the figure.

civilpy.structural.aashto.lrfd.plots.plot_pm_interaction(points, ax=None, p_u: float | None = None, m_u: float | None = None, units: str = 'kip, kip-in')[source]

Plot a column interaction diagram from rc_pm_interaction_diagram() output: the nominal curve dashed, the factored (phi-reduced) curve solid, and optionally the factored demand point (Pu, Mu). Returns the figure.

civilpy.structural.aashto.lrfd.plots.plot_rc_strain_compatibility(b, h, d_s, a_s, f_c, f_y, *, a_s_prime: float = 0.0, d_s_prime: float = 0.0, result=None)[source]

Three-panel strain-compatibility sketch for a rectangular RC section: cross-section with bars, the linear strain diagram (0.003 crushing strain to eps_t through the neutral axis), and the Whitney stress block with the force resultants.

Dimensions in inches, strengths in ksi — the same inputs as rc_rectangular_flexural_resistance(), which is called internally unless its result is passed in. Returns the figure (three shared-depth axes).

civilpy.structural.aashto.lrfd.prestressed module

AASHTO LRFD Chapter 5 — prestressed concrete design checks.

Article numbers follow the 8th Edition renumbering (5.6.3.1 strand stress, 5.9.2.3 stress limits, 5.9.3 losses; pre-8th these were 5.7.3.1, 5.9.4, and 5.9.5 respectively). Units: kip, inch, ksi. Stress sign convention for the limit checks: pass magnitudes — compression checks take compressive stress as positive, tension checks take tensile stress as positive.

civilpy.structural.aashto.lrfd.prestressed.TENDON_STRESS_LIMITS = {'bar': {'post_at_anchorage_after_set': (0.7, 'f_pu'), 'post_elsewhere_after_set': (0.7, 'f_pu'), 'post_prior_to_seating': (0.9, 'f_py'), 'post_service_after_losses': (0.8, 'f_py'), 'pre_prior_to_transfer': (0.7, 'f_pu'), 'pre_service_after_losses': (0.8, 'f_py')}, 'low_relaxation': {'post_at_anchorage_after_set': (0.7, 'f_pu'), 'post_elsewhere_after_set': (0.74, 'f_pu'), 'post_prior_to_seating': (0.9, 'f_py'), 'post_service_after_losses': (0.8, 'f_py'), 'pre_prior_to_transfer': (0.75, 'f_pu'), 'pre_service_after_losses': (0.8, 'f_py')}, 'stress_relieved': {'post_at_anchorage_after_set': (0.7, 'f_pu'), 'post_elsewhere_after_set': (0.7, 'f_pu'), 'post_prior_to_seating': (0.9, 'f_py'), 'post_service_after_losses': (0.8, 'f_py'), 'pre_prior_to_transfer': (0.7, 'f_pu'), 'pre_service_after_losses': (0.8, 'f_py')}}

Table 5.9.2.2-1 tendon stress limits as multipliers on (f_pu or f_py): {tendon_type: {condition: (factor, basis)}}.

civilpy.structural.aashto.lrfd.prestressed.phi_flexure_ps(eps_t: float, eps_cl: float = 0.002, eps_tl: float = 0.005) float[source]

Resistance factor for prestressed flexure from net tensile strain (5.5.4.2): 0.75 compression-controlled up to 1.0 tension-controlled.

civilpy.structural.aashto.lrfd.prestressed.ps_anchorage_set_loss(anchor_set: float, friction_gradient: float, x_from_anchor: float = 0.0, e_p: float = 28500.0) CheckResult[source]

Loss from anchorage set in a post-tensioned tendon (5.9.3.2.1).

With a linear friction gradient friction_gradient (ksi of stress loss per inch of tendon), the set anchor_set (in, typically 0.375) affects a length x = sqrt(Ep*set/gradient); the loss is 2*gradient*x at the anchorage, decreasing linearly to zero at x. capacity holds the loss at x_from_anchor (in).

civilpy.structural.aashto.lrfd.prestressed.ps_approximate_longterm_loss(f_pi: float, a_ps: float, a_g: float, f_ci: float, humidity_pct: float = 70.0, delta_f_pr: float = 2.4) CheckResult[source]

Lump-sum long-term loss for standard precast pretensioned members (5.9.3.3): creep + shrinkage + relaxation combined.

capacity holds the total loss (ksi). f_pi is the strand stress immediately prior to transfer (ksi), a_g the gross section area (in^2), humidity_pct the average annual ambient relative humidity, delta_f_pr the relaxation estimate (2.4 ksi low-relaxation strand).

civilpy.structural.aashto.lrfd.prestressed.ps_deck_shrinkage_gain(delta_f_cdf: float, k_df: float, psi_tf_td: float, e_c: float, e_p: float = 28500.0) CheckResult[source]

Prestress gain from deck shrinkage (5.9.3.4.3d-1): (Ep/Ec) * delta_fcdf * Kdf * (1 + 0.7*psi(tf, td)).

delta_f_cdf is the change in concrete stress at the strand centroid caused by deck shrinkage (ksi, compressive positive — the deck shrinks, cambering the girder and compressing the bottom flange). capacity holds the gain; subtract it from the total loss.

civilpy.structural.aashto.lrfd.prestressed.ps_elastic_shortening_loss(f_cgp: float, e_ct: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from elastic shortening in pretensioned members (5.9.3.2.3a): the strand sheds stress in proportion to the modular ratio times the concrete stress at the strand centroid at transfer.

capacity holds the loss (ksi). f_cgp is the concrete stress at the centroid of the prestressing at transfer (ksi); e_ct the concrete modulus at transfer (ksi).

civilpy.structural.aashto.lrfd.prestressed.ps_flexural_resistance(a_ps: float, f_pu: float, d_p: float, f_c: float, b: float, m_u: float | None = None, b_w: float | None = None, h_f: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, d_s: float = 0.0, a_s_prime: float = 0.0, d_s_prime: float = 0.0, f_y_prime: float | None = None, k: float = 0.28, d_t: float | None = None) CheckResult[source]

Nominal flexural resistance Mn of a bonded prestressed section (5.6.3.2.2 flanged / 5.6.3.2.3 rectangular), kip-in.

Strand stress comes from ps_strand_stress_at_nominal(); phi varies with net tensile strain per 5.5.4.2 (1.0 when tension-controlled). d_t is the depth to the extreme tension steel for the strain check (defaults to d_p).

civilpy.structural.aashto.lrfd.prestressed.ps_friction_loss(f_pj: float, x: float, alpha: float, mu: float = 0.25, k: float = 0.0002) CheckResult[source]

Friction loss in a post-tensioned tendon (5.9.3.2.2b-1): fpj * (1 - e^(-(K*x + mu*alpha))).

x is the tendon length from the jacking end (ft), alpha the sum of angular changes (radians), mu the curvature friction coefficient and k the wobble coefficient (per ft) — defaults are typical of strand in rigid galvanized ducts; use the duct manufacturer’s values when known.

civilpy.structural.aashto.lrfd.prestressed.ps_principal_tension_check(f_ci: float, sigma_ps: float | None = None, lam: float = 1.0) CheckResult[source]

Principal tensile stress limit in webs (5.9.2.3.3): 0.110*lam*sqrt(f’ci), the same for segmental and non-segmental bridges. At construction stages pass the strength at the time of loading (f’ci); at service pass the specified f’c – the article covers both epochs with the same coefficient. sigma_ps is the maximum principal tensile stress (ksi, positive) from the biaxial state (sigma_x, sigma_z, tau) – e.g. via civilpy.structural.mohrs_circle.MohrsCircle.

civilpy.structural.aashto.lrfd.prestressed.ps_refined_loss_creep_deck_stage(f_cgp: float, psi_tf_ti: float, psi_td_ti: float, psi_tf_td: float, delta_f_cd: float, k_df: float, e_ci: float, e_c: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder creep between deck placement and final time (5.9.3.4.3b-1):

(Ep/Eci)*fcgp*(psi(tf,ti) - psi(td,ti))*Kdf
  • (Ep/Ec)*delta_fcd*psi(tf,td)*Kdf, taken >= 0.

delta_f_cd is the change in concrete stress at the strand centroid from deck weight and superimposed loads (ksi, negative when it relieves compression).

civilpy.structural.aashto.lrfd.prestressed.ps_refined_loss_creep_girder(f_cgp: float, psi_td_ti: float, k_id: float, e_ci: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder creep between transfer and deck placement (5.9.3.4.2b-1): (Ep/Eci) * fcgp * psi(td, ti) * Kid.

civilpy.structural.aashto.lrfd.prestressed.ps_refined_loss_relaxation(f_pt: float, f_py: float, k_l: float = 30.0) CheckResult[source]

Strand relaxation loss per stage (5.9.3.4.2c-1): (fpt/KL) * (fpt/fpy - 0.55), taken as zero if fpt/fpy < 0.55.

f_pt is the strand stress immediately after transfer (ksi); k_l = 30 for low-relaxation strand, 7 for stress-relieved. The same value applies again for the deck-to-final stage (5.9.3.4.3c).

civilpy.structural.aashto.lrfd.prestressed.ps_refined_loss_shrinkage_deck_stage(eps_bdf: float, k_df: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder shrinkage between deck placement and final time (5.9.3.4.3a-1): eps_bdf * Ep * Kdf, with Kdf computed on the composite section.

civilpy.structural.aashto.lrfd.prestressed.ps_refined_loss_shrinkage_girder(eps_bid: float, k_id: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder shrinkage between transfer and deck placement (5.9.3.4.2a-1): eps_bid * Ep * Kid.

eps_bid is the girder shrinkage strain over that interval (from shrinkage_strain()), k_id from ps_section_age_adjustment(). capacity holds the loss (ksi).

civilpy.structural.aashto.lrfd.prestressed.ps_section_age_adjustment(a_ps: float, a_g: float, i_g: float, e_pg: float, psi_final: float, e_ci: float, e_p: float = 28500.0) float[source]

Transformed-section/age-adjusted coefficient Kid (5.9.3.4.2a-2) — or Kdf with composite-section properties (5.9.3.4.3a-2).

e_pg is the strand eccentricity from the section centroid (in), psi_final the creep coefficient psi(tf, ti), e_ci the concrete modulus at transfer (ksi).

civilpy.structural.aashto.lrfd.prestressed.ps_service_compression_check(f_c: float, stress_permanent: float | None = None, stress_total: float | None = None, phi_w: float = 1.0) CheckResult[source]

Service-level compressive stress limits after losses (5.9.2.3.2a): 0.45*f’c under effective prestress plus permanent loads, and 0.60*phi_w*f’c under the full Service I combination (phi_w is the slenderness reduction for thin-walled sections; 1.0 for solid beams).

The governing case (lowest margin) populates capacity/demand; both are reported in details.

civilpy.structural.aashto.lrfd.prestressed.ps_service_tension_check(f_c: float, stress: float | None = None, severe_corrosion: bool = False, lam: float = 1.0) CheckResult[source]

Service III tensile stress limit after losses for components with bonded tendons (5.9.2.3.2b): 0.19*lam*sqrt(f’c) <= 0.6 ksi, halved in effect for severe corrosion conditions (0.0948*lam*sqrt(f’c) <= 0.3 ksi). stress is tensile stress magnitude (ksi, positive).

civilpy.structural.aashto.lrfd.prestressed.ps_splitting_resistance(a_s_end: float, p_r_demand: float | None = None, f_s: float = 20.0) CheckResult[source]

Splitting (bursting) resistance at pretensioned member ends (5.9.4.4.1-1): Pr = fs * As, where As is the reinforcement within h/4 of the end and fs is limited to 20 ksi. Pr must resist at least 4% of the total prestress force at transfer — pass 0.04*Ppt as the demand.

civilpy.structural.aashto.lrfd.prestressed.ps_strand_development(f_ps: float, f_pe: float, d_b: float, kappa: float = 1.6, embedment: float | None = None) CheckResult[source]

Development length of bonded pretensioned strand (5.9.4.3.2-1): ld >= kappa * (fps - 2/3*fpe) * db, with transfer length 60*db.

kappa = 1.6 for members deeper than 24 in, 1.0 otherwise. capacity holds the required ld (in); pass the available embedment as the demand side — note this check is inverted (embedment must exceed ld), so ok is computed accordingly.

civilpy.structural.aashto.lrfd.prestressed.ps_strand_stress_at_nominal(a_ps: float, f_pu: float, d_p: float, f_c: float, b: float, b_w: float | None = None, h_f: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, d_s: float = 0.0, a_s_prime: float = 0.0, f_y_prime: float | None = None, k: float = 0.28) CheckResult[source]

Average stress fps in bonded prestressing strands when the section reaches its nominal flexural resistance (5.6.3.1.1), with the neutral axis found for rectangular or flanged behavior.

capacity holds fps (ksi). a_ps is strand area (in^2) at depth d_p; b is the compression-face width, b_w/h_f the web width and flange thickness for T-shaped behavior; mild steel a_s / a_s_prime may be included. k is 0.28 for low-relaxation strand, 0.38 for stress-relieved.

civilpy.structural.aashto.lrfd.prestressed.ps_strand_stress_unbonded(a_ps: float, f_pe: float, d_p: float, f_c: float, b: float, l_i: float, f_py: float, n_s: int = 0, b_w: float | None = None, h_f: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, a_s_prime: float = 0.0, f_y_prime: float | None = None, max_iter: int = 100, tol: float = 1e-06) CheckResult[source]

Average stress fps in unbonded strands at nominal flexural resistance (5.6.3.1.2-1), with the effective tendon length from 5.6.3.1.2-2:

fps = fpe + 900 (dp - c) / le <= fpy, le = 2 li / (2 + Ns)

An unbonded tendon slips relative to the concrete, so its strain change averages over le instead of peaking at the critical section – fps lands far below the bonded 5.6.3.1.1 value. l_i is the tendon length between anchorages (in); n_s the number of support hinges crossed. fps and the neutral axis are solved together by fixed-point iteration from the commentary’s fpe + 15 start; rectangular or flanged behavior as in ps_strand_stress_at_nominal(). capacity holds fps (ksi).

civilpy.structural.aashto.lrfd.prestressed.ps_tendon_stress_limits(f_pu: float, f_py: float | None = None, tendon_type: str = 'low_relaxation') dict[source]

Tendon stress limits of Table 5.9.2.2-1 (ksi) keyed by condition: pre_* rows for pretensioning (prior to transfer, service after losses), post_* rows for post-tensioning (prior to seating, at anchorages/couplers immediately after anchor set, elsewhere after set, service after losses).

f_py defaults to 0.90*f_pu (low-relaxation) or 0.85*f_pu (stress-relieved / plain bar). Midas reports these as the AFDL1 / AFDL2 / AFLL1 allowables against the computed FDL1 / FDL2 / FLL1 tendon stresses.

civilpy.structural.aashto.lrfd.prestressed.ps_transfer_compression_check(f_ci: float, stress: float | None = None, design_year: int | None = None) CheckResult[source]

Compressive stress limit at transfer (5.9.2.3.1a): 0.65*f’ci, or 0.60*f’ci for designs before the 2016 interim revisions (pass design_year for historical designs). stress is the computed compressive stress magnitude (ksi, positive).

civilpy.structural.aashto.lrfd.prestressed.ps_transfer_tension_check(f_ci: float, stress: float | None = None, bonded_reinforcement: bool = False, lam: float = 1.0) CheckResult[source]

Tensile stress limit at transfer (5.9.2.3.1b): 0.0948*lam*sqrt(f’ci) capped at 0.2 ksi without bonded reinforcement sized for the tensile force, or 0.24*lam*sqrt(f’ci) with it. stress is tensile stress magnitude (ksi, positive).

civilpy.structural.aashto.lrfd.railing module

AASHTO LRFD Section 13 / Appendix A13 — traffic railing and parapet checks.

Yield-line analysis of concrete parapets (A13.3.1) and the deck-overhang force effects it generates (A13.4.2), implemented directly from the specification; validate against hand calcs or agency design aids.

Units: the yield-line equations are dimensionally consistent — use any one length unit throughout. Customary usage (and the test-level table below) is kip and ft: H and Lt in ft, Mb and Mw in kip-ft, Mc in kip-ft/ft, giving Rw in kip.

The crash test-level table reflects Table A13.2-1. The design forces, distribution lengths, and minimum effective heights are unchanged from the 1st Edition (NCHRP Report 350 test levels) through the 10th Edition (2024, MASH-era); the 10th Edition adds the minimum rail height H row carried here as h_min.

class civilpy.structural.aashto.lrfd.railing.TestLevelLoad(f_t: float, f_l: float, f_v: float, l_t: float, l_v: float, h_e_min: float, h_min: float)[source]

Bases: object

Design forces for one crash test level (Table A13.2-1).

f_t/f_l/f_v are the transverse, longitudinal, and vertical (down) forces in kip; l_t (= l_l) and l_v their distribution lengths in ft; h_e_min the minimum effective height and h_min the minimum rail height, both in inches.

f_l: float
f_t: float
f_v: float
h_e_min: float
h_min: float
l_t: float
l_v: float
civilpy.structural.aashto.lrfd.railing.deck_overhang_collision_tension(r_w: float, l_c: float, h: float) CheckResult[source]

Axial tensile force per unit length transmitted to the deck overhang when the parapet reaches its yield-line resistance (A13.4.2 Design Case 1): T = Rw/(Lc + 2H), spread over the distribution length at the deck level.

capacity holds T (kip/ft when Rw is kip and Lc/H are ft); the deck overhang reinforcement must then resist T concurrent with the overhang moment.

civilpy.structural.aashto.lrfd.railing.parapet_test_level_check(test_level: str, m_c: float, m_w: float, h_ft: float, m_b: float = 0.0, end_region: bool = False) CheckResult[source]

Convenience wrapper: yield-line capacity checked against a Table A13.2-1 test level. h_ft is wall height in ft; the result’s details flag whether the wall also meets the minimum effective height and the minimum rail height for the test level.

civilpy.structural.aashto.lrfd.railing.parapet_yield_line_capacity(m_c: float, m_w: float, h: float, l_t: float, m_b: float = 0.0, f_t: float | None = None, end_region: bool = False) CheckResult[source]

Total transverse resistance Rw of a concrete parapet by yield-line analysis (A13.3.1), compared against the rail design force Ft.

m_c is the wall’s flexural resistance about its longitudinal axis per unit length (kip-ft/ft), m_w its resistance about the vertical axis (kip-ft), m_b any additional beam/rail resistance at top (kip-ft), h the wall height (ft), l_t the load distribution length (ft). end_region=True uses the end/joint mechanism, which mobilizes a single yield-line fan and gives a shorter critical length.

civilpy.structural.aashto.lrfd.splices module

AASHTO LRFD 6.13.6.1 — bolted field splices for flexural members (8th Edition simplified method).

These functions produce the splice design forces; the plates and bolts are then checked with the existing primitives ( tension_member_resistance(), bolt_shear_resistance, bolt_slip_resistance, block_shear_resistance). Units: kip, inch, ksi.

class civilpy.structural.aashto.lrfd.splices.FlangeSplicePlates(outer_width: float, outer_thickness: float, inner_width: float, inner_width_exact: float, inner_thickness: float, inner_thickness_band: tuple[float, float], clearance: float, min_thickness: float)[source]

Bases: object

Proportioned flange splice plates (C6.13.6.1.3b and the AASHTO/NSBA “develop the flange” guidance). A single outer plate spans the full flange width; a pair of inner plates straddle the web, separated by the clearance gap needed for the web and its fillet welds. Widths and thicknesses in inches.

inner_thickness is the ideal thickness that makes the two inner plates equal in area to the outer plate; inner_thickness_band is the (low, high) range that keeps the inner/outer areas within 10% so the connection may be proportioned for the full flange force in double shear (C6.13.6.1.3b). Pick any standard plate inside the band.

clearance: float
inner_thickness: float
inner_thickness_band: tuple[float, float]
inner_width: float
inner_width_exact: float
min_thickness: float
outer_thickness: float
outer_width: float
class civilpy.structural.aashto.lrfd.splices.SpacingLimits(min_spacing: float, max_spacing_seal: float, min_edge: float, max_edge: float, pitch_ok: bool | None, gage_ok: bool | None, edge_ok: bool | None, end_ok: bool | None)[source]

Bases: object

Result of the 6.13.2.6 layout limit checks. Each *_ok flag is True when the corresponding provided dimension is within the spec limit; the limit values are exposed for reporting.

edge_ok: bool | None
end_ok: bool | None
gage_ok: bool | None
max_edge: float
max_spacing_seal: float
min_edge: float
min_spacing: float
pitch_ok: bool | None
class civilpy.structural.aashto.lrfd.splices.SplicePlateForces(outer: float, inner: float, double_shear: bool, ratio_outer: float)[source]

Bases: object

How the flange design force Pfy is apportioned to the inner and outer splice plates (C6.13.6.1.3b). double_shear is True when the inner and outer plate areas are within 10% and the force is shared equally (each plate group works in double shear at Pfy/2); otherwise each plate carries the fraction of Pfy proportional to its area.

double_shear: bool
inner: float
outer: float
ratio_outer: float
class civilpy.structural.aashto.lrfd.splices.WebSpliceForces(v_uw: float, h_w: float, per_bolt: float, n_bolts: int)[source]

Bases: object

Design forces for a web splice (6.13.6.1.3c): the vertical design shear Vuw, the horizontal force Hw from the moment not carried by the flanges, and the resultant per-bolt force to compare against the bolt shear/slip resistance.

h_w: float
n_bolts: int
per_bolt: float
v_uw: float
class civilpy.structural.aashto.lrfd.splices.WebSplicePlates(thickness: float, min_thickness: float, height: float, max_pitch_seal: float, min_bolts_per_row: int, filler_required: bool)[source]

Bases: object

Proportioned web splice plates (6.13.6.1.3c; 6.13.2.6.2). A pair of plates covers each face of the web over nearly the full depth. height is the plate depth (near-full web depth); max_pitch_seal is the maximum bolt spacing for sealing (6.13.2.6.2) and min_bolts_per_row the resulting minimum number of bolts in a vertical line. Inches.

filler_required: bool
height: float
max_pitch_seal: float
min_bolts_per_row: int
min_thickness: float
thickness: float
civilpy.structural.aashto.lrfd.splices.bolt_spacing_limits(d_bolt: float, plate_t: float, pitch: float | None = None, gage: float | None = None, edge_dist: float | None = None, end_dist: float | None = None, sheared_edge: bool = False) SpacingLimits[source]

Geometric layout limits for a bolt group (6.13.2.6):

  • minimum spacing (pitch and gage) = 3.0*d (6.13.2.6.1);

  • maximum spacing for sealing = min(4.0 + 4.0*t, 7.0) in (6.13.2.6.2);

  • minimum edge/end distance from Table 6.13.2.6.6-1;

  • maximum edge distance = min(8.0*t, 5.0) in (6.13.2.6.6).

Any provided dimension is checked against its limit and the boolean flag set accordingly; None dimensions leave the flag None.

civilpy.structural.aashto.lrfd.splices.filler_plate_reduction(a_f: float, a_p: float, total_filler_thickness: float = 1.0) CheckResult[source]

Bolt shear-resistance reduction for fillers (6.13.6.1.4). When the total thickness of the fillers is 0.25 in or greater, the factored bolt shear resistance is multiplied by R = (1 + gamma)/(1 + 2*gamma), with gamma = Af/Ap; Af is the sum of the filler areas and Ap is the smaller of the connected-plate area or the sum of the splice-plate areas. Below 0.25 in of filler, R = 1.0. capacity holds R.

civilpy.structural.aashto.lrfd.splices.flange_design_stress_fcf(fcf: float, f_yf: float, r_h: float = 1.0, alpha: float = 1.0, phi_f: float = 1.0) float[source]

Flange design stress Fcf (AASHTO LRFD 6.13.6.1.3b):

Fcf = max( (|fcf|/Rh + alpha*phi_f*Fyf)/2 , 0.75*alpha*phi_f*Fyf )

fcf is the maximum factored flexural stress at the mid-thickness of the flange under the governing strength combination (ksi, sign ignored). Rh is the hybrid factor (1.0 non-hybrid), alpha = 1.0 (0.85 for compression flanges w/ slender web), phi_f = 1.0. The result is capped in practice by Fyf and floored at 0.75*alpha*phi_f*Fyf (the minimum splice design stress of C6.13.6.1.3b).

civilpy.structural.aashto.lrfd.splices.flange_moment_resistance(flange_force: float, moment_arm: float, m_u: float | None = None) CheckResult[source]

Moment the flange splices alone can resist as a force couple (6.13.6.1.3c): Mflange = Pfl * arm. Compared against the factored design moment m_u; any excess |Mu| - Mflange is carried by the web as the horizontal force Hw (see web_splice_design_forces()). Forces in kip, arm in inches, moments in kip-in.

civilpy.structural.aashto.lrfd.splices.flange_splice_design_force(a_n: float, a_g: float, f_y: float, f_u: float, f_design: float | None = None) CheckResult[source]

Design force for a flange splice (6.13.6.1.3b-1): P = Fcf*Ae with the effective flange area Ae = (phi_u*Fu)/(phi_y*Fy)*An <= Ag (6.13.6.1.3b-2); phi_u = 0.80, phi_y = 0.95.

f_design is the flange design stress Fcf (6.13.6.1.3b): when omitted it defaults to the full yield stress f_y (the conservative upper bound, correct for a fully stressed flange). Supply the AASHTO Fcf – max((|fcf|/Rh + alpha*phi_f*Fyf)/2, 0.75*alpha*phi_f*Fyf) computed from the actual factored flange stress fcf – to design a lightly stressed splice for its real demand (the ODOT BDM / NSBA workbook method).

The splice plates, their bolts, and the flange itself are then checked against the returned force. capacity holds P (kip).

civilpy.structural.aashto.lrfd.splices.net_section_reduction_limit(a_n: float, a_g: float) CheckResult[source]

Effective net area limit for splice plates in tension (6.13.5.2): the net area used for the fracture check is taken as An but not more than 0.85*Ag. Reported as a NOTICE (not a strength failure): ok is True when An <= 0.85*Ag; details['An_eff'] is the area to use downstream.

civilpy.structural.aashto.lrfd.splices.size_flange_splice_plates(flange_width_left: float, flange_width_right: float, flange_thickness: float, web_thickness_left: float, web_thickness_right: float, weld_size: float = 0.0, outer_thickness: float | None = None, width_increment: float = 0.5, thickness_increment: float = 0.0625) FlangeSplicePlates[source]

Proportion the outer and inner flange splice plates from the girder geometry (C6.13.6.1.3b; NSBA Bolted Field Splices for Steel Bridge Flexural Members).

  • Outer plate width = the narrower connected flange, min(bf_left, bf_right) — the outer plate must be at least as wide as the narrowest flange at the splice.

  • Web clearance gap = max(tw_left, tw_right) + 2*(weld_size + 1/8) so the inner plates clear the web and its fillet welds.

  • Inner plate width = (outer_width - clearance)/2 (each of the pair), rounded down to width_increment.

  • Minimum plate thickness = flange_thickness/2 + 1/16.

  • With the outer thickness chosen (defaults to the rounded-up minimum), the ideal inner thickness equalises the plate areas: t_inner = t_outer * b_outer / (2*b_inner_exact), rounded up to thickness_increment; the returned band keeps the areas within 10%.

flange_thickness is the thickness of the flange being developed (the thicker adjoining flange governs the minimum plate thickness).

civilpy.structural.aashto.lrfd.splices.size_web_splice_plate(web_depth: float, web_thickness: float, web_thickness_other: float, flange_clearance: float, thickness: float | None = None, thickness_increment: float = 0.0625) WebSplicePlates[source]

Proportion the web splice plates from the web geometry (6.13.6.1.3c; seal spacing 6.13.2.6.2).

  • Minimum plate thickness = web_thickness/2 + 1/16 (web_thickness is the governing/thinner connected web).

  • Plate height = web_depth - 2*flange_clearance — the plates extend nearly the full web depth, clearing the flanges by flange_clearance top and bottom.

  • Maximum bolt pitch for sealing = min(4.0 + 4.0*t, 7.0) in (6.13.2.6.2), giving a minimum of 1 + ceil(height/max_pitch) bolts in each vertical line.

  • A filler is required when the two webs differ by more than 1/16 in.

No filler is needed when the web-thickness difference is under 1/16 in.

civilpy.structural.aashto.lrfd.splices.slab_crushing_resistance(f_c: float, b_eff: float, t_s: float, demand_force: float | None = None) CheckResult[source]

Plastic compressive force the composite deck can deliver at the splice (Appendix D6.1): Prb = 0.85*f’c*b_eff*t_s. For a composite section the flange tension force plus the web horizontal force Hw must not exceed this, otherwise the deck is over-stressed and the splice should be designed as non-composite. Pass demand_force = flange force + Hw.

civilpy.structural.aashto.lrfd.splices.splice_plate_design_force(p_fy: float, a_g_outer: float, a_g_inner: float) SplicePlateForces[source]

Apportion the flange design force Pfy between the outer and inner splice plates (C6.13.6.1.3b). If the plate areas differ by no more than 10%, the force is divided equally (double shear, Pfy/2 each); otherwise it is split in proportion to plate area.

civilpy.structural.aashto.lrfd.splices.web_splice_design_forces(v_r_web: float, n_bolts: int, m_u: float = 0.0, m_flange: float = 0.0, moment_arm: float | None = None) WebSpliceForces[source]

Web splice design forces (6.13.6.1.3c, 8th Ed. method).

v_r_web is the smaller factored shear resistance phi_v*Vn of the webs on either side of the splice (6.10.9) — the web splice is designed for the full web capacity, not the applied shear. When the factored moment m_u (kip-in) exceeds the moment the flange splices can carry m_flange, the excess is resisted by a horizontal force couple in the web: Hw = (|Mu| - Mrf)/arm. Each of the n_bolts (one side of the splice) sees the vector sum of Vuw/Nb and Hw/Nb.

civilpy.structural.aashto.lrfd.steel module

AASHTO LRFD Chapter 6 — steel I-girder design checks.

Articles follow the 9th/10th Edition numbering (unchanged since the 5th Edition for these checks). Units: kip, inch, ksi.

civilpy.structural.aashto.lrfd.steel.bearing_stiffener_effective_column(b_t: float, t_p: float, t_w: float, d_web: float, f_ys: float, pairs: int = 1, p_u: float | None = None, design_year: int | None = None) CheckResult[source]

Axial resistance of the bearing-stiffener effective column (6.10.11.2.4): the stiffener plates acting with a web strip extending 9*tw to each side, radius of gyration about the web mid-thickness, KL = 0.75*D, resistance per 6.9.4.1.1 (Q = 1.0 — bearing stiffeners are exempt from the slender-element reduction).

civilpy.structural.aashto.lrfd.steel.bearing_stiffener_resistance(a_pn: float, f_ys: float, r_u: float | None = None) CheckResult[source]

Bearing resistance of fitted bearing-stiffener ends (6.10.11.2.3-1): Rn = 1.4*Apn*Fys with phi_b = 1.0.

a_pn is the stiffener area in contact with the flange after the clip for the web-to-flange weld (in^2). The companion axial check of the stiffener-plus-web effective column (6.10.11.2.4) composes with compression_member_resistance() using KL = 0.75*D and the effective-section properties.

civilpy.structural.aashto.lrfd.steel.bearing_stiffener_width(b_t: float, t_p: float, f_ys: float) CheckResult[source]

Bearing-stiffener projecting-width limit (6.10.11.2.2-1): b_t <= 0.48 * t_p * sqrt(E/Fys).

civilpy.structural.aashto.lrfd.steel.block_shear_resistance(a_vg: float, a_vn: float, a_tn: float, f_y: float, f_u: float, p_u: float | None = None, u_bs: float = 1.0, punched_holes: bool = False) CheckResult[source]

Block shear rupture (6.13.4-1): Rn = Rp*(0.58*Fu*Avn + Ubs*Fu*Atn), not to exceed Rp*(0.58*Fy*Avg + Ubs*Fu*Atn); phi_bs = 0.80.

u_bs = 1.0 for uniform tension stress, 0.5 for nonuniform; Rp = 0.9 for punched holes, 1.0 drilled.

civilpy.structural.aashto.lrfd.steel.bolt_bearing_resistance(d_bolt: float, t_ply: float, f_u_ply: float, clear_distance: float, v_u: float | None = None) CheckResult[source]

Bearing on connected material at a bolt hole (6.13.2.9): Rn = 2.4*d*t*Fu when the clear distance to the next hole or end is at least 2.0*d, else Rn = 1.2*Lc*t*Fu. phi_bb = 0.80.

civilpy.structural.aashto.lrfd.steel.bolt_shear_resistance(d_bolt: float, f_ub: float, n_planes: int = 1, threads_excluded: bool = True, v_u: float | None = None, long_joint: bool = False, design_year: int | None = None) CheckResult[source]

Shear resistance of a high-strength bolt (6.13.2.7): Rn = C*Ab*Fub*Ns; joints longer than 38 in between extreme bolts take a 0.83 reduction. phi_s = 0.80.

The shear-strength coefficient C was raised in the 8th Edition (2017): design_year >= 2017 uses C = 0.56 (threads excluded) / 0.45 (threads included); earlier editions (the default) use 0.48 / 0.38.

civilpy.structural.aashto.lrfd.steel.bolt_slip_resistance(bolt_grade: str, d_bolt: float, n_planes: int = 1, hole_type: str = 'standard', surface_class: str = 'B', v_serv: float | None = None) CheckResult[source]

Slip resistance of one bolt in a slip-critical connection (6.13.2.8-1): Rn = Kh*Ks*Ns*Pt, checked under Service II (phi = 1.0). Pretension Pt from Table 6.13.2.8-2.

civilpy.structural.aashto.lrfd.steel.classify_composite_positive(d_cp: float, t_w: float, f_yc: float, f_yt: float, d_web: float, straight: bool = True, has_longitudinal_stiffeners: bool = False) CheckResult[source]

Compact / noncompact classification of a composite section in positive flexure (6.10.6.2.2). Compact requires all of: a straight bridge, both flange yield strengths <= 70 ksi, the web proportion limit of 6.10.2.1.1 (no longitudinal stiffeners), and 2*Dcp/tw <= 3.76*sqrt(E/Fyc).

d_cp is the depth of web in compression at the plastic moment (D6.3.2 — zero when the PNA is in or above the top flange, which is why most composite positive sections classify compact trivially). capacity is 1.0 when compact; per-condition booleans in details.

civilpy.structural.aashto.lrfd.steel.classify_web_negative(d_c: float, t_w: float, f_yc: float, f_yt: float, i_yc: float, i_yt: float, straight: bool = True) CheckResult[source]

Slender-web screen for composite sections in negative flexure and noncomposite sections (6.10.6.2.3): sections of straight bridges with flange yields <= 70 ksi, web slenderness 2*Dc/tw < 5.7*sqrt(E/Fyc), and Iyc/Iyt >= 0.3 may use the Appendix A6 provisions (web plastification, resistances up to Mp); anything else takes the slender-web 6.10.8 stress-based path.

d_c is the elastic depth of web in compression (D6.3.1). capacity is 1.0 when A6-eligible (nonslender); details carry the slenderness numbers.

civilpy.structural.aashto.lrfd.steel.compact_composite_positive_flexure(m_p: float, d_p: float, d_t: float, m_u: float | None = None, m_y: float | None = None, r_h: float = 1.0, continuous_span: bool = False) CheckResult[source]

Nominal flexural resistance of a compact composite section in positive flexure (6.10.7.1.2): Mn = Mp when Dp <= 0.1*Dt, else the penalty Mn = Mp*(1.07 - 0.7*Dp/Dt); continuous spans not meeting the B6 conditions cap Mn at 1.3*Rh*My.

m_p is the plastic moment (kip-in, from a D6.1 PNA analysis), d_p the depth from the top of slab to the PNA, d_t the total composite depth. The 6.10.7.3 ductility limit Dp <= 0.42*Dt is reported in details.

civilpy.structural.aashto.lrfd.steel.compression_flange_resistance(l_b: float, b_fc: float, t_fc: float, d_c: float, t_w: float, f_yc: float, f_yw: float, c_b: float = 1.0, f_bu: float | None = None, r_b: float = 1.0, r_h: float = 1.0) CheckResult[source]

Compression-flange flexural resistance Fnc (6.10.8.2.1-1): the smaller of local buckling (6.10.8.2.2) and lateral-torsional buckling (6.10.8.2.3).

civilpy.structural.aashto.lrfd.steel.compression_member_resistance(a_g: float, f_y: float, kl_over_r: float, p_u: float | None = None, q_slender: float = 1.0, design_year: int | None = None) CheckResult[source]

Axial compressive resistance of a non-slender-element column (6.9.4.1.1): Pe = pi^2*E/(KL/r)^2 * Ag; Po = Q*Fy*Ag; Pn = 0.658^(Po/Pe)*Po when Pe >= 0.44*Po, else 0.877*Pe.

q_slender is the slender-element reduction (6.9.4.2; 1.0 for nonslender plates). phi_c is 0.95 (0.90 for designs before the 2015 interim — pass design_year).

civilpy.structural.aashto.lrfd.steel.connection_element_shear(a_vg: float, f_y: float, a_vn: float | None = None, f_u: float | None = None, v_u: float | None = None) CheckResult[source]

Shear resistance of a connection element — splice/gusset plate (6.13.5.3): gross-section yielding Rr = phi_v*0.58*Fy*Avg (phi = 1.0); net-section rupture Rr = phi_vu*0.58*Fu*Avn (phi = 0.80) when the net path is given. The governing factored resistance is reported.

civilpy.structural.aashto.lrfd.steel.constructibility_compression_flange(f_bu: float, f_l: float, f_yc: float, f_nc: float, f_crw: float | None = None, r_h: float = 1.0, slender_web: bool = False) CheckResult[source]

Constructibility checks on a discretely braced compression flange during deck placement (6.10.3.2.1): flange yielding fbu + fl <= phi*Rh*Fyc (skipped for slender webs), flange buckling fbu + fl/3 <= phi*Fnc, and web bend-buckling fbu <= phi*Fcrw.

f_bu/f_l are the factored vertical-bending and lateral-bending flange stresses under the steel-plus-wet-concrete condition; f_nc from the 6.10.8.2 functions and f_crw from web_bend_buckling(). capacity/demand carry the governing case; all three appear in details.

civilpy.structural.aashto.lrfd.steel.continuously_braced_flange(f_yf: float, f_bu: float | None = None, r_h: float = 1.0) CheckResult[source]

Continuously braced flange in tension or compression (6.10.8.1.3-1): f_bu <= phi_f * Rh * Fyf (no lateral-bending term — the deck braces the flange continuously).

civilpy.structural.aashto.lrfd.steel.discretely_braced_compression_flange(f_nc: float, f_bu: float, f_l: float = 0.0, f_yf: float | None = None) CheckResult[source]

Discretely braced compression-flange check (6.10.8.1.1-1): f_bu + f_l/3 <= phi_f * Fnc, with f_nc from 6.10.8.2.1 and f_l the flange lateral bending stress. When f_yf is given the 6.10.1.6 limit f_l <= 0.6*Fyf is also verified (reported in details).

civilpy.structural.aashto.lrfd.steel.fatigue_resistance(category: str, delta_f: float | None = None, fatigue_i: bool = True, adtt_sl: float = 1000.0, n_cycles_per_truck: float = 1.0, design_life_years: float = 75.0) CheckResult[source]

Nominal fatigue resistance (6.6.1.2.5): Fatigue I (infinite life) uses the constant-amplitude threshold (delta_F)TH; Fatigue II (finite life) uses (A/N)^(1/3) with N = 365 * years * n * ADTT_SL.

category is the Table 6.6.1.2.3-1 detail category (A through E’); delta_f the live-load stress range demand (ksi).

civilpy.structural.aashto.lrfd.steel.fillet_weld_resistance(leg_size: float, f_exx: float = 70.0, length: float = 1.0, v_u: float | None = None) CheckResult[source]

Factored shear resistance of a fillet weld on its effective throat (6.13.3.2.4b): Rr = 0.6*phi_e2*Fexx with phi_e2 = 0.80, applied to the throat 0.707*leg. capacity holds the factored resistance for the given length of weld (kip), so phi is 1.0 on the result.

civilpy.structural.aashto.lrfd.steel.flange_local_buckling_resistance(b_fc: float, t_fc: float, f_yc: float, f_yw: float, f_bu: float | None = None, r_b: float = 1.0, r_h: float = 1.0) CheckResult[source]

Compression-flange local buckling resistance Fnc (6.10.8.2.2).

Parameters: flange width b_fc and thickness t_fc (in), yield strengths f_yc/f_yw (ksi), factored compression-flange stress f_bu (ksi, optional demand), web load-shedding factor r_b (6.10.1.10.2) and hybrid factor r_h (6.10.1.10.1).

civilpy.structural.aashto.lrfd.steel.hybrid_factor(d_n: float, t_w: float, a_fn: float, f_yw: float, f_n: float) CheckResult[source]

Hybrid factor Rh (6.10.1.10.1-1) accounting for early web yielding when the web is a lower grade than the flanges: Rh = (12 + beta*(3*rho - rho^3)) / (12 + 2*beta), rho = min(Fyw/fn, 1), beta = 2*Dn*tw/Afn.

d_n is the distance from the elastic NA to the inside of the controlling flange (in), a_fn that flange’s area (in^2), f_n its yield (or buckling) stress. Homogeneous girders get Rh = 1.0. capacity holds Rh.

civilpy.structural.aashto.lrfd.steel.lateral_torsional_buckling_resistance(l_b: float, b_fc: float, t_fc: float, d_c: float, t_w: float, f_yc: float, f_yw: float, c_b: float = 1.0, f_bu: float | None = None, r_b: float = 1.0, r_h: float = 1.0) CheckResult[source]

Compression-flange lateral torsional buckling resistance Fnc (6.10.8.2.3).

Parameters: unbraced length l_b (in), compression flange b_fc x t_fc (in), depth of web in compression d_c (in), web thickness t_w (in), yield strengths (ksi), moment gradient modifier c_b, optional factored flange stress demand f_bu (ksi).

civilpy.structural.aashto.lrfd.steel.longitudinal_stiffener_proportions(proj_width: float, t_s: float, moment_of_inertia: float, radius_of_gyration: float, d_web: float, t_w: float, d_o: float, f_ys: float, f_yc: float, r_h: float = 1.0, beta: float = 1.0) CheckResult[source]

Longitudinal web-stiffener proportioning limits (6.10.11.3).

Three requirements, all expressed as provided/required margins; the governing (minimum) margin is the reported ratio (>= 1.0 passes):

  • projecting width (6.10.11.3.2-1): proj_width <= 0.48 t_s sqrt(E/Fys)

  • moment of inertia (6.10.11.3.3-1): I_l >= D tw^3 [2.4 (do/D)^2 - 0.13] beta

  • radius of gyration (6.10.11.3.3-4): r >= 0.16 do sqrt(Fys/E) / sqrt(1 - 0.6 Fyc/(Rh Fys))

proj_width is the stiffener projecting width b_l (in), t_s its thickness (in), moment_of_inertia I_l about the web face (in^4), radius_of_gyration r (in), d_web the web depth D (in), d_o the transverse-stiffener/panel spacing (in), beta the curvature factor (1.0 for straight girders, 6.10.11.3.3-2 for curved). capacity/demand carry the I_l pair (the sizing driver); the width and r margins are in details.

civilpy.structural.aashto.lrfd.steel.nonslender_element_limit(b: float, t: float, f_y: float, k: float = 0.45) CheckResult[source]

Plate width-to-thickness limit for a nonslender compression element (6.9.4.2.1-1): b/t <= k*sqrt(E/Fy). k per Table 6.9.4.2.1-1 (0.45 outstanding angle legs / plates supported on one edge, 0.56 rolled-shape flanges, 1.49 stiffened webs). Exceeding the limit means the member needs the slender-element Q reduction (6.9.4.2.2).

civilpy.structural.aashto.lrfd.steel.proportion_limits(d_web: float, t_w: float, b_fc: float, t_fc: float, b_ft: float, t_ft: float, i_yc: float | None = None, i_yt: float | None = None) CheckResult[source]

I-girder proportion limits (6.10.2): web D/tw <= 150 (without longitudinal stiffeners); each flange bf/2tf <= 12, bf >= D/6, tf >= 1.1*tw; and 0.1 <= Iyc/Iyt <= 10 when flange inertias are given.

Pass/fail only — capacity is 1.0/0.0 against a demand of 1.0 so ok reflects all limits; per-limit booleans are in details.

civilpy.structural.aashto.lrfd.steel.shear_connector_fatigue_pitch(d_stud: float, n_per_row: int, shear_flow: float, n_cycles: float | None = None, pitch: float | None = None) CheckResult[source]

Required stud pitch for fatigue (6.10.10.1.2): p <= n*Zr/Vsr, where the fatigue resistance of one stud is Zr = 5.5*d^2 for Fatigue I (infinite life, n_cycles omitted) or Zr = alpha*d^2 with alpha = 34.5 - 4.28*log10(N) for Fatigue II (6.10.10.2). (The old 4th-edition single-combination rule floored alpha*d^2 at 5.5*d^2/2; the floor died with the Fatigue I/II split.)

shear_flow is the fatigue shear flow Vsr = Vf*Q/I (kip/in). capacity is the maximum permitted pitch (in); pass the actual pitch as demand — note larger-is-worse, so ok means pitch <= max.

civilpy.structural.aashto.lrfd.steel.shear_connector_fatigue_resistance(d_stud: float, n_cycles: float | None = None) CheckResult[source]

Fatigue shear resistance of one stud (6.10.10.2): Fatigue I (infinite life, n_cycles=None): Zr = 5.5*d^2 (6.10.10.2-1). Fatigue II: Zr = alpha*d^2 with alpha = 34.5 - 4.28*log10(N).

civilpy.structural.aashto.lrfd.steel.shear_connector_strength(d_stud: float, f_c: float, e_c: float, nominal_force: float | None = None, f_u_stud: float = 60.0) CheckResult[source]

Nominal resistance of one stud shear connector (6.10.10.4.3-1): Qn = 0.5*Asc*sqrt(f’c*Ec) <= Asc*Fu, phi_sc = 0.85.

Pass the interface force nominal_force P (6.10.10.4.2 — the lesser of the deck crushing and steel yielding forces, kip) to get the required connector count in details.

civilpy.structural.aashto.lrfd.steel.shear_connector_transverse_spacing(d_stud: float, n_per_row: int, gauge_in: float, flange_width_in: float) CheckResult[source]

Transverse spacing limits for stud rows (6.10.10.3): center-to-center >= 4 stud diameters, and clear distance from the flange edge to the nearest stud >= 1.0 in. The governing margin is the reported ratio.

civilpy.structural.aashto.lrfd.steel.stability_bracing_torsional(m_r: float, l_span: float, n_braces: int, i_eff: float, brace_stiffness: float, c_b: float = 1.0, l_b: float | None = None, phi: float = 0.75) CheckResult[source]

Torsional stability-bracing stiffness + strength for cross-frames / diaphragms (6.7.4.2.2, 10th Edition), the adopted Yura provisions.

  • Required torsional brace stiffness (stiffness limit): beta_Treq = 2.4 L Mr^2 / (phi n E I_eff C_b^2)

  • Required brace strength (moment): M_br = 0.024 Mr L / (n C_b L_b)

m_r is the required flexural strength Mr (kip-in), l_span the span L (in), n_braces the number of intermediate brace points, i_eff the effective lateral moment of inertia I_eff (in^4), brace_stiffness the provided torsional stiffness beta_T (kip-in/rad), c_b the moment gradient, l_b the unbraced length (in, defaults to L/(n+1)). The reported ratio is the provided/required stiffness margin; the required brace moment is in details.

NOTE: coefficients follow the adopted torsional-bracing model; validate against BrR (ALRFD_10E_06_07_04_02_02_Stiffness/_Strength) before relying on this for production ratings — flagged in the build plan.

civilpy.structural.aashto.lrfd.steel.tension_flange_resistance(f_yt: float, f_bu: float | None = None, f_l: float = 0.0, r_h: float = 1.0) CheckResult[source]

Tension-flange nominal resistance Fnt = Rh*Fyt (6.10.8.3), checked as fbu + fl/3 <= phi_f*Fnt (6.10.8.1.2-1). f_l is the flange lateral bending stress (ksi).

civilpy.structural.aashto.lrfd.steel.tension_member_resistance(a_g: float, f_y: float, a_n: float | None = None, f_u: float | None = None, u_shear_lag: float = 1.0, p_u: float | None = None) CheckResult[source]

Factored tensile resistance (6.8.2.1): lesser of yielding on the gross section (phi_y = 0.95) and rupture on the net section (phi_u = 0.80, with shear-lag factor U). capacity holds the governing factored resistance (phi already applied — phi on the result is 1.0 to avoid double-counting).

civilpy.structural.aashto.lrfd.steel.transverse_stiffener_inertia(moment_of_inertia: float, b_t: float, t_p: float, d_web: float, t_w: float, d_o: float, f_yw: float, f_ys: float, tension_field: bool = False) CheckResult[source]

Transverse-stiffener moment-of-inertia requirement (6.10.11.1.3).

moment_of_inertia is the provided I_t (in^4; single stiffener taken about the web face, a pair about the web mid-thickness).

  • I_t1 = b * tw^3 * J with b = min(d_o, D) and J = 2.5/(d_o/D)^2 - 2.0 >= 0.5 (6.10.11.1.3-1/-2)

  • I_t2 = D^4 * rho_t^1.3 / 40 * (Fyw/E)^1.5 (6.10.11.1.3-3), with rho_t = max(Fyw/Fcrs, 1.0) and Fcrs = 0.31 E/(b_t/t_p)^2 <= Fys (6.10.11.1.3-4)

Web shear buckling only (tension_field=False): I_t1 governs. When the web’s postbuckling (tension-field) resistance is relied on and I_t2 > I_t1, the requirement rises toward I_t2 — this implementation conservatively requires I_t2 on that path (the spec permits a shear-demand interpolation); validate_against_brr is set for the tension-field path.

civilpy.structural.aashto.lrfd.steel.transverse_stiffener_width(b_t: float, t_p: float, d_web: float, b_f: float) CheckResult[source]

Transverse-stiffener projecting-width limits (6.10.11.1.2): b_t >= 2.0 + D/30 (6.10.11.1.2-1) and 16*t_p >= b_t >= b_f/4 (6.10.11.1.2-2), with b_f the full width of the widest compression flange in the field section. The governing (minimum) margin is the reported ratio.

civilpy.structural.aashto.lrfd.steel.web_bend_buckling(d_web: float, t_w: float, d_c: float, f_yc: float, f_yw: float, r_h: float = 1.0) CheckResult[source]

Nominal web bend-buckling resistance (6.10.1.9.1-1): Fcrw = 0.9*E*k/(D/tw)^2 with k = 9/(Dc/D)^2, capped at min(Rh*Fyc, Fyw/0.7). capacity holds Fcrw (ksi).

civilpy.structural.aashto.lrfd.steel.web_load_shedding_factor(d_c: float, t_w: float, b_fc: float, t_fc: float, f_yc: float) CheckResult[source]

Web load-shedding factor Rb (6.10.1.10.2): 1.0 for compact and noncompact webs (2*Dc/tw <= lambda_rw = 5.7*sqrt(E/Fyc)); slender webs shed stress to the compression flange per -3: Rb = 1 - awc/(1200 + 300*awc) * (2*Dc/tw - lambda_rw) <= 1.0. capacity holds Rb.

civilpy.structural.aashto.lrfd.steel.web_shear_resistance(d_web: float, t_w: float, f_yw: float, v_u: float | None = None, d_o: float | None = None, tension_field: bool = False, b_fc: float | None = None, t_fc: float | None = None, b_ft: float | None = None, t_ft: float | None = None) CheckResult[source]

Nominal web shear resistance Vn (6.10.9).

Unstiffened webs (d_o is None): Vn = C*Vp (6.10.9.2-1). Stiffened interior panels with tension_field=True use 6.10.9.3.2-2, downgraded to 6.10.9.3.2-8 when the panel fails the flange-proportion limit 2*D*tw/(bfc*tfc + bft*tft) <= 2.5. d_web is the web depth D (in), d_o the transverse stiffener spacing (in), v_u the factored shear demand (kip).

civilpy.structural.aashto.lrfd.stm module

AASHTO LRFD 5.8.2 — strut-and-tie method capacity checks.

The geometry/force side (truss solution and diagram) lives in civilpy.structural.strut_and_tie; these functions check the solved member forces, implemented directly from the specification. Units: kip, inch, ksi. Pass strut forces as magnitudes (positive).

civilpy.structural.aashto.lrfd.stm.stm_crack_control_reinforcement(b_w: float, s_h: float, s_v: float, a_s_horizontal: float | None = None, a_s_vertical: float | None = None) CheckResult[source]

Orthogonal crack-control reinforcement in the D-region (5.8.2.6): a ratio of at least 0.003 in each direction, spacing <= min(d/4, 12in) checked by the caller.

Pass the provided bar areas per grid spacing (in^2 at s_h/s_v in); the check compares each direction’s ratio against 0.003. This is what qualifies the nodes for the full Table 5.8.2.5.3a-1 nu.

civilpy.structural.aashto.lrfd.stm.stm_node_resistance(a_cn: float, f_c: float, node_type: str = 'CCC', crack_control: bool = True, m_confinement: float = 1.0, p_u: float | None = None, nu: float | None = None) CheckResult[source]

Crushing resistance of a node face or the strut bearing on it (5.8.2.5.3): Pn = fcu*Acn with fcu = m*nu*f’c.

node_type is the joint classification (CCC, CCT, CTT) setting the efficiency factor nu from Table 5.8.2.5.3a-1; without crack-control reinforcement per 5.8.2.6, nu drops to 0.45. m_confinement is the sqrt(A2/A1) <= 2 bearing modification; pass nu directly to override the table. phi = 0.70.

civilpy.structural.aashto.lrfd.stm.stm_tie_resistance(a_st: float, f_y: float = 60.0, a_ps: float = 0.0, f_pe: float = 0.0, p_u: float | None = None) CheckResult[source]

Nominal resistance of a tie (5.8.2.4.1-1): Pn = fy*Ast + Aps*(fpe + fy), phi = 0.90.

The prestressing term caps the usable strand stress at fpe plus one mild-steel yield increment so tie strain stays compatible with the surrounding reinforcement. p_u is the solved tie force (kip).

civilpy.structural.aashto.lrfd.timber module

AASHTO LRFD Chapter 8 — wood structures.

The adjustment-factor chain (8.4.4) multiplies the reference design values: F = Fo * CKF * CM * (CF or Cv) * Cfu * Ci * Cd * Clambda, then the member resistances apply stability/bearing factors. Units: ksi, inch.

Table-lookup factors that depend on species/grade (CM wet service, Cfu flat use, Cd deck factor) are inputs rather than functions — take them from the design tables for the material at hand.

civilpy.structural.aashto.lrfd.timber.beam_stability_cl(f_b_star: float, e_adj: float, l_e: float, d: float, b: float, grading: str = 'visual') CheckResult[source]

Beam stability factor (8.6.2-2): CL = (1+A)/1.9 - sqrt((1+A)^2/3.61 - A/0.95), with A = FbE/Fb*, FbE = KbE*E’/RB^2 and slenderness RB = sqrt(Le*d/b^2) <= 50.

f_b_star is the adjusted bending strength with all factors except CL and Cv (ksi); e_adj the adjusted modulus (ksi); l_e the effective unbraced length (in). capacity holds CL.

civilpy.structural.aashto.lrfd.timber.bearing_factor_cb(l_b: float, near_end: bool = False) float[source]

Cb (8.8.3): (lb + 0.375)/lb for bearings less than 6 in long and at least 3 in from the member end; 1.0 otherwise (near_end or long bearings). l_b is the bearing length (in).

civilpy.structural.aashto.lrfd.timber.column_stability_cp(f_co_adj: float, e_adj: float, l_e: float, d: float, c: float = 0.8, k_ce: float = 0.76) CheckResult[source]

Column stability factor for wood compression members (8.7): Cp = (1+B)/(2c) - sqrt(((1+B)/(2c))^2 - B/c), with B = FcE/Fco’ and FcE = KcE*E’/(Le/d)^2.

f_co_adj is the adjusted compression strength with all factors except Cp (ksi); c = 0.8 sawn lumber, 0.85 round poles, 0.9 glulam; the Euler coefficient k_ce defaults to the visually graded value. Slenderness Le/d may not exceed 50. capacity holds Cp.

civilpy.structural.aashto.lrfd.timber.deck_factor_cd(deck_type: str, thickness_nominal: float = 4.0) float[source]

Deck factor on Fbo (Table 8.4.4.8-1): 1.15 for stressed-wood, spike-laminated, and nail-laminated decks built from 2- to 4-in (nominal) thick lumber; 1.0 for plank decks and everything else.

civilpy.structural.aashto.lrfd.timber.flat_use_cfu(width_nominal: float, thickness_nominal: float = 2.0, glulam: bool = False) float[source]

Flat-use factor for bending about the weak axis (8.4.4.6).

Sawn dimension lumber uses Table 8.4.4.6-1 (nominal dimensions, widths above 10 in take the 10-in row). Glulam loaded parallel to the wide laminations uses (12/d)^(1/9) with d the actual dimension parallel to the wide face (in), 1.0 at 12 in and wider.

civilpy.structural.aashto.lrfd.timber.format_conversion_ckf(phi: float, bearing: bool = False) float[source]

CKF (8.4.4.2): converts allowable-stress reference values to the LRFD format — 2.5/phi generally, 2.1/phi for compression perpendicular to grain (bearing).

civilpy.structural.aashto.lrfd.timber.incising_factor_ci(modulus: bool = False) float[source]

Ci for incised, preservative-treated dimension lumber (8.4.4.7): 0.80 on strength values, 0.95 on modulus of elasticity.

civilpy.structural.aashto.lrfd.timber.size_factor_cf(d: float) float[source]

CF for sawn beams and stringers deeper than 12 in (8.4.4.4): (12/d)^(1/9), 1.0 otherwise.

civilpy.structural.aashto.lrfd.timber.timber_compression_resistance(f_c_adj: float, a_g: float, c_p: float = 1.0, p_u: float | None = None) CheckResult[source]

Compression parallel to grain (8.7): Pn = Fc_adj * Ag * Cp, Pr = phi * Pn with phi = 0.90.

f_c_adj is the adjusted compression strength (ksi) without Cp; pass the column stability factor from column_stability_cp() (1.0 for fully braced members).

civilpy.structural.aashto.lrfd.timber.timber_flexural_resistance(f_b_adj: float, s_x: float, c_l: float = 1.0, m_u: float | None = None) CheckResult[source]

Flexural resistance of a wood beam (8.6): Mn = Fb_adj * Sx * CL, Mr = phi_f * Mn with phi_f = 0.85.

f_b_adj is the fully adjusted bending strength (ksi, including CKF/CM/CF/Clambda etc.), s_x the section modulus (in^3).

civilpy.structural.aashto.lrfd.timber.timber_tension_resistance(f_t_adj: float, a_n: float, p_u: float | None = None) CheckResult[source]

Tension parallel to grain (8.8.2): Pn = Ft_adj * An on the net section, Pr = phi * Pn with phi = 0.80.

f_t_adj is the adjusted tension strength (ksi, including CKF/CM/CF/Ci/Clambda), a_n the net area (in^2).

civilpy.structural.aashto.lrfd.timber.time_effect_clambda(limit_state: str = 'Strength I') float[source]

Clambda (Table 8.4.4.9-1) by limit state.

civilpy.structural.aashto.lrfd.timber.volume_factor_cv(d: float, b: float, l_ft: float, southern_pine: bool = False) float[source]

Cv for glued-laminated timber in flexure (8.4.4.5): [(12/d)*(5.125/b)*(21/L)]^a <= 1.0, a = 0.05 for Southern Pine and 0.10 for all other species. d/b in inches, l_ft in ft. Cv and CL are not applied simultaneously — use the smaller.

civilpy.structural.aashto.lrfd.timber.wet_service_cm(prop: str, glulam: bool = False, wet: bool = True, f_o_cf: float | None = None) float[source]

Wet service factor CM (8.4.4.3) for a reference design value: prop is one of flexure / tension / shear / bearing / compression / modulus. Dry use (sawn lumber <= 19% moisture, glulam < 16%) returns 1.0.

For sawn lumber pass f_o_cf = Fbo*CF (flexure) or Fco*CF (compression) in ksi to apply the table footnotes that waive the reduction for low reference values.

Module contents

AASHTO LRFD Bridge Design Specifications — independent design checks.

Each check is a pure function of primitive inputs (kip, inch, ksi) so members can be “designed” by looping candidate sizes through the checks without any external software. Article numbering follows the current specification, so results can be compared check-for-check against commercial rating software or hand calculations.

>>> from civilpy.structural.aashto import lrfd
>>> lrfd.ARTICLES["6.10.8.2.2"]
<function flange_local_buckling_resistance at ...>
class civilpy.structural.aashto.lrfd.BoltSpec(bolt_type: 'str' = 'A325', diameter: 'float' = 0.875, flange_threads_excluded: 'bool' = True, web_threads_excluded: 'bool' = False, surface_class: 'str' = 'B', hole_type: 'str' = 'standard')[source]

Bases: object

bolt_type: str = 'A325'
diameter: float = 0.875
flange_threads_excluded: bool = True
hole_type: str = 'standard'
surface_class: str = 'B'
web_threads_excluded: bool = False
class civilpy.structural.aashto.lrfd.CheckResult(article: str, name: str, capacity: float, demand: float | None = None, phi: float = 1.0, details: dict = <factory>)[source]

Bases: object

Outcome of a single spec-article check.

capacity and demand are in the article’s governing unit (stress, moment, or force); details carries the intermediate values an engineer would show in hand calcs, keyed by the symbol used in the spec.

article: str
capacity: float
demand: float | None = None
details: dict
property factored_capacity: float
name: str
property ok: bool | None
phi: float = 1.0
property ratio: float | None

Capacity/demand ratio (>= 1.0 passes); None when no demand given.

class civilpy.structural.aashto.lrfd.ComponentDesign(name: 'str', bolt_rows: 'int', total_bolts: 'int', strength_bolts: 'int', slip_bolts: 'int', controlling_bolts: 'int', design_force: 'float', gage_bolts: 'float' = 0.0, gage_groups: 'float' = 0.0, pitch: 'float' = 0.0, pitch_groups: 'float' = 0.0, edge: 'float' = 0.0, end: 'float' = 0.0, plate_thickness: 'float' = 0.0, plate_width: 'float' = 0.0, plate_length: 'float' = 0.0, long_joint: 'bool' = False, checks: 'list[CheckResult]' = <factory>, extra: 'dict' = <factory>)[source]

Bases: object

bolt_rows: int
checks: list[CheckResult]
controlling_bolts: int
design_force: float
edge: float = 0.0
end: float = 0.0
extra: dict
gage_bolts: float = 0.0
gage_groups: float = 0.0
long_joint: bool = False
name: str
property ok: bool
pitch: float = 0.0
pitch_groups: float = 0.0
plate_length: float = 0.0
plate_thickness: float = 0.0
plate_width: float = 0.0
slip_bolts: int
strength_bolts: int
total_bolts: int
class civilpy.structural.aashto.lrfd.CompositeGirder(side: GirderSide, *, deck_t: float, deck_weff: float, deck_fc: float = 4.0, n: float | None = None, rebar_area: float = 0.0, rebar_cover: float = 2.5, hole_area_per_flange: float = 0.0)[source]

Bases: object

Transformed-section model of one girder side + its composite deck.

Rectangular idealization of the steel (two flanges + web); the deck is a deck_weff x deck_t slab whose bottom sits a haunch above the top of the top flange. Optional longitudinal reinforcement rebar_area sits rebar_cover below the top of the slab (for the cracked negative section).

flange_fcf(flange: str, loads: SpliceLoads, *, holes: bool = False) float[source]

Governing factored flange stress fcf (ksi, magnitude) for the Strength I positive and negative cases, from the unfactored SpliceLoads. The permanent-load factor gamma_p takes its maximum or minimum to maximize the stress in the checked direction (AASHTO 3.4.1, Table 3.4.1-2), matching _factor_loads.

flange_stress(flange: str, moments: dict, *, holes: bool = False) float[source]

Factored flange stress fcf (ksi) at the given flange ("top"/"bottom") mid-thickness, summing each load case on its own section: DC1 on bare steel, DC2/DW on the long-term (3n) composite, and live load on the short-term (n) composite (or the cracked negative section for the negative live-load case).

moments supplies factored case moments (k-ft): dc1, dc2, dw, and one of ll_pos / ll_neg. Tension is positive.

props(state: str, *, holes: bool = False) SectionProps[source]

Transformed properties for state in {"steel", "n", "3n", "negative"}. "steel" is the bare girder; "n"/"3n" add the deck transformed by 1/n and 1/(3n) (positive moment); "negative" is the cracked section (steel + rebar).

property y_bottom_flange: float
property y_top_flange: float
class civilpy.structural.aashto.lrfd.DistributionFactor(one_lane: float, multi_lane: float, applicability: dict = <factory>)[source]

Bases: object

A distribution factor (lanes/girder) with its applicability flags.

applicability: dict
property applicable: bool
property governing: float
multi_lane: float
one_lane: float
class civilpy.structural.aashto.lrfd.Flange(material: str, thickness: float, width: float)[source]

Bases: object

One flange of one girder side.

property area: float
material: str
thickness: float
width: float
class civilpy.structural.aashto.lrfd.FlangeSplicePlates(outer_width: float, outer_thickness: float, inner_width: float, inner_width_exact: float, inner_thickness: float, inner_thickness_band: tuple[float, float], clearance: float, min_thickness: float)[source]

Bases: object

Proportioned flange splice plates (C6.13.6.1.3b and the AASHTO/NSBA “develop the flange” guidance). A single outer plate spans the full flange width; a pair of inner plates straddle the web, separated by the clearance gap needed for the web and its fillet welds. Widths and thicknesses in inches.

inner_thickness is the ideal thickness that makes the two inner plates equal in area to the outer plate; inner_thickness_band is the (low, high) range that keeps the inner/outer areas within 10% so the connection may be proportioned for the full flange force in double shear (C6.13.6.1.3b). Pick any standard plate inside the band.

clearance: float
inner_thickness: float
inner_thickness_band: tuple[float, float]
inner_width: float
inner_width_exact: float
min_thickness: float
outer_thickness: float
outer_width: float
class civilpy.structural.aashto.lrfd.GirderSide(top_flange: Flange, bottom_flange: Flange, web_material: str, web_thickness: float, web_depth: float, haunch: float = 0.0, stiffener_spacing_ft: float | None = None, stiffened: bool = True)[source]

Bases: object

The plate-girder cross section on one side of the splice.

bottom_flange: Flange
haunch: float = 0.0
stiffened: bool = True
stiffener_spacing_ft: float | None = None
top_flange: Flange
web_depth: float
web_material: str
web_thickness: float
class civilpy.structural.aashto.lrfd.MCFTParams(beta: float, theta_deg: float, eps_s: float, s_xe: float | None = None)[source]

Bases: object

beta/theta from the 5.7.3.4.2 general procedure, ready to feed rc_shear_resistance().

beta: float
eps_s: float
s_xe: float | None = None
theta_deg: float
class civilpy.structural.aashto.lrfd.PMPoint(p_n: float, m_n: float, eps_t: float, phi: float, c: float)[source]

Bases: object

One point on the nominal interaction diagram.

c: float
eps_t: float
m_n: float
p_n: float
phi: float
property phi_mn: float
property phi_pn: float
class civilpy.structural.aashto.lrfd.PlatePair(material: str, inner_thickness: float, inner_width: float, outer_thickness: float, outer_width: float, shear_planes: int = 2)[source]

Bases: object

Inner + outer splice plates for a flange (user-selected, then checked).

property inner_area: float
inner_thickness: float
inner_width: float
material: str
property outer_area: float
outer_thickness: float
outer_width: float
shear_planes: int = 2
class civilpy.structural.aashto.lrfd.RebarLayer(area: float, depth: float)[source]

Bases: object

One layer of longitudinal bars: total area (in^2) at depth from the extreme compression fiber (in).

area: float
depth: float
class civilpy.structural.aashto.lrfd.SectionProps(area: float, inertia: float, y_na: float)[source]

Bases: object

Transformed-section properties about the elastic neutral axis.

area and inertia are transformed (steel) values; y_na is the neutral-axis height above the bottom of the bottom flange (in).

area: float
inertia: float
stress(moment_kft: float, y_fiber: float) float[source]

Bending stress (ksi) at height y_fiber for moment_kft (k-ft), tension positive at fibers below the neutral axis for a positive (sagging) moment. sigma = M*c/I with c = y_na - y_fiber.

y_na: float
class civilpy.structural.aashto.lrfd.SpacingLimits(min_spacing: float, max_spacing_seal: float, min_edge: float, max_edge: float, pitch_ok: bool | None, gage_ok: bool | None, edge_ok: bool | None, end_ok: bool | None)[source]

Bases: object

Result of the 6.13.2.6 layout limit checks. Each *_ok flag is True when the corresponding provided dimension is within the spec limit; the limit values are exposed for reporting.

edge_ok: bool | None
end_ok: bool | None
gage_ok: bool | None
max_edge: float
max_spacing_seal: float
min_edge: float
min_spacing: float
pitch_ok: bool | None
class civilpy.structural.aashto.lrfd.SpliceDesign(factored_moments: 'dict', factored_shears: 'dict', top_flange: 'ComponentDesign', bottom_flange: 'ComponentDesign', web: 'ComponentDesign', spec: 'SpliceInput | None' = None)[source]

Bases: object

bottom_flange: ComponentDesign
property checks: list[CheckResult]
property components: list[ComponentDesign]
factored_moments: dict
factored_shears: dict
property ok: bool
spec: SpliceInput | None = None
top_flange: ComponentDesign
web: ComponentDesign
class civilpy.structural.aashto.lrfd.SpliceInput(left: 'GirderSide', right: 'GirderSide', loads: 'SpliceLoads', bolts: 'BoltSpec', top_plates: 'PlatePair', bottom_plates: 'PlatePair', web_plate: 'WebPlate', deck_composite: 'bool' = True, deck_thickness: 'float' = 0.0, deck_eff_width: 'float' = 0.0, fc: 'float' = 4.0, top_flange_rows: 'int' = 4, bottom_flange_rows: 'int' = 4, web_rows: 'int' = 2, bolt_spacing: 'float' = 3.0, flange_edge: 'float' = 2.0, flange_end: 'float' = 1.5, web_edge: 'float' = 2.0, web_end: 'float' = 1.5, web_weld_size: 'float' = 0.3125, web_weld_clearance: 'float' = 0.375, girder_gap: 'float' = 0.75, entering_tightening: 'float' = 3.0, design_year: 'int' = 2020, method: 'str' = 'nsba', fcf_top: 'float | None' = None, fcf_bot: 'float | None' = None, r_h: 'float' = 1.0, alpha: 'float' = 1.0)[source]

Bases: object

alpha: float = 1.0
bolt_spacing: float = 3.0
bolts: BoltSpec
bottom_flange_rows: int = 4
bottom_plates: PlatePair
deck_composite: bool = True
deck_eff_width: float = 0.0
deck_thickness: float = 0.0
design_year: int = 2020
entering_tightening: float = 3.0
fc: float = 4.0
fcf_bot: float | None = None
fcf_top: float | None = None
flange_edge: float = 2.0
flange_end: float = 1.5
girder_gap: float = 0.75
left: GirderSide
loads: SpliceLoads
method: str = 'nsba'
r_h: float = 1.0
right: GirderSide
top_flange_rows: int = 4
top_plates: PlatePair
web_edge: float = 2.0
web_end: float = 1.5
web_plate: WebPlate
web_rows: int = 2
web_weld_clearance: float = 0.375
web_weld_size: float = 0.3125
class civilpy.structural.aashto.lrfd.SpliceLoads(dc1_m: float = 0.0, dc1_v: float = 0.0, dc2_m: float = 0.0, dc2_v: float = 0.0, dw_m: float = 0.0, dw_v: float = 0.0, ll_pos_m: float = 0.0, ll_pos_v: float = 0.0, ll_neg_m: float = 0.0, ll_neg_v: float = 0.0, deck_cast_m: float = 0.0, deck_cast_v: float = 0.0)[source]

Bases: object

Unfactored moment (kip-ft) and shear (kip) at the splice centerline.

dc1_m: float = 0.0
dc1_v: float = 0.0
dc2_m: float = 0.0
dc2_v: float = 0.0
deck_cast_m: float = 0.0
deck_cast_v: float = 0.0
dw_m: float = 0.0
dw_v: float = 0.0
ll_neg_m: float = 0.0
ll_neg_v: float = 0.0
ll_pos_m: float = 0.0
ll_pos_v: float = 0.0
class civilpy.structural.aashto.lrfd.SplicePlateForces(outer: float, inner: float, double_shear: bool, ratio_outer: float)[source]

Bases: object

How the flange design force Pfy is apportioned to the inner and outer splice plates (C6.13.6.1.3b). double_shear is True when the inner and outer plate areas are within 10% and the force is shared equally (each plate group works in double shear at Pfy/2); otherwise each plate carries the fraction of Pfy proportional to its area.

double_shear: bool
inner: float
outer: float
ratio_outer: float
class civilpy.structural.aashto.lrfd.TestLevelLoad(f_t: float, f_l: float, f_v: float, l_t: float, l_v: float, h_e_min: float, h_min: float)[source]

Bases: object

Design forces for one crash test level (Table A13.2-1).

f_t/f_l/f_v are the transverse, longitudinal, and vertical (down) forces in kip; l_t (= l_l) and l_v their distribution lengths in ft; h_e_min the minimum effective height and h_min the minimum rail height, both in inches.

f_l: float
f_t: float
f_v: float
h_e_min: float
h_min: float
l_t: float
l_v: float
class civilpy.structural.aashto.lrfd.WebPlate(material: 'str', thickness: 'float', shear_planes: 'int' = 2)[source]

Bases: object

material: str
shear_planes: int = 2
thickness: float
class civilpy.structural.aashto.lrfd.WebSpliceForces(v_uw: float, h_w: float, per_bolt: float, n_bolts: int)[source]

Bases: object

Design forces for a web splice (6.13.6.1.3c): the vertical design shear Vuw, the horizontal force Hw from the moment not carried by the flanges, and the resultant per-bolt force to compare against the bolt shear/slip resistance.

h_w: float
n_bolts: int
per_bolt: float
v_uw: float
class civilpy.structural.aashto.lrfd.WebSplicePlates(thickness: float, min_thickness: float, height: float, max_pitch_seal: float, min_bolts_per_row: int, filler_required: bool)[source]

Bases: object

Proportioned web splice plates (6.13.6.1.3c; 6.13.2.6.2). A pair of plates covers each face of the web over nearly the full depth. height is the plate depth (near-full web depth); max_pitch_seal is the maximum bolt spacing for sealing (6.13.2.6.2) and min_bolts_per_row the resulting minimum number of bolts in a vertical line. Inches.

filler_required: bool
height: float
max_pitch_seal: float
min_bolts_per_row: int
min_thickness: float
thickness: float
civilpy.structural.aashto.lrfd.a6_flange_local_buckling(b_fc: float, t_fc: float, d_web: float, t_w: float, f_yc: float, f_yw: float, f_yt: float, s_xc: float, s_xt: float, r_pc: float, m_yc: float, m_u: float | None = None, r_h: float = 1.0) CheckResult[source]

Compression-flange local buckling resistance Mnc in moment format (A6.3.2): the plateau Rpc*Myc for compact flanges, interpolated toward Fyr*Sxc using kc = 4/sqrt(D/tw) (0.35 <= kc <= 0.76) for noncompact.

civilpy.structural.aashto.lrfd.a6_lateral_torsional_buckling(l_b: float, r_t: float, j_torsion: float, h_depth: float, f_yc: float, f_yw: float, f_yt: float, s_xc: float, s_xt: float, r_pc: float, m_yc: float, c_b: float = 1.0, m_u: float | None = None, r_h: float = 1.0) CheckResult[source]

Lateral torsional buckling resistance Mnc in moment format (A6.3.3), which credits the St. Venant stiffness J that 6.10.8.2.3 neglects.

r_t is the effective radius of gyration (in), j_torsion from st_venant_j(), h_depth the distance between flange centroids (in).

civilpy.structural.aashto.lrfd.a6_tension_flange_yielding(r_pt: float, m_yt: float, m_u: float | None = None) CheckResult[source]

Tension-flange yielding resistance (A6.4-1): Mnt = Rpt*Myt.

civilpy.structural.aashto.lrfd.article(number: str, name: str)[source]

Register a check function under its LRFD article number.

civilpy.structural.aashto.lrfd.beam_stability_cl(f_b_star: float, e_adj: float, l_e: float, d: float, b: float, grading: str = 'visual') CheckResult[source]

Beam stability factor (8.6.2-2): CL = (1+A)/1.9 - sqrt((1+A)^2/3.61 - A/0.95), with A = FbE/Fb*, FbE = KbE*E’/RB^2 and slenderness RB = sqrt(Le*d/b^2) <= 50.

f_b_star is the adjusted bending strength with all factors except CL and Cv (ksi); e_adj the adjusted modulus (ksi); l_e the effective unbraced length (in). capacity holds CL.

civilpy.structural.aashto.lrfd.bearing_factor_cb(l_b: float, near_end: bool = False) float[source]

Cb (8.8.3): (lb + 0.375)/lb for bearings less than 6 in long and at least 3 in from the member end; 1.0 otherwise (near_end or long bearings). l_b is the bearing length (in).

civilpy.structural.aashto.lrfd.bearing_stiffener_effective_column(b_t: float, t_p: float, t_w: float, d_web: float, f_ys: float, pairs: int = 1, p_u: float | None = None, design_year: int | None = None) CheckResult[source]

Axial resistance of the bearing-stiffener effective column (6.10.11.2.4): the stiffener plates acting with a web strip extending 9*tw to each side, radius of gyration about the web mid-thickness, KL = 0.75*D, resistance per 6.9.4.1.1 (Q = 1.0 — bearing stiffeners are exempt from the slender-element reduction).

civilpy.structural.aashto.lrfd.bearing_stiffener_resistance(a_pn: float, f_ys: float, r_u: float | None = None) CheckResult[source]

Bearing resistance of fitted bearing-stiffener ends (6.10.11.2.3-1): Rn = 1.4*Apn*Fys with phi_b = 1.0.

a_pn is the stiffener area in contact with the flange after the clip for the web-to-flange weld (in^2). The companion axial check of the stiffener-plus-web effective column (6.10.11.2.4) composes with compression_member_resistance() using KL = 0.75*D and the effective-section properties.

civilpy.structural.aashto.lrfd.bearing_stiffener_width(b_t: float, t_p: float, f_ys: float) CheckResult[source]

Bearing-stiffener projecting-width limit (6.10.11.2.2-1): b_t <= 0.48 * t_p * sqrt(E/Fys).

civilpy.structural.aashto.lrfd.block_shear_resistance(a_vg: float, a_vn: float, a_tn: float, f_y: float, f_u: float, p_u: float | None = None, u_bs: float = 1.0, punched_holes: bool = False) CheckResult[source]

Block shear rupture (6.13.4-1): Rn = Rp*(0.58*Fu*Avn + Ubs*Fu*Atn), not to exceed Rp*(0.58*Fy*Avg + Ubs*Fu*Atn); phi_bs = 0.80.

u_bs = 1.0 for uniform tension stress, 0.5 for nonuniform; Rp = 0.9 for punched holes, 1.0 drilled.

civilpy.structural.aashto.lrfd.bolt_bearing_resistance(d_bolt: float, t_ply: float, f_u_ply: float, clear_distance: float, v_u: float | None = None) CheckResult[source]

Bearing on connected material at a bolt hole (6.13.2.9): Rn = 2.4*d*t*Fu when the clear distance to the next hole or end is at least 2.0*d, else Rn = 1.2*Lc*t*Fu. phi_bb = 0.80.

civilpy.structural.aashto.lrfd.bolt_shear_resistance(d_bolt: float, f_ub: float, n_planes: int = 1, threads_excluded: bool = True, v_u: float | None = None, long_joint: bool = False, design_year: int | None = None) CheckResult[source]

Shear resistance of a high-strength bolt (6.13.2.7): Rn = C*Ab*Fub*Ns; joints longer than 38 in between extreme bolts take a 0.83 reduction. phi_s = 0.80.

The shear-strength coefficient C was raised in the 8th Edition (2017): design_year >= 2017 uses C = 0.56 (threads excluded) / 0.45 (threads included); earlier editions (the default) use 0.48 / 0.38.

civilpy.structural.aashto.lrfd.bolt_slip_resistance(bolt_grade: str, d_bolt: float, n_planes: int = 1, hole_type: str = 'standard', surface_class: str = 'B', v_serv: float | None = None) CheckResult[source]

Slip resistance of one bolt in a slip-critical connection (6.13.2.8-1): Rn = Kh*Ks*Ns*Pt, checked under Service II (phi = 1.0). Pretension Pt from Table 6.13.2.8-2.

civilpy.structural.aashto.lrfd.bolt_spacing_limits(d_bolt: float, plate_t: float, pitch: float | None = None, gage: float | None = None, edge_dist: float | None = None, end_dist: float | None = None, sheared_edge: bool = False) SpacingLimits[source]

Geometric layout limits for a bolt group (6.13.2.6):

  • minimum spacing (pitch and gage) = 3.0*d (6.13.2.6.1);

  • maximum spacing for sealing = min(4.0 + 4.0*t, 7.0) in (6.13.2.6.2);

  • minimum edge/end distance from Table 6.13.2.6.6-1;

  • maximum edge distance = min(8.0*t, 5.0) in (6.13.2.6.6).

Any provided dimension is checked against its limit and the boolean flag set accordingly; None dimensions leave the flag None.

civilpy.structural.aashto.lrfd.column_stability_cp(f_co_adj: float, e_adj: float, l_e: float, d: float, c: float = 0.8, k_ce: float = 0.76) CheckResult[source]

Column stability factor for wood compression members (8.7): Cp = (1+B)/(2c) - sqrt(((1+B)/(2c))^2 - B/c), with B = FcE/Fco’ and FcE = KcE*E’/(Le/d)^2.

f_co_adj is the adjusted compression strength with all factors except Cp (ksi); c = 0.8 sawn lumber, 0.85 round poles, 0.9 glulam; the Euler coefficient k_ce defaults to the visually graded value. Slenderness Le/d may not exceed 50. capacity holds Cp.

civilpy.structural.aashto.lrfd.compact_composite_positive_flexure(m_p: float, d_p: float, d_t: float, m_u: float | None = None, m_y: float | None = None, r_h: float = 1.0, continuous_span: bool = False) CheckResult[source]

Nominal flexural resistance of a compact composite section in positive flexure (6.10.7.1.2): Mn = Mp when Dp <= 0.1*Dt, else the penalty Mn = Mp*(1.07 - 0.7*Dp/Dt); continuous spans not meeting the B6 conditions cap Mn at 1.3*Rh*My.

m_p is the plastic moment (kip-in, from a D6.1 PNA analysis), d_p the depth from the top of slab to the PNA, d_t the total composite depth. The 6.10.7.3 ductility limit Dp <= 0.42*Dt is reported in details.

civilpy.structural.aashto.lrfd.compression_flange_resistance(l_b: float, b_fc: float, t_fc: float, d_c: float, t_w: float, f_yc: float, f_yw: float, c_b: float = 1.0, f_bu: float | None = None, r_b: float = 1.0, r_h: float = 1.0) CheckResult[source]

Compression-flange flexural resistance Fnc (6.10.8.2.1-1): the smaller of local buckling (6.10.8.2.2) and lateral-torsional buckling (6.10.8.2.3).

civilpy.structural.aashto.lrfd.compression_member_resistance(a_g: float, f_y: float, kl_over_r: float, p_u: float | None = None, q_slender: float = 1.0, design_year: int | None = None) CheckResult[source]

Axial compressive resistance of a non-slender-element column (6.9.4.1.1): Pe = pi^2*E/(KL/r)^2 * Ag; Po = Q*Fy*Ag; Pn = 0.658^(Po/Pe)*Po when Pe >= 0.44*Po, else 0.877*Pe.

q_slender is the slender-element reduction (6.9.4.2; 1.0 for nonslender plates). phi_c is 0.95 (0.90 for designs before the 2015 interim — pass design_year).

civilpy.structural.aashto.lrfd.connection_element_shear(a_vg: float, f_y: float, a_vn: float | None = None, f_u: float | None = None, v_u: float | None = None) CheckResult[source]

Shear resistance of a connection element — splice/gusset plate (6.13.5.3): gross-section yielding Rr = phi_v*0.58*Fy*Avg (phi = 1.0); net-section rupture Rr = phi_vu*0.58*Fu*Avn (phi = 0.80) when the net path is given. The governing factored resistance is reported.

civilpy.structural.aashto.lrfd.constructibility_compression_flange(f_bu: float, f_l: float, f_yc: float, f_nc: float, f_crw: float | None = None, r_h: float = 1.0, slender_web: bool = False) CheckResult[source]

Constructibility checks on a discretely braced compression flange during deck placement (6.10.3.2.1): flange yielding fbu + fl <= phi*Rh*Fyc (skipped for slender webs), flange buckling fbu + fl/3 <= phi*Fnc, and web bend-buckling fbu <= phi*Fcrw.

f_bu/f_l are the factored vertical-bending and lateral-bending flange stresses under the steel-plus-wet-concrete condition; f_nc from the 6.10.8.2 functions and f_crw from web_bend_buckling(). capacity/demand carry the governing case; all three appear in details.

civilpy.structural.aashto.lrfd.continuously_braced_flange(f_yf: float, f_bu: float | None = None, r_h: float = 1.0) CheckResult[source]

Continuously braced flange in tension or compression (6.10.8.1.3-1): f_bu <= phi_f * Rh * Fyf (no lateral-bending term — the deck braces the flange continuously).

civilpy.structural.aashto.lrfd.creep_coefficient(t: float, t_i: float, f_ci: float, humidity_pct: float = 70.0, v_s: float = 3.5, design_year: int | None = None) float[source]

Creep coefficient psi(t, ti) (5.4.2.3.2-1): 1.9 * ks * khc * kf * ktd * ti^-0.118.

t is concrete age at the time of interest (days), t_i age at loading. Returns a plain float since this is a material model, not a pass/fail check.

civilpy.structural.aashto.lrfd.deck_dead_load_moment(w_ksf: float, s_ft: float, coefficient: float = 10.0) float[source]

Approximate dead-load moment (kip-ft/ft) of the continuous transverse strip: w*S^2/c with the customary c = 10 used for deck strips continuous over three or more supports (used for both the positive and negative regions). Pass coefficient=8.0 for a simple-span strip. For staged decks or unusual framing, analyze the strip explicitly (e.g. civilpy.structural.continuous_beam) instead.

civilpy.structural.aashto.lrfd.deck_equivalent_strip(case: str, s_ft: float) float[source]

Transverse equivalent strip width (in) for a cast-in-place concrete deck (Table 4.6.2.1.3-1).

case is "positive" / "negative" with s_ft the girder spacing S (ft), or "overhang" with s_ft the distance X (ft) from the wheel load to the point of support.

civilpy.structural.aashto.lrfd.deck_ll_negative_moment(s_ft: float, design_section_in: float) float[source]

Maximum HL-93 negative live-load moment (kip-ft/ft) from Table A4-1 at a design section design_section_in inches from the girder centerline (LRFD 4.6.2.1.6), interpolating in both span and offset. Offsets beyond the tabulated 24 in use the 24 in column (conservative).

civilpy.structural.aashto.lrfd.deck_ll_positive_moment(s_ft: float) float[source]

Maximum HL-93 positive live-load moment (kip-ft/ft, IM and multiple presence included) from Table A4-1, interpolating between tabulated girder spacings.

civilpy.structural.aashto.lrfd.deck_overhang_collision_tension(r_w: float, l_c: float, h: float) CheckResult[source]

Axial tensile force per unit length transmitted to the deck overhang when the parapet reaches its yield-line resistance (A13.4.2 Design Case 1): T = Rw/(Lc + 2H), spread over the distribution length at the deck level.

capacity holds T (kip/ft when Rw is kip and Lc/H are ft); the deck overhang reinforcement must then resist T concurrent with the overhang moment.

civilpy.structural.aashto.lrfd.deck_strip_checks(*, bar_size: int, spacing_in: float, t_structural: float, cover_in: float, m_dc: float, m_dw: float, m_ll: float, f_c: float = 4.5, f_y: float = 60.0, exposure_class_2: bool = True) list[CheckResult][source]

Run the LRFD Section 5 check chain for one face of a deck strip.

Moments are unfactored magnitudes in kip-ft/ft for the face being checked (positive moments for the bottom mat, negative for the top); Strength I and Service I factoring happens here. t_structural is the structural deck thickness (in) — for ODOT decks the total thickness minus the monolithic wearing surface — and cover_in the clear cover on the tension face. Returns the 5.6.3.2 flexure, 5.6.3.3 minimum reinforcement, and 5.6.7 crack control results in that order.

civilpy.structural.aashto.lrfd.deflection_limit(span: float, deflection: float | None = None, pedestrian: bool = False, cantilever: bool = False) CheckResult[source]

Optional live-load deflection limits (2.5.2.6.2): span/800 (vehicular), span/1000 (with pedestrian use); cantilevers span/300 and span/375 respectively. Same length unit in and out.

civilpy.structural.aashto.lrfd.design_rolled_splice(left_label: str, right_label: str, loads: SpliceLoads, *, grade: str = 'Grade 50', deck_thickness: float, deck_eff_width: float, deck_fc: float = 4.0, haunch: float = 2.0, rebar_area: float = 0.0, n: float | None = None, **splice_kwargs)[source]

End-to-end rolled-shape composite field-splice design (G7 + B4).

Builds both GirderSides from AISC labels, computes the composite flange design stresses fcf from the deck section (so no MDX-supplied stress is needed), and runs design_splice() with method="odot_bdm". Extra design_splice inputs (bolts, top_plates/bottom_plates, web_plate, *_rows, spacing, design_year …) pass through splice_kwargs.

civilpy.structural.aashto.lrfd.design_splice(inp: SpliceInput) SpliceDesign[source]

Design a bolted field splice: size bolts, lay out the pattern, and run the AASHTO limit-state checks for both flanges and the web.

civilpy.structural.aashto.lrfd.discretely_braced_compression_flange(f_nc: float, f_bu: float, f_l: float = 0.0, f_yf: float | None = None) CheckResult[source]

Discretely braced compression-flange check (6.10.8.1.1-1): f_bu + f_l/3 <= phi_f * Fnc, with f_nc from 6.10.8.2.1 and f_l the flange lateral bending stress. When f_yf is given the 6.10.1.6 limit f_l <= 0.6*Fyf is also verified (reported in details).

civilpy.structural.aashto.lrfd.dynamic_load_allowance(component: str = 'general', fatigue: bool = False) float[source]

IM (Table 3.6.2.1-1) as a multiplier on the truck portion of live load: 1.33 generally, 1.15 for fatigue, 1.75 for deck joints.

civilpy.structural.aashto.lrfd.effective_flange_width(s_ft: float, span_ft: float | None = None, t_s: float | None = None, t_w: float | None = None, b_f: float | None = None, design_year: int | None = None) float[source]

Effective deck width acting with an interior girder (4.6.2.6.1), in inches.

Since the 2008 interim revisions this is simply the girder spacing. Earlier designs used the lesser of L/4, 12*ts + max(tw, bf/2), and S — pass design_year (with span_ft, t_s, t_w, b_f) for those.

civilpy.structural.aashto.lrfd.factor_time_development(t: float, f_ci: float, design_year: int | None = None) float[source]

ktd, time-development factor (5.4.2.3.2-5).

Current (2015 interim onward): t / (12*(100 - 4*f’ci)/(f’ci + 20) + t). 2007-2014 designs used t / (61 - 4*f’ci + t). t is the maturity of the concrete in days from loading (creep) or end of curing (shrinkage).

civilpy.structural.aashto.lrfd.fatigue_resistance(category: str, delta_f: float | None = None, fatigue_i: bool = True, adtt_sl: float = 1000.0, n_cycles_per_truck: float = 1.0, design_life_years: float = 75.0) CheckResult[source]

Nominal fatigue resistance (6.6.1.2.5): Fatigue I (infinite life) uses the constant-amplitude threshold (delta_F)TH; Fatigue II (finite life) uses (A/N)^(1/3) with N = 365 * years * n * ADTT_SL.

category is the Table 6.6.1.2.3-1 detail category (A through E’); delta_f the live-load stress range demand (ksi).

civilpy.structural.aashto.lrfd.filler_plate_reduction(a_f: float, a_p: float, total_filler_thickness: float = 1.0) CheckResult[source]

Bolt shear-resistance reduction for fillers (6.13.6.1.4). When the total thickness of the fillers is 0.25 in or greater, the factored bolt shear resistance is multiplied by R = (1 + gamma)/(1 + 2*gamma), with gamma = Af/Ap; Af is the sum of the filler areas and Ap is the smaller of the connected-plate area or the sum of the splice-plate areas. Below 0.25 in of filler, R = 1.0. capacity holds R.

civilpy.structural.aashto.lrfd.fillet_weld_resistance(leg_size: float, f_exx: float = 70.0, length: float = 1.0, v_u: float | None = None) CheckResult[source]

Factored shear resistance of a fillet weld on its effective throat (6.13.3.2.4b): Rr = 0.6*phi_e2*Fexx with phi_e2 = 0.80, applied to the throat 0.707*leg. capacity holds the factored resistance for the given length of weld (kip), so phi is 1.0 on the result.

civilpy.structural.aashto.lrfd.flange_local_buckling_resistance(b_fc: float, t_fc: float, f_yc: float, f_yw: float, f_bu: float | None = None, r_b: float = 1.0, r_h: float = 1.0) CheckResult[source]

Compression-flange local buckling resistance Fnc (6.10.8.2.2).

Parameters: flange width b_fc and thickness t_fc (in), yield strengths f_yc/f_yw (ksi), factored compression-flange stress f_bu (ksi, optional demand), web load-shedding factor r_b (6.10.1.10.2) and hybrid factor r_h (6.10.1.10.1).

civilpy.structural.aashto.lrfd.flange_moment_resistance(flange_force: float, moment_arm: float, m_u: float | None = None) CheckResult[source]

Moment the flange splices alone can resist as a force couple (6.13.6.1.3c): Mflange = Pfl * arm. Compared against the factored design moment m_u; any excess |Mu| - Mflange is carried by the web as the horizontal force Hw (see web_splice_design_forces()). Forces in kip, arm in inches, moments in kip-in.

civilpy.structural.aashto.lrfd.flange_splice_design_force(a_n: float, a_g: float, f_y: float, f_u: float, f_design: float | None = None) CheckResult[source]

Design force for a flange splice (6.13.6.1.3b-1): P = Fcf*Ae with the effective flange area Ae = (phi_u*Fu)/(phi_y*Fy)*An <= Ag (6.13.6.1.3b-2); phi_u = 0.80, phi_y = 0.95.

f_design is the flange design stress Fcf (6.13.6.1.3b): when omitted it defaults to the full yield stress f_y (the conservative upper bound, correct for a fully stressed flange). Supply the AASHTO Fcf – max((|fcf|/Rh + alpha*phi_f*Fyf)/2, 0.75*alpha*phi_f*Fyf) computed from the actual factored flange stress fcf – to design a lightly stressed splice for its real demand (the ODOT BDM / NSBA workbook method).

The splice plates, their bolts, and the flange itself are then checked against the returned force. capacity holds P (kip).

civilpy.structural.aashto.lrfd.format_conversion_ckf(phi: float, bearing: bool = False) float[source]

CKF (8.4.4.2): converts allowable-stress reference values to the LRFD format — 2.5/phi generally, 2.1/phi for compression perpendicular to grain (bearing).

civilpy.structural.aashto.lrfd.girder_side_from_w(label: str, grade: str = 'Grade 50', *, haunch: float = 0.0, stiffener_spacing_ft: float | None = None, stiffened: bool = False) GirderSide[source]

Build a GirderSide from a rolled AISC W-shape label (G7).

Reads depth, flange_width, flange_thickness, and web_thickness from civilpy.structural.steel.W (the AISC database); the web depth is the clear distance between flanges (d - 2*tf). Top and bottom flanges are identical for a rolled shape. grade names the steel (mapped to Fy/Fu by the splice designer’s STEEL_GRADES).

civilpy.structural.aashto.lrfd.hybrid_factor(d_n: float, t_w: float, a_fn: float, f_yw: float, f_n: float) CheckResult[source]

Hybrid factor Rh (6.10.1.10.1-1) accounting for early web yielding when the web is a lower grade than the flanges: Rh = (12 + beta*(3*rho - rho^3)) / (12 + 2*beta), rho = min(Fyw/fn, 1), beta = 2*Dn*tw/Afn.

d_n is the distance from the elastic NA to the inside of the controlling flange (in), a_fn that flange’s area (in^2), f_n its yield (or buckling) stress. Homogeneous girders get Rh = 1.0. capacity holds Rh.

civilpy.structural.aashto.lrfd.incising_factor_ci(modulus: bool = False) float[source]

Ci for incised, preservative-treated dimension lumber (8.4.4.7): 0.80 on strength values, 0.95 on modulus of elasticity.

civilpy.structural.aashto.lrfd.lateral_torsional_buckling_resistance(l_b: float, b_fc: float, t_fc: float, d_c: float, t_w: float, f_yc: float, f_yw: float, c_b: float = 1.0, f_bu: float | None = None, r_b: float = 1.0, r_h: float = 1.0) CheckResult[source]

Compression-flange lateral torsional buckling resistance Fnc (6.10.8.2.3).

Parameters: unbraced length l_b (in), compression flange b_fc x t_fc (in), depth of web in compression d_c (in), web thickness t_w (in), yield strengths (ksi), moment gradient modifier c_b, optional factored flange stress demand f_bu (ksi).

civilpy.structural.aashto.lrfd.legal_load_factor(adtt: float | None = None) float[source]

Generalized live load factor for legal-load ratings (Table 6A.4.4.2.3a-1): 1.30 at one-direction ADTT <= 1000, 1.45 at ADTT >= 5000 (or unknown), linearly interpolated between.

civilpy.structural.aashto.lrfd.lever_rule_exterior(s_ft: float, d_e_ft: float, apply_multiple_presence: bool = True) float[source]

One-lane exterior-girder DF by the lever rule (C4.6.2.2.1): deck assumed hinged at the first interior girder, one truck with wheel lines 6 ft apart, the nearer one 2 ft from the barrier face. Wheels landing inboard of the interior girder contribute nothing.

Returns lanes/girder including the 1.2 single-lane multiple presence unless apply_multiple_presence is False.

civilpy.structural.aashto.lrfd.longitudinal_stiffener_proportions(proj_width: float, t_s: float, moment_of_inertia: float, radius_of_gyration: float, d_web: float, t_w: float, d_o: float, f_ys: float, f_yc: float, r_h: float = 1.0, beta: float = 1.0) CheckResult[source]

Longitudinal web-stiffener proportioning limits (6.10.11.3).

Three requirements, all expressed as provided/required margins; the governing (minimum) margin is the reported ratio (>= 1.0 passes):

  • projecting width (6.10.11.3.2-1): proj_width <= 0.48 t_s sqrt(E/Fys)

  • moment of inertia (6.10.11.3.3-1): I_l >= D tw^3 [2.4 (do/D)^2 - 0.13] beta

  • radius of gyration (6.10.11.3.3-4): r >= 0.16 do sqrt(Fys/E) / sqrt(1 - 0.6 Fyc/(Rh Fys))

proj_width is the stiffener projecting width b_l (in), t_s its thickness (in), moment_of_inertia I_l about the web face (in^4), radius_of_gyration r (in), d_web the web depth D (in), d_o the transverse-stiffener/panel spacing (in), beta the curvature factor (1.0 for straight girders, 6.10.11.3.3-2 for curved). capacity/demand carry the I_l pair (the sizing driver); the width and r margins are in details.

civilpy.structural.aashto.lrfd.longitudinal_stiffness_kg(n_modular: float, i_girder: float, a_girder: float, e_g: float) float[source]

Kg = n*(I + A*eg^2) (4.6.2.2.1-1), in^4. e_g is the distance between girder and deck centroids (in); n_modular the girder/deck modular ratio.

civilpy.structural.aashto.lrfd.lrfd_edition(design_year: int | None = None) str[source]

Label of the LRFD edition in force for a given design year (the latest edition published in or before that year). None means current.

civilpy.structural.aashto.lrfd.modular_ratio(fc: float, e_s: float = 29000.0) float[source]

Steel/concrete modular ratio n = Es/Ec (AASHTO C6.10.1.1.1b), with Ec = 1820*sqrt(fc) ksi. fc in ksi. (fc = 4.0 -> n ~= 8.)

civilpy.structural.aashto.lrfd.moment_df_exterior(interior_df: DistributionFactor, d_e_ft: float, one_lane_lever_rule: float | None = None) DistributionFactor[source]

Moment DF for exterior I-girders (Table 4.6.2.2.2d-1): multi-lane g = e * g_interior with e = 0.77 + de/9.1; the one-lane value comes from the lever rule (pass it in — it depends on the actual overhang and wheel placement). d_e_ft is the distance from exterior web to the inside face of the barrier (ft, -1.0 <= de <= 5.5).

civilpy.structural.aashto.lrfd.moment_df_interior(s_ft: float, l_ft: float, t_s: float, k_g: float, n_beams: int = 4) DistributionFactor[source]

Moment DF for interior I-girders (Table 4.6.2.2.2b-1, type a/e/k):

one lane: 0.06 + (S/14)^0.4 * (S/L)^0.3 * (Kg/(12*L*ts^3))^0.1 multi: 0.075 + (S/9.5)^0.6 * (S/L)^0.2 * (Kg/(12*L*ts^3))^0.1

civilpy.structural.aashto.lrfd.moment_df_interior_box(b_in: float, l_ft: float, i_beam: float, j_beam: float, n_beams: int) DistributionFactor[source]

Moment DF for interior precast box beams used in multibeam decks (Table 4.6.2.2.2b-1, cross-section type g):

one lane: k*(b/33.3L)^0.5 * (I/J)^0.25 multi: k*(b/305)^0.6 * (b/12L)^0.2 * (I/J)^0.06 k = 2.5*(Nb)^-0.2 >= 1.5

b_in is the beam width (in), i_beam/j_beam the moment of inertia and St. Venant constant (in^4).

civilpy.structural.aashto.lrfd.moment_magnification(p_u: float, p_e: float, m_1: float = 0.0, m_2: float = 1.0, braced: bool = True, sum_p_u: float | None = None, sum_p_e: float | None = None, phi_k: float = 0.75) CheckResult[source]

Approximate slenderness treatment (4.5.3.2.2b): magnify the factored moment by delta_b = Cm/(1 - Pu/(phi_K*Pe)) >= 1.0 for the braced (no-sway) portion, with Cm = 0.6 + 0.4*(M1/M2) >= 0.4 for members without transverse loads; the sway portion uses delta_s = 1/(1 - sum(Pu)/(phi_K*sum(Pe))).

m_1/m_2 are the smaller/larger end moments (signed positive for single curvature). capacity holds the governing magnifier.

civilpy.structural.aashto.lrfd.multiple_presence_factor(n_lanes: int) float[source]

m (Table 3.6.1.1.2-1): 1.20 / 1.00 / 0.85 / 0.65 for 1/2/3/>3 loaded lanes. Already embedded in the 4.6.2.2 DF equations — apply only with the lever rule or refined analysis.

civilpy.structural.aashto.lrfd.net_section_reduction_limit(a_n: float, a_g: float) CheckResult[source]

Effective net area limit for splice plates in tension (6.13.5.2): the net area used for the fracture check is taken as An but not more than 0.85*Ag. Reported as a NOTICE (not a strength failure): ok is True when An <= 0.85*Ag; details['An_eff'] is the area to use downstream.

civilpy.structural.aashto.lrfd.nonslender_element_limit(b: float, t: float, f_y: float, k: float = 0.45) CheckResult[source]

Plate width-to-thickness limit for a nonslender compression element (6.9.4.2.1-1): b/t <= k*sqrt(E/Fy). k per Table 6.9.4.2.1-1 (0.45 outstanding angle legs / plates supported on one edge, 0.56 rolled-shape flanges, 1.49 stiffened webs). Exceeding the limit means the member needs the slender-element Q reduction (6.9.4.2.2).

civilpy.structural.aashto.lrfd.parapet_test_level_check(test_level: str, m_c: float, m_w: float, h_ft: float, m_b: float = 0.0, end_region: bool = False) CheckResult[source]

Convenience wrapper: yield-line capacity checked against a Table A13.2-1 test level. h_ft is wall height in ft; the result’s details flag whether the wall also meets the minimum effective height and the minimum rail height for the test level.

civilpy.structural.aashto.lrfd.parapet_yield_line_capacity(m_c: float, m_w: float, h: float, l_t: float, m_b: float = 0.0, f_t: float | None = None, end_region: bool = False) CheckResult[source]

Total transverse resistance Rw of a concrete parapet by yield-line analysis (A13.3.1), compared against the rail design force Ft.

m_c is the wall’s flexural resistance about its longitudinal axis per unit length (kip-ft/ft), m_w its resistance about the vertical axis (kip-ft), m_b any additional beam/rail resistance at top (kip-ft), h the wall height (ft), l_t the load distribution length (ft). end_region=True uses the end/joint mechanism, which mobilizes a single yield-line fan and gives a shorter critical length.

civilpy.structural.aashto.lrfd.plot_pm_interaction(points, ax=None, p_u: float | None = None, m_u: float | None = None, units: str = 'kip, kip-in')[source]

Plot a column interaction diagram from rc_pm_interaction_diagram() output: the nominal curve dashed, the factored (phi-reduced) curve solid, and optionally the factored demand point (Pu, Mu). Returns the figure.

civilpy.structural.aashto.lrfd.posting_load(rf: float, vehicle_weight_tons: float) float[source]

Safe posting load for a legal vehicle (6A.8.3-1): W*(RF - 0.3)/0.7 for 0.3 <= RF < 1.0; the full vehicle weight when RF >= 1.0; 0 (close the bridge to that vehicle) when RF < 0.3.

civilpy.structural.aashto.lrfd.proportion_limits(d_web: float, t_w: float, b_fc: float, t_fc: float, b_ft: float, t_ft: float, i_yc: float | None = None, i_yt: float | None = None) CheckResult[source]

I-girder proportion limits (6.10.2): web D/tw <= 150 (without longitudinal stiffeners); each flange bf/2tf <= 12, bf >= D/6, tf >= 1.1*tw; and 0.1 <= Iyc/Iyt <= 10 when flange inertias are given.

Pass/fail only — capacity is 1.0/0.0 against a demand of 1.0 so ok reflects all limits; per-limit booleans are in details.

civilpy.structural.aashto.lrfd.ps_anchorage_set_loss(anchor_set: float, friction_gradient: float, x_from_anchor: float = 0.0, e_p: float = 28500.0) CheckResult[source]

Loss from anchorage set in a post-tensioned tendon (5.9.3.2.1).

With a linear friction gradient friction_gradient (ksi of stress loss per inch of tendon), the set anchor_set (in, typically 0.375) affects a length x = sqrt(Ep*set/gradient); the loss is 2*gradient*x at the anchorage, decreasing linearly to zero at x. capacity holds the loss at x_from_anchor (in).

civilpy.structural.aashto.lrfd.ps_approximate_longterm_loss(f_pi: float, a_ps: float, a_g: float, f_ci: float, humidity_pct: float = 70.0, delta_f_pr: float = 2.4) CheckResult[source]

Lump-sum long-term loss for standard precast pretensioned members (5.9.3.3): creep + shrinkage + relaxation combined.

capacity holds the total loss (ksi). f_pi is the strand stress immediately prior to transfer (ksi), a_g the gross section area (in^2), humidity_pct the average annual ambient relative humidity, delta_f_pr the relaxation estimate (2.4 ksi low-relaxation strand).

civilpy.structural.aashto.lrfd.ps_deck_shrinkage_gain(delta_f_cdf: float, k_df: float, psi_tf_td: float, e_c: float, e_p: float = 28500.0) CheckResult[source]

Prestress gain from deck shrinkage (5.9.3.4.3d-1): (Ep/Ec) * delta_fcdf * Kdf * (1 + 0.7*psi(tf, td)).

delta_f_cdf is the change in concrete stress at the strand centroid caused by deck shrinkage (ksi, compressive positive — the deck shrinks, cambering the girder and compressing the bottom flange). capacity holds the gain; subtract it from the total loss.

civilpy.structural.aashto.lrfd.ps_elastic_shortening_loss(f_cgp: float, e_ct: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from elastic shortening in pretensioned members (5.9.3.2.3a): the strand sheds stress in proportion to the modular ratio times the concrete stress at the strand centroid at transfer.

capacity holds the loss (ksi). f_cgp is the concrete stress at the centroid of the prestressing at transfer (ksi); e_ct the concrete modulus at transfer (ksi).

civilpy.structural.aashto.lrfd.ps_flexural_resistance(a_ps: float, f_pu: float, d_p: float, f_c: float, b: float, m_u: float | None = None, b_w: float | None = None, h_f: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, d_s: float = 0.0, a_s_prime: float = 0.0, d_s_prime: float = 0.0, f_y_prime: float | None = None, k: float = 0.28, d_t: float | None = None) CheckResult[source]

Nominal flexural resistance Mn of a bonded prestressed section (5.6.3.2.2 flanged / 5.6.3.2.3 rectangular), kip-in.

Strand stress comes from ps_strand_stress_at_nominal(); phi varies with net tensile strain per 5.5.4.2 (1.0 when tension-controlled). d_t is the depth to the extreme tension steel for the strain check (defaults to d_p).

civilpy.structural.aashto.lrfd.ps_friction_loss(f_pj: float, x: float, alpha: float, mu: float = 0.25, k: float = 0.0002) CheckResult[source]

Friction loss in a post-tensioned tendon (5.9.3.2.2b-1): fpj * (1 - e^(-(K*x + mu*alpha))).

x is the tendon length from the jacking end (ft), alpha the sum of angular changes (radians), mu the curvature friction coefficient and k the wobble coefficient (per ft) — defaults are typical of strand in rigid galvanized ducts; use the duct manufacturer’s values when known.

civilpy.structural.aashto.lrfd.ps_principal_tension_check(f_ci: float, sigma_ps: float | None = None, lam: float = 1.0) CheckResult[source]

Principal tensile stress limit in webs (5.9.2.3.3): 0.110*lam*sqrt(f’ci), the same for segmental and non-segmental bridges. At construction stages pass the strength at the time of loading (f’ci); at service pass the specified f’c – the article covers both epochs with the same coefficient. sigma_ps is the maximum principal tensile stress (ksi, positive) from the biaxial state (sigma_x, sigma_z, tau) – e.g. via civilpy.structural.mohrs_circle.MohrsCircle.

civilpy.structural.aashto.lrfd.ps_refined_loss_creep_deck_stage(f_cgp: float, psi_tf_ti: float, psi_td_ti: float, psi_tf_td: float, delta_f_cd: float, k_df: float, e_ci: float, e_c: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder creep between deck placement and final time (5.9.3.4.3b-1):

(Ep/Eci)*fcgp*(psi(tf,ti) - psi(td,ti))*Kdf
  • (Ep/Ec)*delta_fcd*psi(tf,td)*Kdf, taken >= 0.

delta_f_cd is the change in concrete stress at the strand centroid from deck weight and superimposed loads (ksi, negative when it relieves compression).

civilpy.structural.aashto.lrfd.ps_refined_loss_creep_girder(f_cgp: float, psi_td_ti: float, k_id: float, e_ci: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder creep between transfer and deck placement (5.9.3.4.2b-1): (Ep/Eci) * fcgp * psi(td, ti) * Kid.

civilpy.structural.aashto.lrfd.ps_refined_loss_relaxation(f_pt: float, f_py: float, k_l: float = 30.0) CheckResult[source]

Strand relaxation loss per stage (5.9.3.4.2c-1): (fpt/KL) * (fpt/fpy - 0.55), taken as zero if fpt/fpy < 0.55.

f_pt is the strand stress immediately after transfer (ksi); k_l = 30 for low-relaxation strand, 7 for stress-relieved. The same value applies again for the deck-to-final stage (5.9.3.4.3c).

civilpy.structural.aashto.lrfd.ps_refined_loss_shrinkage_deck_stage(eps_bdf: float, k_df: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder shrinkage between deck placement and final time (5.9.3.4.3a-1): eps_bdf * Ep * Kdf, with Kdf computed on the composite section.

civilpy.structural.aashto.lrfd.ps_refined_loss_shrinkage_girder(eps_bid: float, k_id: float, e_p: float = 28500.0) CheckResult[source]

Prestress loss from girder shrinkage between transfer and deck placement (5.9.3.4.2a-1): eps_bid * Ep * Kid.

eps_bid is the girder shrinkage strain over that interval (from shrinkage_strain()), k_id from ps_section_age_adjustment(). capacity holds the loss (ksi).

civilpy.structural.aashto.lrfd.ps_section_age_adjustment(a_ps: float, a_g: float, i_g: float, e_pg: float, psi_final: float, e_ci: float, e_p: float = 28500.0) float[source]

Transformed-section/age-adjusted coefficient Kid (5.9.3.4.2a-2) — or Kdf with composite-section properties (5.9.3.4.3a-2).

e_pg is the strand eccentricity from the section centroid (in), psi_final the creep coefficient psi(tf, ti), e_ci the concrete modulus at transfer (ksi).

civilpy.structural.aashto.lrfd.ps_service_compression_check(f_c: float, stress_permanent: float | None = None, stress_total: float | None = None, phi_w: float = 1.0) CheckResult[source]

Service-level compressive stress limits after losses (5.9.2.3.2a): 0.45*f’c under effective prestress plus permanent loads, and 0.60*phi_w*f’c under the full Service I combination (phi_w is the slenderness reduction for thin-walled sections; 1.0 for solid beams).

The governing case (lowest margin) populates capacity/demand; both are reported in details.

civilpy.structural.aashto.lrfd.ps_service_tension_check(f_c: float, stress: float | None = None, severe_corrosion: bool = False, lam: float = 1.0) CheckResult[source]

Service III tensile stress limit after losses for components with bonded tendons (5.9.2.3.2b): 0.19*lam*sqrt(f’c) <= 0.6 ksi, halved in effect for severe corrosion conditions (0.0948*lam*sqrt(f’c) <= 0.3 ksi). stress is tensile stress magnitude (ksi, positive).

civilpy.structural.aashto.lrfd.ps_splitting_resistance(a_s_end: float, p_r_demand: float | None = None, f_s: float = 20.0) CheckResult[source]

Splitting (bursting) resistance at pretensioned member ends (5.9.4.4.1-1): Pr = fs * As, where As is the reinforcement within h/4 of the end and fs is limited to 20 ksi. Pr must resist at least 4% of the total prestress force at transfer — pass 0.04*Ppt as the demand.

civilpy.structural.aashto.lrfd.ps_strand_development(f_ps: float, f_pe: float, d_b: float, kappa: float = 1.6, embedment: float | None = None) CheckResult[source]

Development length of bonded pretensioned strand (5.9.4.3.2-1): ld >= kappa * (fps - 2/3*fpe) * db, with transfer length 60*db.

kappa = 1.6 for members deeper than 24 in, 1.0 otherwise. capacity holds the required ld (in); pass the available embedment as the demand side — note this check is inverted (embedment must exceed ld), so ok is computed accordingly.

civilpy.structural.aashto.lrfd.ps_strand_stress_at_nominal(a_ps: float, f_pu: float, d_p: float, f_c: float, b: float, b_w: float | None = None, h_f: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, d_s: float = 0.0, a_s_prime: float = 0.0, f_y_prime: float | None = None, k: float = 0.28) CheckResult[source]

Average stress fps in bonded prestressing strands when the section reaches its nominal flexural resistance (5.6.3.1.1), with the neutral axis found for rectangular or flanged behavior.

capacity holds fps (ksi). a_ps is strand area (in^2) at depth d_p; b is the compression-face width, b_w/h_f the web width and flange thickness for T-shaped behavior; mild steel a_s / a_s_prime may be included. k is 0.28 for low-relaxation strand, 0.38 for stress-relieved.

civilpy.structural.aashto.lrfd.ps_strand_stress_unbonded(a_ps: float, f_pe: float, d_p: float, f_c: float, b: float, l_i: float, f_py: float, n_s: int = 0, b_w: float | None = None, h_f: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, a_s_prime: float = 0.0, f_y_prime: float | None = None, max_iter: int = 100, tol: float = 1e-06) CheckResult[source]

Average stress fps in unbonded strands at nominal flexural resistance (5.6.3.1.2-1), with the effective tendon length from 5.6.3.1.2-2:

fps = fpe + 900 (dp - c) / le <= fpy, le = 2 li / (2 + Ns)

An unbonded tendon slips relative to the concrete, so its strain change averages over le instead of peaking at the critical section – fps lands far below the bonded 5.6.3.1.1 value. l_i is the tendon length between anchorages (in); n_s the number of support hinges crossed. fps and the neutral axis are solved together by fixed-point iteration from the commentary’s fpe + 15 start; rectangular or flanged behavior as in ps_strand_stress_at_nominal(). capacity holds fps (ksi).

civilpy.structural.aashto.lrfd.ps_tendon_stress_limits(f_pu: float, f_py: float | None = None, tendon_type: str = 'low_relaxation') dict[source]

Tendon stress limits of Table 5.9.2.2-1 (ksi) keyed by condition: pre_* rows for pretensioning (prior to transfer, service after losses), post_* rows for post-tensioning (prior to seating, at anchorages/couplers immediately after anchor set, elsewhere after set, service after losses).

f_py defaults to 0.90*f_pu (low-relaxation) or 0.85*f_pu (stress-relieved / plain bar). Midas reports these as the AFDL1 / AFDL2 / AFLL1 allowables against the computed FDL1 / FDL2 / FLL1 tendon stresses.

civilpy.structural.aashto.lrfd.ps_transfer_compression_check(f_ci: float, stress: float | None = None, design_year: int | None = None) CheckResult[source]

Compressive stress limit at transfer (5.9.2.3.1a): 0.65*f’ci, or 0.60*f’ci for designs before the 2016 interim revisions (pass design_year for historical designs). stress is the computed compressive stress magnitude (ksi, positive).

civilpy.structural.aashto.lrfd.ps_transfer_tension_check(f_ci: float, stress: float | None = None, bonded_reinforcement: bool = False, lam: float = 1.0) CheckResult[source]

Tensile stress limit at transfer (5.9.2.3.1b): 0.0948*lam*sqrt(f’ci) capped at 0.2 ksi without bonded reinforcement sized for the tensile force, or 0.24*lam*sqrt(f’ci) with it. stress is tensile stress magnitude (ksi, positive).

civilpy.structural.aashto.lrfd.rating_factor(nominal_capacity: float, dc: float, ll_im: float, dw: float = 0.0, phi: float = 1.0, level: str = 'inventory', gamma_ll: float | None = None, gamma_dc: float = 1.25, gamma_dw: float = 1.5, condition: str = 'good', system: str = 'other_girder_slab', permanent_other: float = 0.0, gamma_p: float = 1.0, service: bool = False) CheckResult[source]

General LRFR rating factor (MBE 6A.4.2.1-1).

nominal_capacity is Rn from any capacity check in this package (pass the check’s capacity and its phi); dc/dw/ll_im are the unfactored force effects, with ll_im already including the distribution factor and dynamic load allowance. level selects the design-load gamma_LL (1.75 inventory / 1.35 operating) unless gamma_ll is given (legal/permit ratings). At service limit states pass service=True to skip the condition/system factors.

capacity on the result holds RF; ok means RF >= 1.0.

civilpy.structural.aashto.lrfd.rc_biaxial_check(p_u: float, m_ux: float, m_uy: float, m_rx: float, m_ry: float, p_rx: float | None = None, p_ry: float | None = None, phi_p_o: float | None = None, f_c: float | None = None, a_g: float | None = None) CheckResult[source]

Biaxial flexure (5.6.4.5). Below the low-axial threshold 0.10*phi*f’c*Ag the moment-contour form applies: Mux/Mrx + Muy/Mry <= 1.0. Above it, the reciprocal (Bresler) load method: 1/Prxy = 1/Prx + 1/Pry - 1/(phi*Po) and Prxy >= Pu.

m_rx/m_ry are the factored uniaxial moment resistances at Pu (from rc_pm_capacity_check()); p_rx/p_ry the factored axial resistances at eccentricities ey and ex. capacity/demand carry the governing pair (resistance/applied).

civilpy.structural.aashto.lrfd.rc_column_axial_resistance(a_g: float, a_st: float, f_c: float, f_y: float, p_u: float | None = None, spiral: bool = False) CheckResult[source]

Nominal axial resistance of a nonprestressed column (5.6.4.4): Po = 0.85*f’c*(Ag - Ast) + fy*Ast, with Pn = 0.85*Po for spiral columns and 0.80*Po for tied columns; phi = 0.75.

civilpy.structural.aashto.lrfd.rc_column_reinforcement_limits(a_g: float, a_st: float, f_c: float, f_y: float) CheckResult[source]

Longitudinal reinforcement limits for columns (5.6.4.2): maximum Ast/Ag <= 0.08 and minimum Ast*fy/(Ag*f’c) >= 0.135.

Pass/fail check — per-limit booleans in details.

civilpy.structural.aashto.lrfd.rc_crack_control_spacing(d_c: float, h: float, f_ss: float, f_y: float = 60.0, spacing: float | None = None, exposure_class_2: bool = False) CheckResult[source]

Maximum bar spacing for crack control (5.6.7, 2005 interim onward): s <= 700*gamma_e/(beta_s*fss) - 2*dc, the standard deck and tension-face check.

d_c is cover to center of nearest bar (in), h overall thickness (in), f_ss service-level steel stress (ksi, capped at 0.6*fy per the article), spacing the actual bar spacing (demand). Class 2 exposure (gamma_e = 0.75) is for decks/substructure exposed to chlorides; Class 1 (1.00) otherwise.

civilpy.structural.aashto.lrfd.rc_crack_control_z_factor(d_c: float, a_bar: float, f_ss: float | None = None, f_y: float = 60.0, z: float = 170.0) CheckResult[source]

Crack control for designs before the 2005 interim revisions, when the article (then 5.7.3.4) limited steel stress to z/(dc*A)^(1/3) rather than limiting bar spacing.

a_bar is the concrete tension area per bar A = 2*dc*s/n (in^2), z the crack-width parameter (kip/in): 170 moderate exposure, 130 severe, 100 buried. f_ss is the service steel stress (demand, ksi); the allowable is also capped at 0.6*fy.

civilpy.structural.aashto.lrfd.rc_effective_moment_of_inertia(i_g: float, i_cr: float, m_cr: float, m_a: float) float[source]

Branson effective moment of inertia for deflections (5.6.3.5.2): Ie = (Mcr/Ma)^3*Ig + (1 - (Mcr/Ma)^3)*Icr, capped at Ig and equal to Ig when the section is uncracked (Ma <= Mcr). in^4.

civilpy.structural.aashto.lrfd.rc_effective_shear_depth(h: float, a: float, a_ps: float = 0.0, f_ps: float = 0.0, d_p: float = 0.0, a_s: float = 0.0, f_y: float = 60.0, d_s: float = 0.0) CheckResult[source]

Effective shear depth dv (5.7.2.8): the lever arm between the flexural tension and compression resultants,

dv = max(de - a/2, 0.9*de, 0.72*h)

with the effective depth combining strands and mild steel (5.7.2.8-2): de = (Aps*fps*dp + As*fy*ds) / (Aps*fps + As*fy). a is the equivalent stress-block depth at the section. capacity holds dv (in). Segmental box girders use 5.12.5.3.8c instead (the greater of 0.8h and the depth to the prestressing centroid) – not implemented here.

civilpy.structural.aashto.lrfd.rc_interface_shear(a_cv: float, f_c: float, case: str = 'roughened', v_ui: float | None = None, a_vf: float = 0.0, f_y: float = 60.0, p_c: float = 0.0) CheckResult[source]

Interface (horizontal) shear resistance (5.7.4.3-3): Vni = c*Acv + mu*(Avf*fy + Pc), capped at min(K1*f’c, K2)*Acv.

case selects the 5.7.4.4 cohesion/friction set (see INTERFACE_SHEAR_CASES); a_cv is the interface area (in^2), a_vf the reinforcement crossing it (in^2), p_c permanent net compressive force (kip); v_ui the factored interface shear demand (kip) checked against phi_v = 0.9 times Vni. details includes the 5.7.4.2 minimum Avf.

civilpy.structural.aashto.lrfd.rc_longitudinal_reinforcement(m_u: float, v_u: float, d_v: float, theta_deg: float, a_s_f_y: float = 0.0, a_ps_f_ps: float = 0.0, n_u: float = 0.0, v_s: float = 0.0, v_p: float = 0.0, phi_f: float = 0.9, phi_v: float = 0.9, phi_c: float = 0.75) CheckResult[source]

Tension demand on longitudinal reinforcement from combined moment, axial, and shear (5.7.3.5-1):

Aps*fps + As*fy >= |Mu|/(dv*phi_f) + 0.5*Nu/phi_c
                   + (|Vu/phi_v - Vp| - 0.5*Vs)*cot(theta)

v_s is capped at Vu/phi_v per the article. capacity is the tension the reinforcement can develop (pass the products As*fy and Aps*fps), demand the required tension.

civilpy.structural.aashto.lrfd.rc_max_stirrup_spacing(v_u: float, b_v: float, d_v: float, f_c: float, s: float | None = None, v_p: float = 0.0, phi_v: float = 0.9) CheckResult[source]

Maximum stirrup spacing (5.7.2.6): with the shear stress vu = |Vu - phi*Vp|/(phi*bv*dv), smax = min(0.8*dv, 24in) when vu < 0.125*f’c, else min(0.4*dv, 12in). capacity is smax and demand the actual spacing s.

civilpy.structural.aashto.lrfd.rc_mcft_beta_theta(m_u: float, v_u: float, d_v: float, e_s_a_s: float, n_u: float = 0.0, v_p: float = 0.0, a_ps: float = 0.0, f_po: float = 0.0, e_p_a_ps: float = 0.0, has_min_transverse_reinf: bool = True, s_x: float | None = None, a_g_agg: float = 0.75, e_c_a_ct: float = 0.0) MCFTParams[source]

Longitudinal strain, beta, and theta per the general (MCFT-based) procedure (5.7.3.4.2).

e_s_a_s and e_p_a_ps are the stiffness products Es*As and Ep*Aps (kip) on the flexural tension side; f_po is normally 0.7*fpu for bonded strand. With minimum transverse reinforcement, beta = 4.8/(1 + 750*eps_s); without it the crack-spacing penalty 51/(39 + sxe) applies, where s_x (in) and the max aggregate size a_g_agg (in) set sxe. When eps_s comes out negative (section uncracked), the concrete stiffness e_c_a_ct = Ec*Act may be added to the denominator; eps_s is bounded to [-0.40e-3, 6.0e-3].

civilpy.structural.aashto.lrfd.rc_min_transverse_reinforcement(b_v: float, s: float, f_c: float, f_y: float = 60.0, a_v: float | None = None, lam: float = 1.0) CheckResult[source]

Minimum transverse reinforcement where shear reinforcement is required (5.7.2.5-1): Av >= 0.0316*lam*sqrt(f’c)*bv*s/fy.

capacity is the provided a_v (in^2) and demand the required minimum, so ratio >= 1 passes.

civilpy.structural.aashto.lrfd.rc_minimum_reinforcement(m_n: float, phi: float, f_c: float, s_c: float, m_u: float | None = None, gamma_1: float = 1.6, gamma_3: float = 0.67, design_year: int | None = None, f_cpe: float = 0.0, gamma_2: float = 1.1, m_dnc: float = 0.0, s_nc: float | None = None, f_r: float | None = None) CheckResult[source]

Minimum flexural reinforcement check (5.6.3.3): Mr = phi*Mn must exceed the lesser of Mcr and 1.33*Mu, with the full 5.6.3.3-1 cracking moment:

Mcr = gamma_3 * [(gamma_1*fr + gamma_2*f_cpe)*Sc
  • M_dnc*(Sc/Snc - 1)]

s_c is the section modulus of the extreme tension fiber (in^3); f_cpe the compressive stress there from effective prestress (ksi, 0 for nonprestressed); for composite sections m_dnc is the unfactored dead-load moment carried by the noncomposite section (kip-in) and s_nc its section modulus (the deduction vanishes for monolithic/noncomposite sections, s_nc = None). gamma_1 = 1.6 flexural cracking variability (1.2 precast segmental), gamma_2 = 1.1 prestress variability (bonded; 1.0 unbonded), gamma_3 = 0.67 for A615 Grade 60, 0.75 for A706, 1.0 for prestressed structures. Designs before the 2012 6th Edition used 1.2*Mcr instead of the gamma factors — pass design_year for historical designs (gamma_1/gamma_3 overrides are ignored; gamma_2 becomes 1.0).

f_r overrides the 5.4.2.6 modulus of rupture (0.24*sqrt(f’c)) – e.g. 0.37*sqrt(f’c) to reproduce Midas Civil (or the 2008-2016 editions whose conservatism the gamma_1 = 1.6 factor replaced).

civilpy.structural.aashto.lrfd.rc_pm_capacity_check(p_u: float, m_u: float, layers: list[RebarLayer], f_c: float, f_y: float, h: float | None = None, b: float | None = None, diameter: float | None = None, spiral: bool = False) CheckResult[source]

Uniaxial column adequacy: interpolate the factored interaction diagram at the factored axial load p_u (kip, compression positive) and compare the available phi*Mn against m_u (kip-in).

capacity holds the factored moment resistance at Pu; phi on the result is 1.0 because phi is baked into the diagram point by point (it varies with eps_t along the curve).

civilpy.structural.aashto.lrfd.rc_pm_interaction_diagram(layers: list[RebarLayer], f_c: float, f_y: float, h: float | None = None, b: float | None = None, diameter: float | None = None, spiral: bool = False, n_points: int = 60) list[PMPoint][source]

Nominal P-M interaction diagram for a rectangular (b x h) or circular (diameter) reinforced section by strain compatibility, sweeping the neutral axis from pure tension to pure compression.

Returns points ordered from pure tension (negative Pn) to the maximum axial point, with phi per 5.5.4.2 attached; Pn is capped at the 5.6.4.4 tied/spiral maximum. Moments are about the section mid-depth (symmetric sections assumed for the axial-load point of application).

civilpy.structural.aashto.lrfd.rc_rectangular_flexural_resistance(a_s: float, f_y: float, f_c: float, b: float, d_s: float, m_u: float | None = None, a_s_prime: float = 0.0, d_s_prime: float = 0.0, f_y_prime: float | None = None) CheckResult[source]

Nominal flexural resistance of a rectangular (or rectangular-behaving) reinforced section (5.6.3.2.3), with phi per 5.5.4.2.

Parameters: tension steel a_s (in^2) at depth d_s (in), compression steel a_s_prime at d_s_prime, section width b (in), f_y/f_c (ksi), optional factored moment demand m_u (kip-in). Compression steel is assumed yielding only if the computed strain supports it; otherwise it is ignored (conservative).

civilpy.structural.aashto.lrfd.rc_shear_resistance(b_v: float, d_v: float, f_c: float, v_u: float | None = None, a_v: float = 0.0, s: float = 1.0, f_y: float = 60.0, beta: float = 2.0, theta_deg: float = 45.0, v_p: float = 0.0, lam: float = 1.0, alpha_deg: float = 90.0) CheckResult[source]

Nominal shear resistance Vn (5.7.3.3) with phi_v = 0.9 (5.5.4.2).

Vc = 0.0316*lam*beta*sqrt(f’c)*bv*dv (5.7.3.3-3) and Vs per 5.7.3.3-4 with stirrups a_v (in^2) at spacing s (in), inclined at alpha_deg to the longitudinal axis (90 = vertical, where the (cot theta + cot alpha)*sin alpha term reduces to cot theta). Defaults beta = 2.0 / theta = 45 deg correspond to the 5.7.3.4.1 simplified procedure; pass values from the 5.7.3.4.2 general (MCFT) procedure for sections that qualify for it.

civilpy.structural.aashto.lrfd.rc_spiral_reinforcement(a_g: float, a_c: float, f_c: float, f_yh: float = 60.0, rho_s_provided: float | None = None) CheckResult[source]

Minimum volumetric spiral reinforcement ratio (5.6.4.6-1): rho_s >= 0.45*(Ag/Ac - 1)*f’c/fyh.

a_c is the core area to the outside of the spiral (in^2); the provided ratio (4*Asp/(d_core*pitch)) is the capacity side.

civilpy.structural.aashto.lrfd.rc_torsion_longitudinal(t_u: float, p_h: float, a_o: float, f_y: float = 60.0, a_lt: float | None = None, phi_t: float = 0.9) CheckResult[source]

Additional longitudinal reinforcement for torsion in box sections (5.7.3.6.3-2): Alt >= (Tu/phi)*ph / (2*Ao*fy).

p_h is the perimeter of the centerline of the closed transverse reinforcement (in). capacity is the provided a_lt (in^2, if given) and demand the required area.

civilpy.structural.aashto.lrfd.rc_torsion_resistance(a_o: float, a_t: float, s: float, theta_deg: float = 45.0, f_y: float = 60.0, t_u: float | None = None, lam_duct: float = 1.0) CheckResult[source]

Nominal torsional resistance (5.7.3.6.2-1): Tn = 2*Ao*At*fy*cot(theta)/s * lam_duct, with phi_t = 0.9 (5.5.4.2.1).

a_t is the area of ONE leg of closed transverse torsion reinforcement (in^2) at spacing s (in); theta_deg from the shear MCFT procedure; lam_duct the duct-reduction factor (5.7.3.6.2, 1.0 with no ducts in the web).

civilpy.structural.aashto.lrfd.rc_torsion_threshold(a_cp: float, p_c: float, f_c: float, t_u: float | None = None, f_pc: float = 0.0, lam: float = 1.0, phi_t: float = 0.9, a_o: float | None = None, b_e: float | None = None) CheckResult[source]

Whether torsion must be considered (5.7.2.1): Tu > 0.25*phi*Tcr.

Solid sections (5.7.2.1-4): Tcr = 0.126*lam*sqrt(f’c)*(Acp^2/pc)*sqrt(1 + fpc/(0.126*lam*sqrt(f’c))); cellular/box sections (5.7.2.1-5, pass a_o and b_e): Tcr = 0.126*lam*sqrt(f’c)*2*Ao*be*sqrt(same term).

a_cp is the area enclosed by the outside perimeter (in^2), p_c that perimeter (in), a_o the area enclosed by the shear flow path (in^2), b_e its effective width (min wall, <= Acp/pc), f_pc the prestress at the centroid – or at the web/flange junction when the centroid falls in the flange (ksi). capacity is the 0.25*phi*Tcr threshold (kip-in); ok True means torsion may be neglected.

civilpy.structural.aashto.lrfd.rc_transverse_reinf_required(v_u: float, v_c: float, v_p: float = 0.0, phi_v: float = 0.9) CheckResult[source]

Whether transverse reinforcement is required (5.7.2.3-1): Vu > 0.5*phi*(Vc + Vp). Below that threshold the transverse reinforcement checks may be skipped. capacity is the threshold (kips), demand is Vu; details['required'] gives the verdict.

civilpy.structural.aashto.lrfd.rebar_development_length(d_b: float, f_y: float = 60.0, f_c: float = 4.0, top_bar: bool = False, epoxy_coated: bool = False, cover_lt_3db: bool = False, lambda_rc: float = 1.0, lam: float = 1.0, available: float | None = None) CheckResult[source]

Tension development length of deformed bars (5.10.8.2.1, current edition): ld = ldb * modifiers, ldb = 2.4*db*fy/sqrt(f’c), >= 12 in.

Modifiers: 1.3 for top bars (>12 in of fresh concrete below), epoxy coating 1.5 when cover < 3db or clear spacing < 6db else 1.2 (their product with the top-bar factor need not exceed 1.7), confinement reduction lambda_rc (0.4 <= lambda_rc <= 1.0) from 5.10.8.2.1c. capacity is the available embedment when given (ok means it exceeds ld); otherwise ld itself.

civilpy.structural.aashto.lrfd.shear_connector_fatigue_pitch(d_stud: float, n_per_row: int, shear_flow: float, n_cycles: float | None = None, pitch: float | None = None) CheckResult[source]

Required stud pitch for fatigue (6.10.10.1.2): p <= n*Zr/Vsr, where the fatigue resistance of one stud is Zr = 5.5*d^2 for Fatigue I (infinite life, n_cycles omitted) or Zr = alpha*d^2 with alpha = 34.5 - 4.28*log10(N) for Fatigue II (6.10.10.2). (The old 4th-edition single-combination rule floored alpha*d^2 at 5.5*d^2/2; the floor died with the Fatigue I/II split.)

shear_flow is the fatigue shear flow Vsr = Vf*Q/I (kip/in). capacity is the maximum permitted pitch (in); pass the actual pitch as demand — note larger-is-worse, so ok means pitch <= max.

civilpy.structural.aashto.lrfd.shear_connector_fatigue_resistance(d_stud: float, n_cycles: float | None = None) CheckResult[source]

Fatigue shear resistance of one stud (6.10.10.2): Fatigue I (infinite life, n_cycles=None): Zr = 5.5*d^2 (6.10.10.2-1). Fatigue II: Zr = alpha*d^2 with alpha = 34.5 - 4.28*log10(N).

civilpy.structural.aashto.lrfd.shear_connector_strength(d_stud: float, f_c: float, e_c: float, nominal_force: float | None = None, f_u_stud: float = 60.0) CheckResult[source]

Nominal resistance of one stud shear connector (6.10.10.4.3-1): Qn = 0.5*Asc*sqrt(f’c*Ec) <= Asc*Fu, phi_sc = 0.85.

Pass the interface force nominal_force P (6.10.10.4.2 — the lesser of the deck crushing and steel yielding forces, kip) to get the required connector count in details.

civilpy.structural.aashto.lrfd.shear_connector_transverse_spacing(d_stud: float, n_per_row: int, gauge_in: float, flange_width_in: float) CheckResult[source]

Transverse spacing limits for stud rows (6.10.10.3): center-to-center >= 4 stud diameters, and clear distance from the flange edge to the nearest stud >= 1.0 in. The governing margin is the reported ratio.

civilpy.structural.aashto.lrfd.shear_df_exterior(interior_df: DistributionFactor, d_e_ft: float, one_lane_lever_rule: float | None = None) DistributionFactor[source]

Shear DF for exterior I-girders (Table 4.6.2.2.3b-1): multi-lane g = e * g_interior with e = 0.6 + de/10.

civilpy.structural.aashto.lrfd.shear_df_interior(s_ft: float, l_ft: float = 80.0, t_s: float = 8.0, n_beams: int = 4) DistributionFactor[source]

Shear DF for interior I-girders (Table 4.6.2.2.3a-1, type a/e/k): one lane 0.36 + S/25; multi 0.2 + S/12 - (S/35)^2.

civilpy.structural.aashto.lrfd.shrinkage_strain(t: float, f_ci: float, humidity_pct: float = 70.0, v_s: float = 3.5, design_year: int | None = None) float[source]

Shrinkage strain eps_sh (5.4.2.3.3-1): ks * khs * kf * ktd * 0.48e-3 (in/in, returned positive for shortening). t is drying time in days from the end of curing.

civilpy.structural.aashto.lrfd.size_factor_cf(d: float) float[source]

CF for sawn beams and stringers deeper than 12 in (8.4.4.4): (12/d)^(1/9), 1.0 otherwise.

civilpy.structural.aashto.lrfd.size_flange_splice_plates(flange_width_left: float, flange_width_right: float, flange_thickness: float, web_thickness_left: float, web_thickness_right: float, weld_size: float = 0.0, outer_thickness: float | None = None, width_increment: float = 0.5, thickness_increment: float = 0.0625) FlangeSplicePlates[source]

Proportion the outer and inner flange splice plates from the girder geometry (C6.13.6.1.3b; NSBA Bolted Field Splices for Steel Bridge Flexural Members).

  • Outer plate width = the narrower connected flange, min(bf_left, bf_right) — the outer plate must be at least as wide as the narrowest flange at the splice.

  • Web clearance gap = max(tw_left, tw_right) + 2*(weld_size + 1/8) so the inner plates clear the web and its fillet welds.

  • Inner plate width = (outer_width - clearance)/2 (each of the pair), rounded down to width_increment.

  • Minimum plate thickness = flange_thickness/2 + 1/16.

  • With the outer thickness chosen (defaults to the rounded-up minimum), the ideal inner thickness equalises the plate areas: t_inner = t_outer * b_outer / (2*b_inner_exact), rounded up to thickness_increment; the returned band keeps the areas within 10%.

flange_thickness is the thickness of the flange being developed (the thicker adjoining flange governs the minimum plate thickness).

civilpy.structural.aashto.lrfd.size_web_splice_plate(web_depth: float, web_thickness: float, web_thickness_other: float, flange_clearance: float, thickness: float | None = None, thickness_increment: float = 0.0625) WebSplicePlates[source]

Proportion the web splice plates from the web geometry (6.13.6.1.3c; seal spacing 6.13.2.6.2).

  • Minimum plate thickness = web_thickness/2 + 1/16 (web_thickness is the governing/thinner connected web).

  • Plate height = web_depth - 2*flange_clearance — the plates extend nearly the full web depth, clearing the flanges by flange_clearance top and bottom.

  • Maximum bolt pitch for sealing = min(4.0 + 4.0*t, 7.0) in (6.13.2.6.2), giving a minimum of 1 + ceil(height/max_pitch) bolts in each vertical line.

  • A filler is required when the two webs differ by more than 1/16 in.

No filler is needed when the web-thickness difference is under 1/16 in.

civilpy.structural.aashto.lrfd.skew_correction_moment(skew_deg: float, s_ft: float, l_ft: float, t_s: float, k_g: float) float[source]

Reduction of moment DF on skewed supports (Table 4.6.2.2.2e-1): 1 - c1*(tan(theta))^1.5, with c1 = 0.25*(Kg/(12*L*ts^3))^0.25*(S/L)^0.5. No reduction below 30 degrees; theta capped at 60.

civilpy.structural.aashto.lrfd.skew_correction_shear(skew_deg: float, l_ft: float, t_s: float, k_g: float) float[source]

Increase of shear DF at the obtuse corner of skewed spans (Table 4.6.2.2.3c-1): 1 + 0.20*(12*L*ts^3/Kg)^0.3 * tan(theta).

civilpy.structural.aashto.lrfd.slab_crushing_resistance(f_c: float, b_eff: float, t_s: float, demand_force: float | None = None) CheckResult[source]

Plastic compressive force the composite deck can deliver at the splice (Appendix D6.1): Prb = 0.85*f’c*b_eff*t_s. For a composite section the flange tension force plus the web horizontal force Hw must not exceed this, otherwise the deck is over-stressed and the splice should be designed as non-composite. Pass demand_force = flange force + Hw.

civilpy.structural.aashto.lrfd.slab_equivalent_strip(span_ft: float, width_ft: float, n_lanes: int, multi_lane: bool = True, skew_deg: float = 0.0) float[source]

Equivalent strip width E (in) carrying one wheel line of live load in a cast-in-place slab bridge (4.6.2.3):

one lane: E = 10.0 + 5.0*sqrt(L1*W1), W1 capped at 30 ft multi: E = 84.0 + 1.44*sqrt(L1*W1) <= 12.0*W/NL, W1 capped at 60 ft

with L1 = min(span, 60 ft). Skewed bridges may reduce the force effects by r = 1.05 - 0.25*tan(theta) <= 1.00 — the reduction is applied to E here (wider strip = lower demand per ft).

civilpy.structural.aashto.lrfd.splice_plate_design_force(p_fy: float, a_g_outer: float, a_g_inner: float) SplicePlateForces[source]

Apportion the flange design force Pfy between the outer and inner splice plates (C6.13.6.1.3b). If the plate areas differ by no more than 10%, the force is divided equally (double shear, Pfy/2 each); otherwise it is split in proportion to plate area.

civilpy.structural.aashto.lrfd.st_venant_j(d_web: float, t_w: float, b_fc: float, t_fc: float, b_ft: float, t_ft: float) float[source]

St. Venant torsional constant (A6.3.3-9): J = D*tw^3/3 + sum(bf*tf^3/3 * (1 - 0.63*tf/bf)), in^4.

civilpy.structural.aashto.lrfd.stability_bracing_torsional(m_r: float, l_span: float, n_braces: int, i_eff: float, brace_stiffness: float, c_b: float = 1.0, l_b: float | None = None, phi: float = 0.75) CheckResult[source]

Torsional stability-bracing stiffness + strength for cross-frames / diaphragms (6.7.4.2.2, 10th Edition), the adopted Yura provisions.

  • Required torsional brace stiffness (stiffness limit): beta_Treq = 2.4 L Mr^2 / (phi n E I_eff C_b^2)

  • Required brace strength (moment): M_br = 0.024 Mr L / (n C_b L_b)

m_r is the required flexural strength Mr (kip-in), l_span the span L (in), n_braces the number of intermediate brace points, i_eff the effective lateral moment of inertia I_eff (in^4), brace_stiffness the provided torsional stiffness beta_T (kip-in/rad), c_b the moment gradient, l_b the unbraced length (in, defaults to L/(n+1)). The reported ratio is the provided/required stiffness margin; the required brace moment is in details.

NOTE: coefficients follow the adopted torsional-bracing model; validate against BrR (ALRFD_10E_06_07_04_02_02_Stiffness/_Strength) before relying on this for production ratings — flagged in the build plan.

civilpy.structural.aashto.lrfd.stm_crack_control_reinforcement(b_w: float, s_h: float, s_v: float, a_s_horizontal: float | None = None, a_s_vertical: float | None = None) CheckResult[source]

Orthogonal crack-control reinforcement in the D-region (5.8.2.6): a ratio of at least 0.003 in each direction, spacing <= min(d/4, 12in) checked by the caller.

Pass the provided bar areas per grid spacing (in^2 at s_h/s_v in); the check compares each direction’s ratio against 0.003. This is what qualifies the nodes for the full Table 5.8.2.5.3a-1 nu.

civilpy.structural.aashto.lrfd.stm_node_resistance(a_cn: float, f_c: float, node_type: str = 'CCC', crack_control: bool = True, m_confinement: float = 1.0, p_u: float | None = None, nu: float | None = None) CheckResult[source]

Crushing resistance of a node face or the strut bearing on it (5.8.2.5.3): Pn = fcu*Acn with fcu = m*nu*f’c.

node_type is the joint classification (CCC, CCT, CTT) setting the efficiency factor nu from Table 5.8.2.5.3a-1; without crack-control reinforcement per 5.8.2.6, nu drops to 0.45. m_confinement is the sqrt(A2/A1) <= 2 bearing modification; pass nu directly to override the table. phi = 0.70.

civilpy.structural.aashto.lrfd.stm_tie_resistance(a_st: float, f_y: float = 60.0, a_ps: float = 0.0, f_pe: float = 0.0, p_u: float | None = None) CheckResult[source]

Nominal resistance of a tie (5.8.2.4.1-1): Pn = fy*Ast + Aps*(fpe + fy), phi = 0.90.

The prestressing term caps the usable strand stress at fpe plus one mild-steel yield increment so tie strain stays compatible with the surrounding reinforcement. p_u is the solved tie force (kip).

civilpy.structural.aashto.lrfd.tension_flange_resistance(f_yt: float, f_bu: float | None = None, f_l: float = 0.0, r_h: float = 1.0) CheckResult[source]

Tension-flange nominal resistance Fnt = Rh*Fyt (6.10.8.3), checked as fbu + fl/3 <= phi_f*Fnt (6.10.8.1.2-1). f_l is the flange lateral bending stress (ksi).

civilpy.structural.aashto.lrfd.tension_member_resistance(a_g: float, f_y: float, a_n: float | None = None, f_u: float | None = None, u_shear_lag: float = 1.0, p_u: float | None = None) CheckResult[source]

Factored tensile resistance (6.8.2.1): lesser of yielding on the gross section (phi_y = 0.95) and rupture on the net section (phi_u = 0.80, with shear-lag factor U). capacity holds the governing factored resistance (phi already applied — phi on the result is 1.0 to avoid double-counting).

civilpy.structural.aashto.lrfd.timber_flexural_resistance(f_b_adj: float, s_x: float, c_l: float = 1.0, m_u: float | None = None) CheckResult[source]

Flexural resistance of a wood beam (8.6): Mn = Fb_adj * Sx * CL, Mr = phi_f * Mn with phi_f = 0.85.

f_b_adj is the fully adjusted bending strength (ksi, including CKF/CM/CF/Clambda etc.), s_x the section modulus (in^3).

civilpy.structural.aashto.lrfd.time_effect_clambda(limit_state: str = 'Strength I') float[source]

Clambda (Table 8.4.4.9-1) by limit state.

civilpy.structural.aashto.lrfd.transverse_stiffener_inertia(moment_of_inertia: float, b_t: float, t_p: float, d_web: float, t_w: float, d_o: float, f_yw: float, f_ys: float, tension_field: bool = False) CheckResult[source]

Transverse-stiffener moment-of-inertia requirement (6.10.11.1.3).

moment_of_inertia is the provided I_t (in^4; single stiffener taken about the web face, a pair about the web mid-thickness).

  • I_t1 = b * tw^3 * J with b = min(d_o, D) and J = 2.5/(d_o/D)^2 - 2.0 >= 0.5 (6.10.11.1.3-1/-2)

  • I_t2 = D^4 * rho_t^1.3 / 40 * (Fyw/E)^1.5 (6.10.11.1.3-3), with rho_t = max(Fyw/Fcrs, 1.0) and Fcrs = 0.31 E/(b_t/t_p)^2 <= Fys (6.10.11.1.3-4)

Web shear buckling only (tension_field=False): I_t1 governs. When the web’s postbuckling (tension-field) resistance is relied on and I_t2 > I_t1, the requirement rises toward I_t2 — this implementation conservatively requires I_t2 on that path (the spec permits a shear-demand interpolation); validate_against_brr is set for the tension-field path.

civilpy.structural.aashto.lrfd.transverse_stiffener_width(b_t: float, t_p: float, d_web: float, b_f: float) CheckResult[source]

Transverse-stiffener projecting-width limits (6.10.11.1.2): b_t >= 2.0 + D/30 (6.10.11.1.2-1) and 16*t_p >= b_t >= b_f/4 (6.10.11.1.2-2), with b_f the full width of the widest compression flange in the field section. The governing (minimum) margin is the reported ratio.

civilpy.structural.aashto.lrfd.volume_factor_cv(d: float, b: float, l_ft: float, southern_pine: bool = False) float[source]

Cv for glued-laminated timber in flexure (8.4.4.5): [(12/d)*(5.125/b)*(21/L)]^a <= 1.0, a = 0.05 for Southern Pine and 0.10 for all other species. d/b in inches, l_ft in ft. Cv and CL are not applied simultaneously — use the smaller.

civilpy.structural.aashto.lrfd.web_bend_buckling(d_web: float, t_w: float, d_c: float, f_yc: float, f_yw: float, r_h: float = 1.0) CheckResult[source]

Nominal web bend-buckling resistance (6.10.1.9.1-1): Fcrw = 0.9*E*k/(D/tw)^2 with k = 9/(Dc/D)^2, capped at min(Rh*Fyc, Fyw/0.7). capacity holds Fcrw (ksi).

civilpy.structural.aashto.lrfd.web_load_shedding_factor(d_c: float, t_w: float, b_fc: float, t_fc: float, f_yc: float) CheckResult[source]

Web load-shedding factor Rb (6.10.1.10.2): 1.0 for compact and noncompact webs (2*Dc/tw <= lambda_rw = 5.7*sqrt(E/Fyc)); slender webs shed stress to the compression flange per -3: Rb = 1 - awc/(1200 + 300*awc) * (2*Dc/tw - lambda_rw) <= 1.0. capacity holds Rb.

civilpy.structural.aashto.lrfd.web_plastification_factors(d_c: float, d_cp: float, t_w: float, m_p: float, m_yc: float, m_yt: float, f_yc: float, r_h: float = 1.0) CheckResult[source]

Web plastification factors Rpc and Rpt (A6.2).

Compact webs (2*Dcp/tw within lambda_pw(Dcp), A6.2.1) reach the full plastic moment: Rpc = Mp/Myc, Rpt = Mp/Myt. Noncompact webs (A6.2.2) interpolate between Rh and Mp/My. d_c/d_cp are the elastic and plastic depths of web in compression (in). capacity holds Rpc; Rpt and the slenderness parameters are in details.

civilpy.structural.aashto.lrfd.web_shear_resistance(d_web: float, t_w: float, f_yw: float, v_u: float | None = None, d_o: float | None = None, tension_field: bool = False, b_fc: float | None = None, t_fc: float | None = None, b_ft: float | None = None, t_ft: float | None = None) CheckResult[source]

Nominal web shear resistance Vn (6.10.9).

Unstiffened webs (d_o is None): Vn = C*Vp (6.10.9.2-1). Stiffened interior panels with tension_field=True use 6.10.9.3.2-2, downgraded to 6.10.9.3.2-8 when the panel fails the flange-proportion limit 2*D*tw/(bfc*tfc + bft*tft) <= 2.5. d_web is the web depth D (in), d_o the transverse stiffener spacing (in), v_u the factored shear demand (kip).

civilpy.structural.aashto.lrfd.web_splice_design_forces(v_r_web: float, n_bolts: int, m_u: float = 0.0, m_flange: float = 0.0, moment_arm: float | None = None) WebSpliceForces[source]

Web splice design forces (6.13.6.1.3c, 8th Ed. method).

v_r_web is the smaller factored shear resistance phi_v*Vn of the webs on either side of the splice (6.10.9) — the web splice is designed for the full web capacity, not the applied shear. When the factored moment m_u (kip-in) exceeds the moment the flange splices can carry m_flange, the excess is resisted by a horizontal force couple in the web: Hw = (|Mu| - Mrf)/arm. Each of the n_bolts (one side of the splice) sees the vector sum of Vuw/Nb and Hw/Nb.