Function bodies 335 total
detect_water_crossing function · python · L643-L670 (28 LOC)src/nlb/tools/site_recon.py
def detect_water_crossing(description: str) -> ScourProfile:
"""Parse bridge description for water-crossing keywords.
Per AASHTO §2.6.4.4.2 and FHWA HEC-18: any bridge over or near a water
body requires scour evaluation. Design flood = Q100 (100-yr return
period); extreme check flood = Q500 (500-yr return period).
The foundation tool will use these flags to:
- Remove soil springs above the computed scour depth
- Evaluate foundation capacity at scoured condition
- Apply the Extreme Event II load combination
Args:
description: Natural language bridge description from the user.
Returns:
ScourProfile with water_crossing flag and flood return periods.
"""
matches = _WATER_KEYWORDS.findall(description)
unique_matches = sorted(set(m.lower() for m in matches))
water_crossing = len(matches) > 0
return ScourProfile(
water_crossing=water_crossing,
design_flood="Q100" if water_crossing else Nonerun_site_recon function · python · L677-L840 (164 LOC)src/nlb/tools/site_recon.py
def run_site_recon(
lat: float,
lon: float,
description: str = "",
site_class: str = "D",
exposure: str = _DEFAULT_EXPOSURE,
noaa_token: Optional[str] = None,
) -> SiteProfile:
"""Run the full site reconnaissance pipeline for a bridge project.
This is the canonical entry point. It:
1. Reverse-geocodes the coordinates → state, county, climate zone
2. Fetches USGS seismic hazard parameters
3. Determines wind speed from state lookup
4. Determines thermal range from NOAA or state climate zone
5. Parses description for water-crossing / scour flag
6. Looks up frost depth by state
7. Assembles and returns a complete :class:`SiteProfile`
The function **never raises** — all failures are caught, logged, and
filled with conservative defaults. Check `profile.warnings` to see
which data sources fell back to defaults.
Args:
lat: Latitude (WGS-84 decimal degrees).
lon: LongitColumnShape class · python · L68-L70 (3 LOC)src/nlb/tools/substructure.py
class ColumnShape(str, Enum):
CIRCULAR = "circular"
RECTANGULAR = "rectangular"SubstructureType class · python · L73-L79 (7 LOC)src/nlb/tools/substructure.py
class SubstructureType(str, Enum):
SINGLE_COLUMN = "single_column"
MULTI_COLUMN_BENT = "multi_column_bent"
WALL_PIER = "wall_pier"
PILE_BENT = "pile_bent"
INTEGRAL_ABUTMENT = "integral_abutment"
SEAT_ABUTMENT = "seat_abutment"ColumnConfig class · python · L87-L129 (43 LOC)src/nlb/tools/substructure.py
class ColumnConfig:
"""Column definition.
Attributes:
shape: "circular" or "rectangular".
diameter_in: Diameter for circular columns (inches).
width_in: Width for rectangular columns (inches, along bridge).
depth_in: Depth for rectangular columns (inches, transverse).
height_ft: Column clear height (ft). Converted internally to inches.
fc_ksi: Concrete compressive strength (ksi).
fy_ksi: Longitudinal rebar yield strength (ksi).
num_bars: Number of longitudinal bars.
bar_size: Bar designation, e.g. "#8".
cover_in: Clear cover to hoops/spirals (inches).
fy_transverse_ksi: Transverse steel yield strength (ksi).
rho_s: Volumetric ratio of transverse reinforcement.
cracked: Whether to flag for cracked section stiffness (0.5 EIg).
"""
shape: str = "circular"
diameter_in: float = 48.0
width_in: float = 48.0
depth_in: float = 48.0
height_ft: float = 20.0
CapBeamConfig class · python · L133-L155 (23 LOC)src/nlb/tools/substructure.py
class CapBeamConfig:
"""Cap beam definition.
Attributes:
width_in: Cap width along bridge (inches).
depth_in: Cap depth (inches).
fc_ksi: Concrete f'c (ksi).
fy_ksi: Rebar yield strength (ksi).
num_bars_top: Top bars count.
num_bars_bot: Bottom bars count.
bar_size: Bar designation.
cover_in: Clear cover (inches).
cracked: Whether to flag for cracked stiffness (0.35 EIg).
"""
width_in: float = 60.0
depth_in: float = 48.0
fc_ksi: float = 4.0
fy_ksi: float = 60.0
num_bars_top: int = 8
num_bars_bot: int = 8
bar_size: str = "#9"
cover_in: float = 2.0
cracked: bool = TrueWallPierConfig class · python · L159-L200 (42 LOC)src/nlb/tools/substructure.py
class WallPierConfig:
"""Wall pier definition.
Attributes:
height_ft: Pier height (ft).
width_in: Width along bridge axis (inches).
thickness_in: Thickness transverse to bridge (inches).
fc_ksi: Concrete f'c (ksi).
fy_ksi: Rebar yield strength (ksi).
num_bars_face: Bars per face (width direction).
bar_size: Bar designation.
cover_in: Clear cover (inches).
fy_transverse_ksi: Transverse steel yield (ksi).
rho_s: Volumetric transverse steel ratio.
"""
height_ft: float = 25.0
width_in: float = 240.0 # 20 ft
thickness_in: float = 48.0 # 4 ft
fc_ksi: float = 4.0
fy_ksi: float = 60.0
num_bars_face: int = 20
bar_size: str = "#9"
cover_in: float = 2.0
fy_transverse_ksi: float = 60.0
rho_s: float = 0.006
@property
def height_in(self) -> float:
return self.height_ft * FT_TO_IN
@property
def bar_area(self) -> float:
return REBAR_AROpen data scored by Repobility · https://repobility.com
PileBentConfig class · python · L204-L222 (19 LOC)src/nlb/tools/substructure.py
class PileBentConfig:
"""Pile bent configuration.
Attributes:
pile_type: "HP", "pipe", "precast" (string tag for downstream).
pile_diameter_in: Pile outer diameter or depth (inches).
pile_wall_thickness_in: For pipe piles (inches).
pile_count: Number of piles.
spacing_ft: Center-to-center pile spacing (ft).
free_height_ft: Height above ground to cap bottom (ft).
cap: Cap beam configuration.
"""
pile_type: str = "HP"
pile_diameter_in: float = 14.0
pile_wall_thickness_in: float = 0.5
pile_count: int = 5
spacing_ft: float = 6.0
free_height_ft: float = 10.0
cap: CapBeamConfig = field(default_factory=CapBeamConfig)IntegralAbutmentConfig class · python · L226-L250 (25 LOC)src/nlb/tools/substructure.py
class IntegralAbutmentConfig:
"""Integral abutment configuration.
Attributes:
backwall_height_ft: Height from seat to top of backwall (ft).
seat_width_in: Seat width along bridge (inches).
wingwall_length_ft: Wingwall length (ft).
skew_deg: Skew angle (degrees).
backfill_gamma_pcf: Backfill unit weight (pcf).
backfill_phi_deg: Backfill friction angle (degrees).
fc_ksi: Concrete f'c for backwall (ksi).
num_springs: Number of backfill springs behind backwall.
"""
backwall_height_ft: float = 6.0
seat_width_in: float = 36.0
wingwall_length_ft: float = 15.0
skew_deg: float = 0.0
backfill_gamma_pcf: float = 120.0
backfill_phi_deg: float = 34.0
fc_ksi: float = 4.0
num_springs: int = 5
@property
def backwall_height_in(self) -> float:
return self.backwall_height_ft * FT_TO_INSeatAbutmentConfig class · python · L254-L270 (17 LOC)src/nlb/tools/substructure.py
class SeatAbutmentConfig:
"""Stub/seat abutment configuration.
Attributes:
seat_width_in: Seat width along bridge (inches).
backwall_height_ft: Height above seat (ft).
bearing_locations_in: Transverse locations for bearings (inches from CL).
fc_ksi: Concrete f'c (ksi).
"""
seat_width_in: float = 36.0
backwall_height_ft: float = 5.0
bearing_locations_in: list[float] = field(default_factory=lambda: [-36.0, 36.0])
fc_ksi: float = 4.0
@property
def backwall_height_in(self) -> float:
return self.backwall_height_ft * FT_TO_INSubstructureModel class · python · L278-L304 (27 LOC)src/nlb/tools/substructure.py
class SubstructureModel:
"""Complete substructure model output.
All tags are integers for direct OpenSees use.
All coordinates in kip-inch-second.
"""
nodes: list[dict] = field(default_factory=list)
elements: list[dict] = field(default_factory=list)
sections: list[dict] = field(default_factory=list)
materials: list[dict] = field(default_factory=list)
top_nodes: list[int] = field(default_factory=list)
base_nodes: list[int] = field(default_factory=list)
cap_nodes: list[int] = field(default_factory=list)
plastic_hinge_elements: list[int] = field(default_factory=list)
constraints: list[dict] = field(default_factory=list)
springs: list[dict] = field(default_factory=list)
warnings: list[str] = field(default_factory=list)
substructure_type: str = ""
cracked_stiffness: dict = field(default_factory=dict)
def summary(self) -> str:
return (
f"SubstructureModel ({self.substructure_type}): "
f"summary method · python · L298-L304 (7 LOC)src/nlb/tools/substructure.py
def summary(self) -> str:
return (
f"SubstructureModel ({self.substructure_type}): "
f"{len(self.nodes)} nodes, {len(self.elements)} elements, "
f"{len(self.sections)} sections, {len(self.materials)} materials | "
f"top={self.top_nodes}, base={self.base_nodes}"
)TagAllocator class · python · L311-L328 (18 LOC)src/nlb/tools/substructure.py
class TagAllocator:
"""Sequential tag allocator for OpenSees objects."""
def __init__(self, start: int = 1):
self._next = start
def next(self, count: int = 1) -> int | list[int]:
if count == 1:
tag = self._next
self._next += 1
return tag
tags = list(range(self._next, self._next + count))
self._next += count
return tags
@property
def current(self) -> int:
return self._nextnext method · python · L317-L324 (8 LOC)src/nlb/tools/substructure.py
def next(self, count: int = 1) -> int | list[int]:
if count == 1:
tag = self._next
self._next += 1
return tag
tags = list(range(self._next, self._next + count))
self._next += count
return tagsplastic_hinge_length function · python · L335-L352 (18 LOC)src/nlb/tools/substructure.py
def plastic_hinge_length(L_in: float, fy_ksi: float, db_in: float) -> float:
"""Compute plastic hinge length per Paulay & Priestley (1992).
Lp = 0.08L + 0.15 * fy * db
Args:
L_in: Member clear height (inches).
fy_ksi: Rebar yield strength (ksi).
db_in: Longitudinal bar diameter (inches).
Returns:
Plastic hinge length Lp (inches).
Reference:
Paulay & Priestley (1992), Eq. 4.30.
Caltrans SDC §5.3.4.
"""
return 0.08 * L_in + 0.15 * fy_ksi * db_inMethodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
_column_mesh_lengths function · python · L359-L410 (52 LOC)src/nlb/tools/substructure.py
def _column_mesh_lengths(
height_in: float,
Lp: float,
min_elements: int = 6,
min_ph_elements: int = 2,
) -> tuple[list[float], list[bool]]:
"""Generate element lengths along column height with plastic hinge refinement.
Places refined elements at top and bottom plastic hinge zones,
uniform elements in the middle elastic region.
Args:
height_in: Total column height (inches).
Lp: Plastic hinge length (inches).
min_elements: Minimum total elements. Default: 6.
min_ph_elements: Minimum elements per plastic hinge zone. Default: 2.
Returns:
Tuple of (lengths, is_ph) where:
lengths: List of element lengths (inches).
is_ph: List of booleans indicating plastic hinge zone.
"""
# Clamp Lp so two PH zones don't exceed column height
Lp = min(Lp, height_in * 0.4)
# Elements in each PH zone
ph_len = Lp / min_ph_elements
# Elastic region
elastic_len = height_in - 2.0 * L_mander_confinement function · python · L417-L439 (23 LOC)src/nlb/tools/substructure.py
def _mander_confinement(
fc_ksi: float,
fy_trans_ksi: float,
rho_s: float,
config: str = "circular",
) -> tuple[float, float, float]:
"""Compute confined concrete parameters per Mander et al. (1988).
Returns (fcc, ecc, ecu).
"""
ke = 0.95 if config == "circular" else 0.75
fl = 0.5 * ke * rho_s * fy_trans_ksi
ratio = fl / fc_ksi if fc_ksi > 0 else 0
fcc = fc_ksi * (-1.254 + 2.254 * math.sqrt(1.0 + 7.94 * ratio) - 2.0 * ratio)
eps_co = 0.002
ecc = eps_co * (1.0 + 5.0 * (fcc / fc_ksi - 1.0))
eps_su = 0.09 # Grade 60 ultimate strain
ecu = 0.004 + 1.4 * rho_s * fy_trans_ksi * eps_su / fcc
return fcc, ecc, ecu_backfill_spring_params function · python · L446-L504 (59 LOC)src/nlb/tools/substructure.py
def _backfill_spring_params(
height_in: float,
width_in: float,
gamma_pci: float,
phi_deg: float,
num_springs: int,
) -> list[dict]:
"""Compute nonlinear backfill spring parameters for integral abutments.
Uses log-spiral passive pressure theory (simplified Rankine Kp)
distributed over the backwall height.
Each spring uses a HyperbolicGap-like formulation:
F = Fult * y / (y + y_ref) for y > 0 (compression only)
Args:
height_in: Backwall height (inches).
width_in: Backwall width (inches, tributary per spring).
gamma_pci: Backfill unit weight (kip/in³).
phi_deg: Backfill friction angle (degrees).
num_springs: Number of springs.
Returns:
List of dicts with {depth_in, Fult, y50, Kini, spring_type}.
"""
phi_rad = math.radians(phi_deg)
# Rankine passive pressure coefficient
Kp = (1.0 + math.sin(phi_rad)) / (1.0 - math.sin(phi_rad))
trib_height = height_in / num_springsbuild_single_column function · python · L511-L653 (143 LOC)src/nlb/tools/substructure.py
def build_single_column(
col: ColumnConfig,
base_x: float = 0.0,
base_y: float = 0.0,
base_z: float = 0.0,
tag_start: int = 1,
) -> SubstructureModel:
"""Build a single column substructure model.
Creates a dispBeamColumn column with:
- Confined core + unconfined cover (Mander model)
- Steel02 reinforcing steel
- PDelta geometric transform
- Plastic hinge zone mesh refinement
Args:
col: ColumnConfig with column parameters.
base_x, base_y, base_z: Base node coordinates (inches).
tag_start: Starting tag for all OpenSees objects.
Returns:
SubstructureModel with nodes, elements, sections, materials.
"""
tags = TagAllocator(tag_start)
model = SubstructureModel(substructure_type="single_column")
height = col.height_in
config = "circular" if col.shape == "circular" else "rectangular"
# --- Materials ---
# Unconfined concrete (cover)
mat_unconf = tags.next()
model.materiabuild_multi_column_bent function · python · L656-L888 (233 LOC)src/nlb/tools/substructure.py
def build_multi_column_bent(
num_columns: int,
spacing_ft: float,
col: ColumnConfig,
cap: CapBeamConfig,
base_x: float = 0.0,
base_y: float = 0.0,
base_z: float = 0.0,
tag_start: int = 1,
) -> SubstructureModel:
"""Build a multi-column bent with cap beam.
Creates multiple columns at regular spacing with a cap beam connecting
their tops. Rigid offsets at column-cap connections if cap depth exceeds
column dimension.
Args:
num_columns: Number of columns.
spacing_ft: Column center-to-center spacing (ft).
col: Column configuration (shared by all columns).
cap: Cap beam configuration.
base_x, base_y, base_z: Origin (left column base).
tag_start: Starting tag.
Returns:
SubstructureModel.
"""
tags = TagAllocator(tag_start)
model = SubstructureModel(substructure_type="multi_column_bent")
spacing_in = spacing_ft * FT_TO_IN
height = col.height_in
config = "cibuild_wall_pier function · python · L891-L995 (105 LOC)src/nlb/tools/substructure.py
def build_wall_pier(
wall: WallPierConfig,
base_x: float = 0.0,
base_y: float = 0.0,
base_z: float = 0.0,
tag_start: int = 1,
) -> SubstructureModel:
"""Build a solid wall pier model.
Models as dispBeamColumn with rectangular fiber section.
Checks for wall slenderness (h/t > 25).
Args:
wall: WallPierConfig.
base_x, base_y, base_z: Base coordinates.
tag_start: Starting tag.
Returns:
SubstructureModel.
"""
tags = TagAllocator(tag_start)
model = SubstructureModel(substructure_type="wall_pier")
height = wall.height_in
config = "rectangular"
# --- Materials ---
mat_unconf = tags.next()
model.materials.append({
"tag": mat_unconf, "type": "Concrete01",
"name": "unconfined_concrete", "fc_ksi": wall.fc_ksi,
})
fcc, ecc, ecu = _mander_confinement(
wall.fc_ksi, wall.fy_transverse_ksi, wall.rho_s, config,
)
mat_conf = tags.next()
model.materials.build_pile_bent function · python · L998-L1163 (166 LOC)src/nlb/tools/substructure.py
def build_pile_bent(
config: PileBentConfig,
base_x: float = 0.0,
base_y: float = 0.0,
base_z: float = 0.0,
tag_start: int = 1,
) -> SubstructureModel:
"""Build a pile bent with cap beam.
Piles extend above ground (free height) with a cap beam connecting tops.
Pile bases are output as base_nodes for connection to foundation springs.
Args:
config: PileBentConfig.
base_x, base_y, base_z: Origin (first pile base).
tag_start: Starting tag.
Returns:
SubstructureModel.
"""
tags = TagAllocator(tag_start)
model = SubstructureModel(substructure_type="pile_bent")
spacing_in = config.spacing_ft * FT_TO_IN
free_height_in = config.free_height_ft * FT_TO_IN
cap = config.cap
# --- Materials for piles (structural steel for HP/pipe) ---
if config.pile_type in ("HP", "pipe"):
mat_pile = tags.next()
model.materials.append({
"tag": mat_pile, "type": "Steel02",
build_integral_abutment function · python · L1166-L1280 (115 LOC)src/nlb/tools/substructure.py
def build_integral_abutment(
config: IntegralAbutmentConfig,
base_x: float = 0.0,
base_y: float = 0.0,
base_z: float = 0.0,
tag_start: int = 1,
) -> SubstructureModel:
"""Build an integral abutment with backfill springs.
Monolithic connection between superstructure and abutment.
Passive pressure backfill springs model soil-structure interaction.
Args:
config: IntegralAbutmentConfig.
base_x, base_y, base_z: Origin.
tag_start: Starting tag.
Returns:
SubstructureModel with backfill springs.
"""
tags = TagAllocator(tag_start)
model = SubstructureModel(substructure_type="integral_abutment")
height = config.backwall_height_in
gamma_pci = config.backfill_gamma_pcf * PCF_TO_PCI
# --- Base node (bottom of abutment) ---
base_node = tags.next()
model.nodes.append({"tag": base_node, "x": base_x, "y": base_y, "z": base_z})
model.base_nodes.append(base_node)
# --- Top node (top of baWant fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
build_seat_abutment function · python · L1283-L1362 (80 LOC)src/nlb/tools/substructure.py
def build_seat_abutment(
config: SeatAbutmentConfig,
base_x: float = 0.0,
base_y: float = 0.0,
base_z: float = 0.0,
tag_start: int = 1,
) -> SubstructureModel:
"""Build a stub/seat abutment.
Conventional abutment with discrete bearing seats. No backfill springs
(joint separates backwall from bridge).
Args:
config: SeatAbutmentConfig.
base_x, base_y, base_z: Origin.
tag_start: Starting tag.
Returns:
SubstructureModel with bearing seat nodes.
"""
tags = TagAllocator(tag_start)
model = SubstructureModel(substructure_type="seat_abutment")
height = config.backwall_height_in
# --- Base node ---
base_node = tags.next()
model.nodes.append({"tag": base_node, "x": base_x, "y": base_y, "z": base_z})
model.base_nodes.append(base_node)
# --- Seat level node (top of stem) ---
seat_y = base_y + height
seat_node = tags.next()
model.nodes.append({"tag": seat_node, "x": base_x, "create_substructure function · python · L1369-L1478 (110 LOC)src/nlb/tools/substructure.py
def create_substructure(
sub_type: str,
**kwargs: Any,
) -> SubstructureModel:
"""Create a substructure model from type string and parameters.
This is the main entry point for the NLB pipeline.
Args:
sub_type: One of SubstructureType values.
**kwargs: Parameters forwarded to the specific builder.
Returns:
SubstructureModel.
Raises:
ValueError: If sub_type is not recognized.
"""
sub_type = sub_type.lower().replace(" ", "_").replace("-", "_")
if sub_type == "single_column":
col = kwargs.get("column", ColumnConfig(**{
k: v for k, v in kwargs.items()
if k in ColumnConfig.__dataclass_fields__
}))
return build_single_column(
col=col,
base_x=kwargs.get("base_x", 0.0),
base_y=kwargs.get("base_y", 0.0),
base_z=kwargs.get("base_z", 0.0),
tag_start=kwargs.get("tag_start", 1),
)
elif sub_type == "multi_SuperstructureModel class · python · L49-L80 (32 LOC)src/nlb/tools/superstructure.py
class SuperstructureModel:
"""Complete superstructure model output.
Contains all nodes, elements, sections, and materials needed to
build an OpenSees model of the bridge superstructure.
Attributes:
nodes: List of node dicts [{tag, x, y, z}, ...]
elements: List of element dicts [{tag, type, nodes, section, transform}, ...]
sections: List of section dicts [{tag, type, params}, ...]
materials: List of material dicts [{tag, type, params}, ...]
diaphragms: Transverse connectivity elements
span_lengths: Span lengths in feet (as input)
girder_lines: Number of girder lines modeled
deck_width: Out-to-out deck width (ft)
support_nodes: Node tags at abutments/piers (for bearing connection)
midspan_nodes: Node tags at midspan (for max moment check)
continuity: 'continuous' or 'simple' at each support
transforms: Geometric transformation dTagManager class · python · L87-L107 (21 LOC)src/nlb/tools/superstructure.py
class TagManager:
"""Manages unique tags for nodes, elements, sections, materials, transforms."""
def __init__(self, base: int = 1):
self._counters = {
'node': base,
'element': base,
'section': base,
'material': base,
'transform': base,
}
def next(self, kind: str) -> int:
tag = self._counters[kind]
self._counters[kind] += 1
return tag
def next_n(self, kind: str, n: int) -> List[int]:
tags = list(range(self._counters[kind], self._counters[kind] + n))
self._counters[kind] += n
return tags__init__ method · python · L90-L97 (8 LOC)src/nlb/tools/superstructure.py
def __init__(self, base: int = 1):
self._counters = {
'node': base,
'element': base,
'section': base,
'material': base,
'transform': base,
}next method · python · L99-L102 (4 LOC)src/nlb/tools/superstructure.py
def next(self, kind: str) -> int:
tag = self._counters[kind]
self._counters[kind] += 1
return tagnext_n method · python · L104-L107 (4 LOC)src/nlb/tools/superstructure.py
def next_n(self, kind: str, n: int) -> List[int]:
tags = list(range(self._counters[kind], self._counters[kind] + n))
self._counters[kind] += n
return tagsselect_transform_type function · python · L114-L136 (23 LOC)src/nlb/tools/superstructure.py
def select_transform_type(span_ft: float) -> str:
"""Select geometric transformation type based on span length.
Per engineering practice:
- < 100 ft: Linear (P-delta effects negligible)
- 100-200 ft: PDelta (second-order effects significant)
- > 200 ft: Corotational (large displacement formulation)
Args:
span_ft: Span length in feet.
Returns:
Transform type string: 'Linear', 'PDelta', or 'Corotational'.
Reference:
AASHTO LRFD C4.5.3.2.2b: When to include P-delta effects.
"""
if span_ft > 200.0:
return 'Corotational'
elif span_ft >= 100.0:
return 'PDelta'
else:
return 'Linear'Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
compute_mesh_density function · python · L139-L159 (21 LOC)src/nlb/tools/superstructure.py
def compute_mesh_density(span_ft: float) -> int:
"""Compute number of elements per span.
Minimum 10 elements per span, 20 for spans > 100 ft.
Ensures nodes at tenth-points and midspan.
Args:
span_ft: Span length in feet.
Returns:
Number of elements per span (always divisible by 10 for tenth-points).
Reference:
General FEA best practice for beam models.
"""
if span_ft > 100.0:
base = 20
else:
base = 10
# Round up to nearest 10 for clean tenth-point spacing
return max(base, 10 * math.ceil(base / 10))effective_slab_width function · python · L162-L193 (32 LOC)src/nlb/tools/superstructure.py
def effective_slab_width(span_ft: float, girder_spacing_ft: float,
slab_thickness_in: float,
top_flange_width_in: float) -> float:
"""Compute effective slab width per AASHTO LRFD 4.6.2.6.1.
For interior girders, effective width is the minimum of:
1. One-quarter of the effective span length
2. Center-to-center girder spacing
3. 12 × slab thickness + max(top flange width, 0.5 × web thickness)
Simplified: uses top flange width for the third criterion.
Args:
span_ft: Effective span length (ft).
girder_spacing_ft: Center-to-center girder spacing (ft).
slab_thickness_in: Slab thickness (inches).
top_flange_width_in: Top flange width (inches).
Returns:
Effective slab width in inches.
Reference:
AASHTO LRFD 4.6.2.6.1: Effective Flange Width for Interior Beams.
"""
span_in = span_ft * FT_TO_IN
spacing_in = girder_s_span_node_positions function · python · L196-L208 (13 LOC)src/nlb/tools/superstructure.py
def _span_node_positions(span_in: float, n_elements: int) -> List[float]:
"""Generate node positions along a span (relative to span start).
Returns positions that include tenth-points and midspan.
Args:
span_in: Span length in inches.
n_elements: Number of elements.
Returns:
List of positions from 0 to span_in (n_elements + 1 values).
"""
return [i * span_in / n_elements for i in range(n_elements + 1)]_diaphragm_positions function · python · L211-L227 (17 LOC)src/nlb/tools/superstructure.py
def _diaphragm_positions(span_in: float) -> List[float]:
"""Compute diaphragm locations within a span.
Diaphragms at supports and at third-points minimum (AASHTO 6.7.4).
Returns positions relative to span start (excluding supports themselves,
which are handled separately).
Args:
span_in: Span length in inches.
Returns:
List of diaphragm positions (relative to span start).
Reference:
AASHTO LRFD 6.7.4: Diaphragms and Cross-Frames.
"""
return [span_in / 3.0, 2.0 * span_in / 3.0]create_superstructure function · python · L234-L418 (185 LOC)src/nlb/tools/superstructure.py
def create_superstructure(
bridge_type: str,
span_lengths_ft: List[float],
*,
# Common parameters
num_girders: int = 5,
girder_spacing_ft: float = 8.0,
deck_width_ft: Optional[float] = None,
slab_thickness_in: float = 8.0,
continuity: Optional[List[str]] = None,
skew_angle: float = 0.0,
# Steel plate girder parameters
girder_depth_in: float = 48.0,
top_flange_width_in: float = 16.0,
top_flange_thick_in: float = 1.0,
bot_flange_width_in: float = 18.0,
bot_flange_thick_in: float = 1.5,
web_thickness_in: float = 0.5625,
haunch_in: float = 2.0,
fy_ksi: float = 50.0,
fc_ksi: float = 4.0,
# Prestressed girder parameters
girder_type: Optional[str] = None,
strand_pattern: Optional[List[Tuple[float, int]]] = None,
strand_area: float = 0.217,
# Box girder parameters
num_cells: int = 3,
box_depth_in: float = 72.0,
top_slab_thick_in: float = 9.0,
bot_slab_thick_in: float = 6.0,
b_generate_grillage_nodes function · python · L425-L516 (92 LOC)src/nlb/tools/superstructure.py
def _generate_grillage_nodes(
span_lengths_ft: List[float],
num_girders: int,
girder_spacing_ft: float,
skew_angle: float,
tags: TagManager,
elevation: float = 0.0,
) -> Tuple[List[Dict], Dict[Tuple[int, int], int], List[int], List[int]]:
"""Generate nodes for a multi-girder grillage model.
Creates nodes for all girder lines across all spans. Nodes are placed
at element boundaries determined by mesh density.
Args:
span_lengths_ft: Span lengths (ft).
num_girders: Number of girder lines.
girder_spacing_ft: Spacing between girders (ft).
skew_angle: Skew angle (degrees).
tags: Tag manager for unique IDs.
elevation: Y-coordinate for all nodes (inches).
Returns:
Tuple of:
- nodes: list of node dicts
- node_map: {(girder_idx, longitudinal_idx): node_tag}
- support_positions: longitudinal indices at supports
- mids_generate_longitudinal_elements function · python · L519-L555 (37 LOC)src/nlb/tools/superstructure.py
def _generate_longitudinal_elements(
node_map: Dict[Tuple[int, int], int],
num_girders: int,
n_long: int,
section_tag: int,
transform_tag: int,
tags: TagManager,
element_type: str = 'dispBeamColumn',
) -> List[Dict]:
"""Generate longitudinal beam-column elements for each girder line.
Args:
node_map: {(girder_idx, long_idx): node_tag}
num_girders: Number of girder lines.
n_long: Number of longitudinal node positions.
section_tag: Section tag for all elements.
transform_tag: Geometric transformation tag.
tags: Tag manager.
element_type: Element type string.
Returns:
List of element dicts.
"""
elements = []
for g_idx in range(num_girders):
for l_idx in range(n_long - 1):
n_i = node_map[(g_idx, l_idx)]
n_j = node_map[(g_idx, l_idx + 1)]
e_tag = tags.next('element')
elements.append({
_generate_diaphragms function · python · L558-L619 (62 LOC)src/nlb/tools/superstructure.py
def _generate_diaphragms(
node_map: Dict[Tuple[int, int], int],
num_girders: int,
n_long: int,
span_lengths_ft: List[float],
tags: TagManager,
diaphragm_section_tag: int,
diaphragm_transform_tag: int,
support_long_indices: List[int],
) -> List[Dict]:
"""Generate transverse diaphragm/cross-frame elements.
Places diaphragms at supports and span third-points.
Args:
node_map: Node lookup.
num_girders: Number of girder lines.
n_long: Number of longitudinal positions.
span_lengths_ft: Span lengths.
tags: Tag manager.
diaphragm_section_tag: Section for diaphragm elements.
diaphragm_transform_tag: Transform for diaphragms.
support_long_indices: Longitudinal indices at supports.
Returns:
List of diaphragm element dicts.
Reference:
AASHTO LRFD 6.7.4: Diaphragms and Cross-Frames.
"""
diaOpen data scored by Repobility · https://repobility.com
_build_steel_plate_girder function · python · L626-L793 (168 LOC)src/nlb/tools/superstructure.py
def _build_steel_plate_girder(
bridge_type: str,
span_lengths_ft: List[float],
num_girders: int,
girder_spacing_ft: float,
deck_width_ft: float,
slab_thickness_in: float,
continuity: List[str],
skew_angle: float,
girder_depth_in: float,
top_flange_width_in: float,
top_flange_thick_in: float,
bot_flange_width_in: float,
bot_flange_thick_in: float,
web_thickness_in: float,
haunch_in: float,
fy_ksi: float,
fc_ksi: float,
tag_base: int = 1,
**kwargs,
) -> SuperstructureModel:
"""Build steel plate girder superstructure (composite or non-composite).
Models each girder line as a series of dispBeamColumn elements with
fiber sections. Transverse connectivity via diaphragm elements.
For composite: uses composite_section() with effective slab width.
For non-composite: uses steel_i_section() with deck mass as nodal mass.
Reference:
AASHTO LRFD 6.10: I-Section Flexural Members.
AAS_build_prestressed_i_girder function · python · L800-L938 (139 LOC)src/nlb/tools/superstructure.py
def _build_prestressed_i_girder(
span_lengths_ft: List[float],
num_girders: int,
girder_spacing_ft: float,
deck_width_ft: float,
slab_thickness_in: float,
continuity: List[str],
skew_angle: float,
girder_type: Optional[str],
strand_pattern: Optional[List[Tuple[float, int]]],
strand_area: float,
fc_ksi: float,
tag_base: int = 1,
**kwargs,
) -> SuperstructureModel:
"""Build prestressed concrete I-girder superstructure.
Simple-span precast girders with composite deck. Each girder line modeled
as dispBeamColumn with prestressed_i_section fiber section.
Args:
girder_type: Key into GIRDER_LIBRARY (e.g., 'BT_72', 'AASHTO_IV').
strand_pattern: List of (y_from_bottom_in, num_strands) tuples.
Reference:
AASHTO LRFD 5.9: Prestressed Concrete.
PCI Bridge Design Manual, 3rd Edition.
"""
from ..opensees.sections import GIRDER_LIBRARY
tags = TagManager(tag_base)
model = Superstr_build_cip_box_girder function · python · L945-L1037 (93 LOC)src/nlb/tools/superstructure.py
def _build_cip_box_girder(
span_lengths_ft: List[float],
num_girders: int,
girder_spacing_ft: float,
deck_width_ft: float,
slab_thickness_in: float,
continuity: List[str],
skew_angle: float,
num_cells: int,
box_depth_in: float,
top_slab_thick_in: float,
bot_slab_thick_in: float,
box_web_thick_in: float,
box_top_width_ft: Optional[float],
box_bot_width_ft: Optional[float],
fc_ksi: float,
tag_base: int = 1,
**kwargs,
) -> SuperstructureModel:
"""Build CIP concrete box girder superstructure.
Single box with multiple cells modeled as a single spine with the
full box cross-section. Suitable for continuous post-tensioned bridges.
Reference:
AASHTO LRFD 5.12.2: Segmental Concrete Bridges.
AASHTO LRFD 4.6.2.6.2: Box Girder Effective Width.
"""
tags = TagManager(tag_base)
model = SuperstructureModel()
model.span_lengths = list(span_lengths_ft)
model.girder_lines = 1 # spine_build_segmental_box_girder function · python · L1044-L1178 (135 LOC)src/nlb/tools/superstructure.py
def _build_segmental_box_girder(
span_lengths_ft: List[float],
segment_length_ft: float,
num_cells: int,
box_depth_in: float,
top_slab_thick_in: float,
bot_slab_thick_in: float,
box_web_thick_in: float,
box_top_width_ft: Optional[float],
box_bot_width_ft: Optional[float],
deck_width_ft: float,
continuity: List[str],
fc_ksi: float,
skew_angle: float,
tag_base: int = 1,
**kwargs,
) -> SuperstructureModel:
"""Build prestressed segmental box girder superstructure.
Similar to CIP box but with segment joints modeled as zero-length
elements with reduced stiffness (compression-only + friction).
Segment joints are placed at regular intervals per segment_length_ft.
Reference:
AASHTO LRFD 5.12.2: Segmental Concrete Bridges.
AASHTO LRFD 5.12.5.3.6: Joint Design.
"""
tags = TagManager(tag_base)
model = SuperstructureModel()
model.span_lengths = list(span_lengths_ft)
model.girder_li_find_closest_node function · python · L1181-L1194 (14 LOC)src/nlb/tools/superstructure.py
def _find_closest_node(nodes: List[Dict], x: float, y: float, z: float,
tol: float = 1.0) -> Optional[int]:
"""Find the node tag closest to target coordinates within tolerance."""
best_tag = None
best_dist = float('inf')
for n in nodes:
dist = math.sqrt((n['x'] - x)**2 + (n['y'] - y)**2 + (n['z'] - z)**2)
if dist < best_dist:
best_dist = dist
best_tag = n['tag']
if best_dist <= tol:
return best_tag
# If no node within tolerance, return nearest anyway
return best_tag_build_steel_truss function · python · L1201-L1396 (196 LOC)src/nlb/tools/superstructure.py
def _build_steel_truss(
span_lengths_ft: List[float],
panel_length_ft: float,
truss_depth_ft: float,
top_chord_area_in2: float,
bot_chord_area_in2: float,
vertical_area_in2: float,
diagonal_area_in2: float,
connection_type: str,
fy_ksi: float,
deck_width_ft: float,
continuity: List[str],
skew_angle: float,
tag_base: int = 1,
**kwargs,
) -> SuperstructureModel:
"""Build steel truss superstructure.
Warren or Pratt truss geometry with corotTruss elements.
Two truss lines (left and right) with floor beam connections.
Reference:
AASHTO LRFD 4.6.2.7: Truss Bridges.
"""
tags = TagManager(tag_base)
model = SuperstructureModel()
model.span_lengths = list(span_lengths_ft)
model.girder_lines = 2 # two truss lines
model.deck_width = deck_width_ft
model.continuity = list(continuity)
truss_depth_in = truss_depth_ft * FT_TO_IN
panel_length_in = panel_length_ft * FT_TO_IN
truss_s_build_concrete_slab function · python · L1403-L1527 (125 LOC)src/nlb/tools/superstructure.py
def _build_concrete_slab(
span_lengths_ft: List[float],
slab_thickness_in: float,
slab_width_ft: Optional[float],
deck_width_ft: float,
continuity: List[str],
skew_angle: float,
fc_ksi: float,
rebar_area_in2_per_ft: float,
tag_base: int = 1,
**kwargs,
) -> SuperstructureModel:
"""Build concrete slab bridge using ShellMITC4 elements.
For short-span bridges (typically < 40 ft). Models the slab as a
2D shell mesh with plate bending behavior.
Reference:
AASHTO LRFD 4.6.2.3: Equivalent Strip Widths for Slab-Type Bridges.
"""
tags = TagManager(tag_base)
model = SuperstructureModel()
model.span_lengths = list(span_lengths_ft)
model.girder_lines = 0 # no girder lines — shell model
width_ft = slab_width_ft or deck_width_ft
model.deck_width = width_ft
model.continuity = list(continuity)
width_in = width_ft * FT_TO_IN
# --- Material (nDMaterial for shell) ---
from ..opensees.materials _arch_shape_y function · python · L1534-L1564 (31 LOC)src/nlb/tools/superstructure.py
def _arch_shape_y(x: float, span_in: float, rise_in: float,
shape: str) -> float:
"""Compute arch rib elevation at position x.
Args:
x: Position along span (0 to span_in).
span_in: Total span length (inches).
rise_in: Rise at midspan (inches).
shape: 'parabolic' or 'circular'.
Returns:
Y-coordinate (inches) of arch rib centerline.
"""
if shape == 'parabolic':
# y = 4*rise * x/L * (1 - x/L)
xi = x / span_in
return 4.0 * rise_in * xi * (1.0 - xi)
elif shape == 'circular':
# Circular arc: find R from span and rise
# The arc passes through (0,0), (span/2, rise), (span, 0)
# Center of circle is at (span/2, -(R - rise))
# R² = (span/2)² + (R - rise)²
# R = [(span/2)² + rise²] / (2 * rise)
half_span = span_in / 2.0
R = (half_span**2 + rise_in**2) / (2.0 * rise_in)
y_center = -(R - rise_in) # center below the chMethodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
_build_arch function · python · L1567-L1674 (108 LOC)src/nlb/tools/superstructure.py
def _build_arch(
span_lengths_ft: List[float],
arch_rise_ft: float,
arch_shape: str,
rib_depth_in: float,
rib_width_in: float,
deck_width_ft: float,
continuity: List[str],
skew_angle: float,
fc_ksi: float,
fy_ksi: float,
tag_base: int = 1,
**kwargs,
) -> SuperstructureModel:
"""Build arch bridge superstructure.
Single arch span modeled as dispBeamColumn elements following the
arch geometry. Supports parabolic and circular arch shapes.
Only the first span is used for the arch; multi-span arches not supported.
Reference:
AASHTO LRFD 4.5.3.2.2c: Arches.
"""
tags = TagManager(tag_base)
model = SuperstructureModel()
model.span_lengths = list(span_lengths_ft)
model.girder_lines = 1
model.deck_width = deck_width_ft
model.continuity = list(continuity)
span_ft = span_lengths_ft[0]
span_in = span_ft * FT_TO_IN
rise_in = arch_rise_ft * FT_TO_IN
# --- Material ---
concreGeoLocation class · python · L116-L135 (20 LOC)src/nlb/utils/geo.py
class GeoLocation:
"""Result of a reverse geocode call.
All fields may be empty-string if the geocoder returned no data —
callers should handle this gracefully and fall back to conservative
default values.
"""
lat: float
lon: float
state: str # USPS 2-letter abbreviation, e.g. "IL"
county: str # e.g. "Winnebago County"
city: str # nearest populated place, may be empty
country: str # ISO 3166-1 alpha-2, e.g. "US"
display_name: str # full Nominatim display string (for logging/reports)
@property
def climate_zone(self) -> str:
"""Infer ASHRAE climate zone from state abbreviation."""
return CLIMATE_ZONE_BY_STATE.get(self.state, "mixed")reverse_geocode function · python · L142-L224 (83 LOC)src/nlb/utils/geo.py
def reverse_geocode(
lat: float,
lon: float,
timeout: int = 10,
user_agent: str = "natural-language-builder/0.1 (bridge-engineering-tool)",
) -> GeoLocation:
"""Reverse-geocode a WGS-84 coordinate pair via OSM Nominatim.
Returns a :class:`GeoLocation`. On any network or parse failure, falls
back to an empty :class:`GeoLocation` so callers never crash — they just
get less-rich data and should apply conservative defaults.
Args:
lat: Latitude, decimal degrees (positive = North).
lon: Longitude, decimal degrees (positive = East).
timeout: Request timeout in seconds.
user_agent: Required by Nominatim usage policy; identifies the app.
Returns:
GeoLocation with state, county, city populated where available.
"""
_empty = GeoLocation(
lat=lat, lon=lon,
state="", county="", city="", country="",
display_name="",
)
url = "https://nominatim.openstreetmap.org/