civilpy.geotech package
Geotechnical engineering: boring-log data models and parsers, SPT corrections, foundation capacity, lateral pile analysis, and earth pressure.
Submodules
civilpy.geotech.axial_load_transfer module
Axial pile load-transfer (t-z and q-z) curves.
The lateral-pile module (civilpy.geotech.lateral_pile) gives the p-y
springs that resist horizontal pile movement; this module is the axial
companion, supplying the t-z curves (mobilised side / skin friction per
unit length versus axial displacement) and the q-z curve (mobilised end
bearing at the tip versus tip settlement). Together the three families give
the full set of foundation springs a structural model needs to support a
pier or an integral-abutment pile bent on soil rather than on fixed points.
The backbone shapes are the American Petroleum Institute recommendation
(API RP 2A-WSD, §6.7): normalised t/t_max and Q/Q_p tables against
z/D (clay) or absolute displacement (sand), linearly interpolated. The
ultimate values t_max (unit skin friction times perimeter) and Q_p
(tip area times unit end bearing) come from the capacity routines in
civilpy.geotech.deep_foundation, so a single boring drives capacity,
settlement, and the spring model consistently.
These are normalised design curves; a settlement-sensitive structure should be checked against a project-specific load-transfer analysis.
Units: displacements in inches, forces in pounds, diameters in inches (so a
t-z secant modulus is lb/in per inch of pile = lb/in^2 and a spring constant
is lb/in) – matching civilpy.geotech.lateral_pile. Use
spring_constant_kip_per_in() when handing values to a kip-unit model.
- class civilpy.geotech.axial_load_transfer.APIQZCurve(q_max: float, diameter: float = 12.0)[source]
Bases:
QZCurveAPI RP 2A-WSD q-z curve.
q_maxis the ultimate tip resistance (lb) = tip area times unit end bearing;diameter(in) sets the z/D normalisation (full mobilisation at a tip settlement of 0.10 D).
- class civilpy.geotech.axial_load_transfer.APITZCurve(t_max: float, soil: str = 'clay', diameter: float = 12.0)[source]
Bases:
TZCurveAPI RP 2A-WSD t-z curve.
t_maxis the ultimate side resistance per unit pile length (lb/in) – the unit skin friction times the pile perimeter.soilselects the normalised backbone:"clay"uses the z/D table (sodiameterin inches is required),"sand"mobilisest_maxat a fixed 0.10 in.
- class civilpy.geotech.axial_load_transfer.QZCurve[source]
Bases:
objectBase class for end-bearing (q-z) curves. Subclasses implement
q()and exposeq_max.
- class civilpy.geotech.axial_load_transfer.TZCurve[source]
Bases:
objectBase class for axial side-resistance (t-z) curves. Subclasses implement
t()and exposet_max; the secant modulus follows.- secant_modulus(w: float) float[source]
Secant load-transfer modulus
t/w(lb/in^2) at displacementw(in); uses a displacement floor so it stays finite at w = 0.
- civilpy.geotech.axial_load_transfer.axial_pile_springs(curve: TZCurve, embedded_length: float, n_nodes: int, design_disp: float) list[tuple[float, float]][source]
Discretise an embedded pile into
n_nodesequally spaced axial (t-z) springs and return(depth_in, k_lb_per_in)for each.The spring constant at a node is the t-z secant modulus at
design_disp(in) times the tributary length (in) the node represents – a linearised Winkler spring suitable for a MIDAS nodal spring support.endnodes carry half the tributary length.embedded_lengthis in inches.
civilpy.geotech.boring module
Canonical, library-neutral data model for a subsurface boring.
A geotechnical boring log is the hub object the rest of CivilPy reads from:
the same Borehole can drive scour grain-size lookups in the
hydraulics library, axial capacity in the foundations modules, and soil
zone moduli for CANDE. Ingestion (DIGGS XML, PDF logs, …) lives in
civilpy.geotech.boring_io and produces these objects; nothing here
depends on how the data was read.
Units are US customary: depths and elevations in feet, particle sizes in millimetres (the geotechnical convention for gradations), recovery in inches. Blow counts are dimensionless.
- class civilpy.geotech.boring.Borehole(boring_id: str, project: str | None = None, ground_elevation_ft: float | None = None, latitude: float | None = None, longitude: float | None = None, station: str | None = None, offset_ft: float | None = None, offset_direction: str | None = None, total_depth_ft: float | None = None, water_strike_depth_ft: float | None = None, date: str | None = None, purpose: str | None = None, samples: list[Sample] = <factory>, spt: list[SPTResult] = <factory>, grading: list[GradingResult] = <factory>)[source]
Bases:
objectA single subsurface boring: header location/geometry plus the depth-indexed sample, SPT, and gradation records read from a log.
- d50_at(depth_ft: float) float | None[source]
D50 (mm) of the gradation nearest
depth_ft– the scour input.
- elevation_at(depth_ft: float) float | None[source]
Ground-surface elevation minus
depth_ft(None if the collar elevation is unknown).
- grading: list[GradingResult]
- grading_at(depth_ft: float) GradingResult | None[source]
Gradation analysis nearest
depth_ft(None if none present).
- class civilpy.geotech.boring.DriveIncrement(blows: 'int', penetration_in: 'float' = 6.0)[source]
Bases:
object
- class civilpy.geotech.boring.GradingPoint(particle_size_mm: float, percent_passing: float)[source]
Bases:
objectOne point on a particle-size distribution:
percent_passingfiner thanparticle_size_mm.
- class civilpy.geotech.boring.GradingResult(depth_ft: float, points: tuple[GradingPoint, ...])[source]
Bases:
objectA particle-size (sieve + hydrometer) analysis on a sample taken at
depth_ft.pointsare stored sorted coarse-to-fine.- FINES_SIZE_MM = 0.075
US No. 200 sieve opening, mm (the silt/sand fines boundary).
- d_size(percent: float) float | None[source]
Particle size (mm) at which
percentof the sample is finer (e.g.d_size(50)is D50), log-linearly interpolated;Noneif the curve does not bracket that percentage.
- percent_passing_at(size_mm: float) float | None[source]
Percent finer than
size_mmby log-linear interpolation on the gradation curve;Noneif outside the measured range.
- points: tuple[GradingPoint, ...]
- class civilpy.geotech.boring.SPTResult(depth_ft: float, increments: tuple[DriveIncrement, ...], hammer_type: str | None = None, hammer_efficiency: str | None = None)[source]
Bases:
objectOne Standard Penetration Test at
depth_ft(top of the 18-inch drive).incrementsare the successive 6-inch drives in order (seating, then the two that count).- increments: tuple[DriveIncrement, ...]
- n60(energy_ratio: float = 0.6, rod_length_ft: float | None = None, borehole_diameter_in: float = 4.0, liner: bool = False) float | None[source]
Energy-corrected blow count N60 (Skempton 1986): N60 = N * (Em/0.60) * Cr * Cb * Cs, where
energy_ratioEm is the measured/rated hammer efficiency as a decimal. Rod-length Cr is applied fromrod_length_ft(taken asdepth_ftwhen omitted), borehole Cb fromborehole_diameter_in, sampler Cs fromliner.
- property n_value: int | None
the sum of the second and third 6-inch increments (ASTM D1586). With only two increments their sum is used; with fewer than two,
None.- Type:
Field SPT blow count N
civilpy.geotech.boring_io module
Readers that turn published boring-log deliverables into the canonical
Borehole objects.
The primary, near-lossless path is DIGGS (Data Interchange for
Geotechnical and Geoenvironmental Specialists) XML – the structured export
many DOTs publish alongside the rendered PDF log. Ohio DOT, for example,
serves a DIGGS_URL for each hole on its TIMS geotechnical layer; that
file carries the borehole geometry, every SPT drive set, and the full
particle-size curve, so no character-window scraping is needed.
A DIGGS document is GML-based and heavily namespaced; this reader matches
on local element names so it is agnostic to the schema version
(2.5.a, 2.6, …) and to namespace-prefix churn. Only the standard
library (xml.etree.ElementTree) is used.
PDF log ingestion (for the raster/scanned holes that have no DIGGS file) is
a separate, lower-fidelity concern handled by read_pdf_log().
- civilpy.geotech.boring_io.parse_diggs(source) list[Borehole][source]
Parse a DIGGS document into a list of
Borehole.sourcemay be a file path, an open file/bytes, or a string of XML. EveryBoreholesampling feature becomes one object; the SPT and particle-sizeTestrecords and theSamplingActivitysample intervals are attached to their borehole bysamplingFeatureRef.
- civilpy.geotech.boring_io.read_pdf_log(path) Borehole[source]
Best-effort reader for a rendered PDF boring log.
Most published logs are raster/scanned PDFs with no text layer, which require OCR and template-specific table recovery; that lower-fidelity path is not yet implemented. Prefer
parse_diggs()whenever a DIGGS file is available for the hole.
civilpy.geotech.cande_adapter module
Turn a boring log into CANDE soil zones.
civilpy.structural.cande builds a buried-culvert model from three
soil materials (in situ, bedding, fill). This adapter derives those
SoilMaterial objects from the measured
Borehole: an SPT-based linear-elastic
soil for the in-situ ground, or a canned Duncan/Selig material chosen from
the gradation and a target compaction for engineered fill/bedding.
The elastic moduli come from the SPT correlations in
civilpy.geotech.spt; they are estimates and should yield to a
laboratory-characterised soil when one exists.
- civilpy.geotech.cande_adapter.clay_soil_material_from_spt(n60: float, modulus_ratio: float = 300.0, su_factor_psf: float = 92.0, poisson: float | None = None, density_pcf: float | None = None, name: str | None = None) SoilMaterial[source]
A linear-elastic
SoilMaterialfor a fine-grained soil: Su from N60 (Stroud), then Eu =modulus_ratio* Su.
- civilpy.geotech.cande_adapter.duncan_selig_from_gradation(grading: GradingResult, compaction_percent: float, density_pcf: float, fine_group: str = 'ML') SoilMaterial[source]
Pick a canned Duncan/Selig
SoilMaterialfor engineered fill/bedding from a gradation and a target compaction.Coarse soils (fines < 50%) map to the gravelly-sand
SWfamily; fine soils map tofine_group("ML"sandy silt by default,"CL"for plastic clays). The canned material nearestcompaction_percentstandard Proctor is selected.
- civilpy.geotech.cande_adapter.in_situ_soil_material(borehole: Borehole, depth_ft: float, energy_ratio: float = 0.6, sigma_v_eff_psf: float | None = None, density_pcf: float | None = None, name: str | None = None) SoilMaterial[source]
The in-situ CANDE soil zone for
boreholeatdepth_ft.Uses the SPT nearest the depth, classifies coarse vs fine from the nearest gradation (fines >= 50% -> clay path), and returns the matching linear-elastic
SoilMaterial. Raises if the hole has no SPT data near the depth.
- civilpy.geotech.cande_adapter.soil_material_from_spt(n: float, soil_type: str = 'sand', poisson: float | None = None, density_pcf: float | None = None, name: str | None = None) SoilMaterial[source]
A linear-elastic
SoilMaterialfrom an SPT N value.soil_typeis one of the Bowles coarse-grained categories (seecivilpy.geotech.spt.elastic_modulus_from_spt()). Young’s modulus comes from N; Poisson’s ratio and unit weight default by soil type and N unless given.
civilpy.geotech.culmanns module
Culmann’s graphical method for active earth pressure.
Reproduces the classic Culmann construction for a retaining wall backfill loaded by a Cooper E80 railroad surcharge, computing trial-wedge weights and the governing failure plane, and plotting the construction with matplotlib.
- class civilpy.geotech.culmanns.CulmannsMethod(coordinates_list=None, soil_unit_weight=<Quantity(117.7, 'force_pound / foot ** 3')>, soil_angle_int_friction=<Quantity(29.8, 'degree')>, angle_back_wall_with_horizontal=<Quantity(0, 'degree')>, angle_of_wall_friction_delta=<Quantity(0, 'degree')>, angle_of_wall_friction_gamma=<Quantity(90, 'degree')>, load_scale=<Quantity(2.9059, 'kip / foot')>, wall_height=<Quantity(19.5, 'foot')>, soil_height_above_wall=<Quantity(4.4, 'foot')>, num_slices=19, total_length=<Quantity(38, 'foot')>, track_offset=<Quantity(2, 'foot')>)[source]
Bases:
objectImplements Culmann’s graphical method for lateral earth pressure.
Culmann’s method is a graphical/tabular approach for determining the maximum active lateral earth pressure on a retaining wall under arbitrary backfill geometry and surcharge loading. This class builds the calculation spreadsheet and provides plotting utilities.
- table
Spreadsheet of intermediate Culmann calculations (a_i, b_i, c_i, wedge areas, weights, x/y coordinates, and resultant forces).
- Type:
- __init__(coordinates_list=None, soil_unit_weight=<Quantity(117.7, 'force_pound / foot ** 3')>, soil_angle_int_friction=<Quantity(29.8, 'degree')>, angle_back_wall_with_horizontal=<Quantity(0, 'degree')>, angle_of_wall_friction_delta=<Quantity(0, 'degree')>, angle_of_wall_friction_gamma=<Quantity(90, 'degree')>, load_scale=<Quantity(2.9059, 'kip / foot')>, wall_height=<Quantity(19.5, 'foot')>, soil_height_above_wall=<Quantity(4.4, 'foot')>, num_slices=19, total_length=<Quantity(38, 'foot')>, track_offset=<Quantity(2, 'foot')>)[source]
Initialise the Culmann’s method calculator and generate the table.
- Parameters:
coordinates_list (dict, optional) – Dictionary of labelled coordinate points defining the wall geometry and trial wedge locations. Defaults to
default_coordinates_listbuilt from Cooper E80 loading.soil_unit_weight (pint.Quantity) – Unit weight of the retained soil (default 117.7 lbf/ft³).
soil_angle_int_friction (pint.Quantity) – Angle of internal friction φ (default 29.8°).
angle_back_wall_with_horizontal (pint.Quantity) – Angle α between the back of the wall and horizontal (default 0°).
angle_of_wall_friction_delta (pint.Quantity) – Wall friction angle δ (default 0°).
angle_of_wall_friction_gamma (pint.Quantity) – Angle γ used in the force polygon construction (default 90°).
load_scale (pint.Quantity) – Scale factor converting cumulative wedge weight to plot coordinates (default 2.9059 kips/ft).
wall_height (pint.Quantity) – Height of the retaining wall (default 19.5 ft).
soil_height_above_wall (pint.Quantity) – Height of soil above the wall top (default 4.4 ft).
num_slices (int) – Number of trial wedge slices (default 19).
total_length (pint.Quantity) – Total horizontal extent of the backfill area (default 38 ft).
track_offset (pint.Quantity) – Horizontal offset to the first trial point (default 2 ft).
- calculate_A_i(s_i, a_i, b_i, c_i)[source]
Calculate area A_i (ft^2) using the formula provided.
- calculate_a_i(x_val, y_val)[source]
Calculate a_i (ft) based on the current coordinates.
- calculate_b_i(current_key, keys, coordinates_list, x_val, y_val)[source]
Calculate b_i (ft) using the previous point’s coordinates.
- calculate_c_i(current_key, keys, coordinates_list)[source]
Calculate c_i (ft) based on the previous coordinates. If first point, refer to point ‘A’.
- calculate_cumulative_weights(values)[source]
Calculate cumulative weights (lbf/ft) for a list of values.
- calculate_ll_surcharge(b_i)[source]
Calculate the live-load surcharge for a wedge slice per unit wall length.
Uses a simplified Cooper E80 equivalent strip load distribution. The E80 axle load (80 000 lbf) is distributed over a 4-rail area (18 ft tie spacing × 8.5 ft track width) and integrated over the wedge base length b_i.
- Parameters:
b_i (pint.Quantity) – Length of the wedge base segment b_i (ft).
- Returns:
Live load surcharge contribution (lbf/ft).
- Return type:
pint.Quantity
- calculate_running_total(values)[source]
Calculate running total (ft) for a list of values.
- calculate_s_i(a_i, b_i, c_i)[source]
Calculate s_i (ft) as the semi-perimeter of the triangle.
- calculate_w_i(A_i, soil_unit_weight)[source]
Calculate w_i (lbf/ft) as the incremental weight of the triangle per unit length.
- calculate_x_cgi(x_val, next_x_val)[source]
Calculate x_{cgi} (ft) as the center of gravity x-coordinate.
- calculate_x_ci(total_weight, load_scale, soil_angle_int_friction)[source]
Calculate x_ci (dimensionless plotting coordinate on the force polygon).
Converts total wedge weight to a force-polygon x-coordinate by dividing by the load scale (converted to matching units) and projecting onto the friction angle direction.
- Parameters:
total_weight (pint.Quantity) – Total cumulative wedge weight in lbf/ft.
load_scale (pint.Quantity) – Force-polygon scale factor in kips/ft.
soil_angle_int_friction (pint.Quantity) – Angle of internal friction φ.
- Returns:
The x_ci plotting coordinate (dimensionless).
- Return type:
- calculate_x_ci_prime(y_ci, x_ci, angle_back_wall_with_horizontal, angle_of_wall_friction_delta, soil_angle_int_friction, D, C)[source]
- calculate_y_cgi(y_val, next_y_val)[source]
Calculate y_{cgi} (ft) as the center of gravity y-coordinate.
- calculate_y_ci(x_ci, soil_angle_int_friction)[source]
Calculate y_ci (dimensionless plotting coordinate on the force polygon).
- generate_spreadsheet(coordinates_list, soil_unit_weight, load_scale, soil_angle_int_friction, angle_back_wall_with_horizontal, angle_of_wall_friction_delta)[source]
Calculate various columns for soil and wall friction analysis.
Args: coordinates_list (dict): Dictionary containing coordinate points. soil_unit_weight (float): The unit weight of the soil. load_scale (float): Load scale value. soil_angle_int_friction (float): Angle of internal friction of soil in radians. angle_back_wall_with_horizontal (float): Angle between back of wall and horizontal in radians. angle_of_wall_friction_delta (float): Angle of wall friction in radians.
Returns: pd.DataFrame: DataFrame containing computed columns.
- plot_results()[source]
Plot the retaining wall geometry and Culmann’s method construction.
Generates a matplotlib figure showing:
Trial wedge points (C_1 … C_n) and the base points A and B.
Dashed green lines connecting each C-point back to B.
The ground surface line from A through all C-points.
A trapezoidal retaining wall cross-section.
The figure is displayed via
plt.show().
- civilpy.geotech.culmanns.build_coordinates_list(starting_coordinates_list={'A': (0, 23.9, 'LS1'), 'B': (0, 0, None), 'C_1': (2.0, 19.5, 'LS1'), 'C_10': (20.0, 19.5, 'LS1'), 'C_11': (22.0, 19.5, None), 'C_12': (24.0, 19.5, None), 'C_13': (26.0, 19.5, 'LS2'), 'C_14': (28.0, 19.5, 'LS2'), 'C_15': (30.0, 19.5, 'LS2'), 'C_16': (32.0, 19.5, 'LS2'), 'C_17': (34.0, 19.5, 'LS2'), 'C_18': (36.0, 19.5, 'LS2'), 'C_19': (38.0, 19.5, 'LS2'), 'C_2': (4.0, 19.5, 'LS1'), 'C_3': (6.0, 19.5, 'LS1'), 'C_4': (8.0, 19.5, 'LS1'), 'C_5': (10.0, 19.5, 'LS1'), 'C_6': (12.0, 19.5, 'LS1'), 'C_7': (14.0, 19.5, 'LS1'), 'C_8': (16.0, 19.5, 'LS1'), 'C_9': (18.0, 19.5, 'LS1')}, total_length=38, num_slices=19, track_offset=2, wall_height=19.5, soil_height_above_wall=0)[source]
Populate a Culmann’s method coordinate dictionary with trial wedge points.
Adds
num_slicesC-points ("C_1"…"C_n") to starting_coordinates_list. Each point represents the top of a trial failure wedge at a horizontal spacing oftotal_length / num_slicesstarting from track_offset.- Parameters:
starting_coordinates_list (dict) – Base dictionary containing at least the fixed
"A"(wall top) and"B"(wall toe) points.total_length (float) – Horizontal extent of the soil wedge area (ft).
num_slices (int) – Number of trial wedge points to generate.
track_offset (float) – Horizontal offset from the wall face to the first trial point (ft).
wall_height (float) – Height of the retaining wall (ft).
soil_height_above_wall (float) – Additional soil height above the wall top (ft).
- Returns:
Updated coordinate dictionary with the new C-points added.
- Return type:
- civilpy.geotech.culmanns.find_key_for_value_in_tuple_range(data, number)[source]
Find the key in a dictionary where the number falls between the first two values of the tuple.
Args: data (dict): Dictionary containing lists of tuples. number (float): The number to search for within the tuple ranges.
Returns: key: The key in the dictionary whose tuple contains the number, or None if not found.
civilpy.geotech.deep_foundation module
Axial capacity of deep foundations from a boring log.
Two methods share one boring-driven integrator:
Drilled shafts – FHWA / AASHTO LRFD Article 10.8 (O’Neill & Reese, FHWA GEC-10): the alpha method for side and tip resistance in cohesive soil and the beta method for cohesionless soil.
Driven piles – the Meyerhof (1976) SPT method for cohesionless soil (unit skin friction and end bearing from N60) plus the alpha method in clay, consistent with AASHTO 10.7.3.8.6.
The unit-resistance functions are the citable core; the
drilled_shaft_capacity() and driven_pile_capacity() drivers
discretise the element, pull soil properties at each depth from a
Borehole (blow counts via
civilpy.geotech.spt), integrate side resistance, and add tip
resistance.
Soil parameters derived from SPT are estimates; a foundation for final design should be checked against a project-specific subsurface characterisation. The Meyerhof method in particular is known to be unconservative for end bearing in dense sand.
Units: lengths in feet, unit weights in pcf, stresses and unit resistances in ksf, capacities in kips, angles in degrees.
- civilpy.geotech.deep_foundation.GAMMA_WATER_PCF = 62.4
Unit weight of water, pcf.
- civilpy.geotech.deep_foundation.PA_KSF = 2.116
Atmospheric pressure, ksf (used to normalise Su for the alpha factor).
- class civilpy.geotech.deep_foundation.PileCapacity(width_ft: float, tip_depth_ft: float, side_nominal_kips: float, tip_nominal_kips: float)[source]
Bases:
objectResult of
driven_pile_capacity(): nominal resistances (kips) and the pile geometry that produced them.
- class civilpy.geotech.deep_foundation.ShaftCapacity(diameter_ft: float, tip_depth_ft: float, side_nominal_kips: float, tip_nominal_kips: float)[source]
Bases:
objectResult of
drilled_shaft_capacity(): nominal resistances (kips) and the shaft geometry that produced them.
- civilpy.geotech.deep_foundation.alpha_factor(su_ksf: float) float[source]
Adhesion factor alpha for drilled-shaft side resistance in clay (AASHTO LRFD 10.8.3.5.1b, O’Neill & Reese):
alpha = 0.55 for Su/pa <= 1.5 alpha = 0.55 - 0.1 (Su/pa - 1.5) for 1.5 < Su/pa <= 2.5
- civilpy.geotech.deep_foundation.beta_factor(depth_ft: float, n60: float) float[source]
Side-resistance factor beta for sand (AASHTO 10.8.3.5.2b, O’Neill & Reese): beta = 1.5 - 0.135 sqrt(z), 0.25 <= beta <= 1.2, with a linear reduction by N60/15 for loose sand (N60 < 15).
zin feet.
- civilpy.geotech.deep_foundation.drilled_shaft_capacity(borehole: Borehole, diameter_ft: float, tip_depth_ft: float, water_table_ft: float | None = None, energy_ratio: float = 0.6, step_ft: float = 0.5, su_factor_psf: float = 92.0, exclude_top_ft: float = 5.0, exclude_bottom_diameters: float = 1.0) ShaftCapacity[source]
Nominal axial (compression) capacity of a straight drilled shaft.
Discretises the shaft into
step_ftelements, derives soil properties at each fromborehole(cohesive vs cohesionless by gradation fines, blow counts energy-corrected to N60), integrates the effective vertical stress, and sums side resistance – excluding the topexclude_top_ftand the bottomexclude_bottom_diametersdiameters per AASHTO 10.8.3.5 – then adds tip resistance at the base.water_table_ftoverrides the boring’s recorded water strike; with neither, fully drained (no pore pressure) is assumed.
- civilpy.geotech.deep_foundation.driven_pile_capacity(borehole: Borehole, width_ft: float, tip_depth_ft: float, perimeter_ft: float | None = None, area_ft2: float | None = None, displacement: bool = True, alpha_clay: float = 0.55, water_table_ft: float | None = None, energy_ratio: float = 0.6, step_ft: float = 0.5, su_factor_psf: float = 92.0) PileCapacity[source]
Nominal axial (compression) capacity of a driven pile.
Discretises the pile, derives soil properties at each element from
borehole(cohesive vs cohesionless by gradation fines), and sums skin friction over the full embedded length – Meyerhof fs = m Pa N60 in sand, alpha * Su in clay – then adds end bearing at the tip (Meyerhof in sand, 9 Su in clay).width_ftis the pile diameter/width. By default a solid round/ square section is assumed (perimeterpi*B,areapi*B^2/4); passperimeter_ftandarea_ft2for H-piles or open sections.displacementselects the Meyerhof skin-friction coefficient.
- civilpy.geotech.deep_foundation.meyerhof_unit_end_bearing_sand(n60: float, embedment_ratio: float, pa_ksf: float = 2.116) float[source]
Nominal unit end bearing (ksf) of a driven pile in cohesionless soil (Meyerhof 1976): qp = 0.4 Pa N60 (Lb/D) <= 4 Pa N60, where
embedment_ratioLb/D is the embedment in the bearing stratum over the pile width.
- civilpy.geotech.deep_foundation.meyerhof_unit_skin_friction_sand(n60: float, displacement: bool = True, pa_ksf: float = 2.116) float[source]
Nominal unit skin friction (ksf) of a driven pile in cohesionless soil (Meyerhof 1976): fs = m * Pa * N60, with m = 0.02 for large- displacement piles (closed-end pipe, precast) and 0.01 for small- displacement piles (H-piles, open-end pipe).
- civilpy.geotech.deep_foundation.pile_unit_skin_friction_clay(su_ksf: float, alpha: float = 0.55) float[source]
Nominal unit skin friction (ksf) of a driven pile in cohesive soil by the alpha (total-stress) method: fs = alpha * Su.
alphafollows Tomlinson/API and ranges from ~0.5 (stiff clay) to 1.0 (soft clay).
- civilpy.geotech.deep_foundation.unit_side_resistance_clay(su_ksf: float) float[source]
Nominal unit side resistance in cohesive soil (ksf): q_s = alpha * Su (AASHTO 10.8.3.5.1b).
- civilpy.geotech.deep_foundation.unit_side_resistance_sand(sigma_v_eff_ksf: float, depth_ft: float, n60: float, limit_ksf: float = 4.0) float[source]
Nominal unit side resistance in cohesionless soil (ksf): q_s = beta * sigma’_v, capped at
limit_ksf(AASHTO 10.8.3.5.2b).
civilpy.geotech.lateral_earth module
Rankine and Coulomb lateral earth pressure with the classic pressure-
diagram plot — companions to the Culmann graphical method already in
civilpy.geotech.culmanns.
Units: ft, pcf inputs; pressures plotted in psf.
Examples
>>> round(rankine_ka(30), 4)
0.3333
>>> round(rankine_kp(30), 1)
3.0
>>> wall = LateralEarthPressure(height=12, gamma=120, phi=30)
>>> round(wall.resultant, 0) # 0.5*Ka*gamma*H^2 = 2880 lb/ft
2880.0
- class civilpy.geotech.lateral_earth.LateralEarthPressure(height: float, gamma: float, phi: float, surcharge: float = 0.0, water_depth: float | None = None, k: float | None = None, passive: bool = False)[source]
Bases:
objectActive (or passive) pressure diagram on a wall of
heightft retaining soil of unit weightgammapcf and friction anglephideg, with optional uniform surcharge (psf) and water table depth (ft below the top).- plot(ax=None)[source]
Pressure-diagram plot: wall on the left, pressure wedge growing with depth, resultant arrow at its centroid.
- civilpy.geotech.lateral_earth.coulomb_ka(phi_deg: float, delta_deg: float = 0.0, beta_deg: float = 0.0, theta_deg: float = 0.0) float[source]
Coulomb active coefficient: wall friction
delta, backfill slopebeta, wall back-face batterthetafrom vertical.
civilpy.geotech.lateral_pile module
Laterally loaded piles: a shared p-y curve library, a finite-element beam-on-nonlinear-foundation solver, Broms’ closed-form ultimate-load method, and the characteristic-length / subgrade-reaction hand methods.
The p-y curve classes (SoftClayPY, StiffClayPY,
SandPY, LinearPY) are the reusable core: they expose a
common p(y, z) (soil resistance per unit length) and pu(z) (ultimate
resistance) so the same soil models drive both the in-process solver here
and the LPILE input-file generator in civilpy.geotech.lpile.
Curve references: soft clay – Matlock (1970); stiff clay without free water – Reese & Welch (1975); sand – the API RP 2A / O’Neill & Murchison hyperbolic-tangent form on Reese’s (1974) ultimate resistance.
Units throughout this module are inches, pounds, and psi (so unit weights are pci and the flexural stiffness EI is lb-in^2), matching the convention LPILE uses. Angles are in degrees.
- class civilpy.geotech.lateral_pile.BromsResult(h_ult: float, mode: str, h_short: float, h_long: float, f_maxmoment: float | None = None)[source]
Bases:
objectUltimate lateral load by Broms’ method and the governing mechanism.
- class civilpy.geotech.lateral_pile.LateralPileResult(depth: ndarray, deflection: ndarray, moment: ndarray, shear: ndarray, soil_reaction: ndarray, iterations: int, converged: bool)[source]
Bases:
objectDepth-wise response of a laterally loaded pile.
- class civilpy.geotech.lateral_pile.LinearPY(k: float, p_ult: float = inf)[source]
Bases:
PYCurveA constant-modulus Winkler spring
p = k*y(k in psi). Mostly for verifying the solver against the closed-form subgrade-reaction solution, but also a valid simple model.
- civilpy.geotech.lateral_pile.MATLOCK_REESE_AY = 2.435
Matlock-Reese non-dimensional coefficients at the ground surface (Z = 0) for a long, free-headed pile in soil with linearly increasing modulus.
- class civilpy.geotech.lateral_pile.PYCurve[source]
Bases:
objectBase class for p-y curves. Subclasses implement
p()andpu(); the secant modulus used by the solver follows from them.
- class civilpy.geotech.lateral_pile.SandPY(phi_deg: float, gamma: float, b: float, k: float | None = None, submerged: bool = False, static: bool = True)[source]
Bases:
PYCurveAPI RP 2A / O’Neill & Murchison sand p-y curve on Reese’s ultimate resistance:
p = A*pu*tanh(k*z*y/(A*pu)).phi_degfriction angle,gammaeffective unit weight (pci),bdiameter (in),kinitial subgrade modulus (pci; defaults fromsand_subgrade_modulus()),submergedselects the k table, andstaticthe A-factor (max(3 - 0.8 z/b, 0.9)static, 0.9 cyclic).
- class civilpy.geotech.lateral_pile.SoftClayPY(cu: float, b: float, gamma: float, eps50: float = 0.02, J: float = 0.5, static: bool = True)[source]
Bases:
PYCurveMatlock (1970) soft-clay p-y curve.
cuundrained shear strength (psi),bpile diameter (in),gammaeffective unit weight (pci),eps50strain at half the ultimate stress,Jthe empirical factor (0.5 soft / 0.25 stiffer field clays).staticselects the static backbone (the cyclic curve flattens at 0.72*pu below the critical depth).
- class civilpy.geotech.lateral_pile.StiffClayPY(cu: float, b: float, gamma: float, eps50: float = 0.007, J: float = 0.5)[source]
Bases:
PYCurveReese & Welch (1975) stiff clay without free water.
Same ultimate resistance as Matlock but a flatter backbone
p = 0.5*pu*(y/y50)^0.25reaching pu at 16*y50, withy50 = eps50*b.
- class civilpy.geotech.lateral_pile.SubgradeResponse(head_deflection: float, head_slope: float, max_moment: float, characteristic_length: float, point_of_fixity: float)[source]
Bases:
objectPile-head response from a closed-form subgrade-reaction analysis.
- civilpy.geotech.lateral_pile.broms_cohesionless(phi_deg: float, gamma: float, b: float, length: float, yield_moment: float, e: float = 0.0) BromsResult[source]
Broms (1964) ultimate lateral load of a free-headed pile in cohesionless soil, using a passive resistance
3*Kp*gamma*z*b(RankineKp).gammaeffective unit weight (pci), other arguments as inbroms_cohesive(). Short pile:Hu = 0.5*Kp*gamma*b*L^3/(e+L); long pile:Mmax = Hu(e + 2f/3) = Mywithf = sqrt(Hu/(1.5 Kp gamma b)).
- civilpy.geotech.lateral_pile.broms_cohesive(cu: float, b: float, length: float, yield_moment: float, e: float = 0.0) BromsResult[source]
Broms (1964) ultimate lateral load of a free-headed pile in cohesive soil. Resistance is neglected over the top
1.5*band taken as9*cu*bbelow it.cuundrained shear strength (psi),bdiameter (in),lengthembedded length (in),yield_momentplastic moment of the pile section (lb-in),eload height above ground (in). The lesser of the short-pile (soil) and long-pile (yield) failures governs.
- civilpy.geotech.lateral_pile.reese_sand_pu(phi_deg: float, gamma: float, b: float, z: float) float[source]
Reese (1974) ultimate sand resistance per unit length (lb/in), the lesser of the wedge (shallow) and flow-around (deep) failure values.
phi_degfriction angle,gammaeffective unit weight (pci),bdiameter (in),zdepth (in).
- civilpy.geotech.lateral_pile.sand_subgrade_modulus(phi_deg: float, submerged: bool = False) float[source]
Typical initial modulus of subgrade reaction k (pci) for sand from the API RP 2A / Reese charts, interpolated on friction angle. These are order-of-magnitude design values; use project-specific data when available.
- civilpy.geotech.lateral_pile.solve_lateral_pile(curves, length: float, ei: float, shear: float, moment: float = 0.0, n_elem: int = 100, fixed_head: bool = False, max_iter: int = 100, tol: float = 1e-06, relax: float = 0.5) LateralPileResult[source]
Solve a laterally loaded pile by finite elements on nonlinear p-y springs (the in-process equivalent of an LPILE run).
curvesis onePYCurvefor the whole pile or a callablecurve(z)returning the curve at depthz(in).lengthis the embedded length (in),eithe flexural stiffness (lb-in^2), andshear/momentthe load applied at the pile head (lb, lb-in). Afixed_headpile has zero head rotation. Soil springs use the secant modulus and are iterated with under-relaxationrelaxuntil the head deflection settles withintol.
- civilpy.geotech.lateral_pile.subgrade_constant_k(k: float, ei: float, shear: float, moment: float = 0.0) SubgradeResponse[source]
Long pile in soil of constant modulus
k(psi) – the Hetenyi semi-infinite beam-on-elastic-foundation solution.beta = (k/(4 EI))^{1/4}; head deflectiony0 = 2 beta (P + beta M)/kand slope-2 beta^2 (P + 2 beta M)/kfor head shearPand momentM. The point of fixity is taken at the rule-of-thumb1.4/beta.
- civilpy.geotech.lateral_pile.subgrade_linear_nh(nh: float, ei: float, shear: float, moment: float = 0.0) SubgradeResponse[source]
Long pile in soil of linearly increasing modulus
Es = nh*z(nhin pci) – the Matlock-Reese non-dimensional solution for a free head.Relative stiffness
T = (EI/nh)^{1/5}; ground-line deflectiony_g = Ay P T^3/EI + By M T^2/EIand maximum moment~Am P T(plus the applied head moment). Point of fixity is taken at the common1.8 Tfor sand.
civilpy.geotech.lpile module
LPILE (Ensoft) integration: input-file generation and output parsing.
LPILE has no COM/SDK automation interface, so – following the same
codegen-run-parse pattern as the CANDE box-culvert wrapper in
civilpy.structural.cande – this module integrates through LPILE’s
versioned ASCII data-file format. An LPileModel carries the pile
section, the soil layers (each backed by a p-y curve from
civilpy.geotech.lateral_pile, so the same models drive both the
in-process solver and the LPILE run), and the pile-head loading; it emits a
data file with LPileModel.to_lpd(). Output is read back from an LPILE
text report with parse_lpile_report() into an LPileResults
object holding the depth-wise deflection / moment / shear / soil-reaction
profiles and the pile-head response, with plotly plot helpers.
Because LPILE is rarely installed alongside civilpy,
LPileModel.simulate() runs the equivalent analysis with civilpy’s own
finite-element p-y solver and returns the same LPileResults, so a
model is fully usable (and round-trips through the report format) without
the Ensoft engine.
Soil layering can be sourced from a
SoilProfile (and therefore from a
parsed DIGGS boring) via LPileModel.from_soil_profile().
Units: inches, pounds, psi (unit weights pci), matching LPILE’s English
unit set and civilpy.geotech.lateral_pile.
- civilpy.geotech.lpile.DATA_FORMAT_VERSION = 11
LPILE ASCII data-file format this module targets. LPILE’s data exchange file is versioned (“Data Format Version 9/10/11”); we pin 11.
- class civilpy.geotech.lpile.LPileLoad(shear: float, moment: float = 0.0, axial: float = 0.0, condition: int = 1, slope: float = 0.0)[source]
Bases:
objectPile-head loading.
condition1 = shear + moment (free head), 2 = shear + slope (slope in radians, 0 for a fixed head). Forces in lb / lb-in.
- class civilpy.geotech.lpile.LPileModel(section: PileSection, layers: list[LPileSoilLayer], load: LPileLoad, n_increments: int = 100, cyclic: bool = False, n_cycles: int = 1, title: str | None = None)[source]
Bases:
objectAn LPILE single-pile model: section, soil layers, and head loading.
- curve_at(depth: float) PYCurve[source]
The p-y curve governing a given depth (in); the deepest layer extends below its nominal bottom.
- classmethod from_soil_profile(profile: SoilProfile, curves: list[PYCurve], section: PileSection, load: LPileLoad, **kwargs) LPileModel[source]
Build a model whose layers follow a
SoilProfile(feet, pcf), converting depths to inches.curvesis one p-y curve per soil layer (top to bottom).
- run(work_dir=None, prefix: str = 'pile', lpile_exe=None) LPileResults[source]
Run the model through an installed LPILE engine. LPILE has no automation API, so this writes the data file, invokes the LPILE command-line executable on it, and parses the text report. Raises if no executable is available – use
simulate()to analyze without Ensoft LPILE.
- simulate(**solver_kwargs) LPileResults[source]
Run the analysis with civilpy’s own FE p-y solver (no Ensoft engine needed) and return
LPileResults.
- class civilpy.geotech.lpile.LPileResults(depth: ndarray, deflection: ndarray, moment: ndarray, shear: ndarray, soil_reaction: ndarray, pile_head_deflection: float, max_moment: float, max_moment_depth: float, pile_head_rotation: float = 0.0, source: str = 'lpile')[source]
Bases:
objectDepth-wise pile response from an LPILE run or simulation.
- property lateral_stiffness: float
Secant pile-head lateral stiffness (lb/in) = head shear / head deflection, recovered from the shear at the top node.
- plot()[source]
A 1x4 plotly figure of deflection / moment / shear / soil reaction vs depth (depth increasing downward).
- to_report_text() str[source]
Format the results as an LPILE-style text report (the inverse of
parse_lpile_report()).
- class civilpy.geotech.lpile.LPileSoilLayer(top: float, bottom: float, curve: PYCurve, name: str = '')[source]
Bases:
objectOne LPILE soil layer over a depth range, backed by a p-y curve.
top/bottomare depths below the pile head (in);curveis thePYCurvesupplying both the LPILE p-y model parameters and the in-process simulation.
- class civilpy.geotech.lpile.PileSection(length: float, diameter: float, ei: float, modulus: float = 29000000.0, area: float | None = None)[source]
Bases:
objectA prismatic pile section.
lengthanddiameterin inches,eithe flexural stiffness (lb-in^2).areaandmodulusare optional (used only for the data-file fields and axial reporting); if omitted,modulusis taken as steel andareafrom a solid circle.
- civilpy.geotech.lpile.parse_lpile_report(text: str) LPileResults[source]
Parse an LPILE text report into
LPileResults.Reads the depth / deflection / moment / shear / soil-reaction table (any block of rows with five numeric columns under a header naming
DepthandDeflection) and the pile-head deflection, rotation, and maximum-moment summary lines.
civilpy.geotech.shallow_foundation module
Shallow (spread) foundation analysis and design.
Three families of routines, all pure functions or small dataclasses:
Bearing capacity – the general (Terzaghi / Meyerhof / Vesic) bearing capacity equation with shape, embedment-depth, and load-inclination modifiers, and Meyerhof’s effective-area reduction for eccentric loads. AASHTO LRFD 10.6.3.1; allowable-stress (factor of safety) and factored (resistance-factor) forms both fall out of one result object.
Contact pressure – the soil bearing-pressure distribution under a combined vertical load and moment (full-contact trapezoid, triangular with partial uplift) used to check the bearing demand and to load the footing as a structural element.
Settlement – Schmertmann strain-influence elastic settlement and one-dimensional primary consolidation, both able to source soil layering and effective stresses from
SoilProfile.
The footing’s own structural design (one-way shear, two-way punching shear,
flexural reinforcement) reuses the reinforced-concrete resistance functions
in civilpy.structural.aashto.lrfd.concrete rather than re-deriving
them here.
Units: feet, pounds-force, and pcf for the geotechnical side (pressures in psf, capacities reported in both psf and ksf); the structural helpers convert to the kip-inch-ksi convention the LRFD module expects. Angles in degrees.
- class civilpy.geotech.shallow_foundation.BearingCapacityFactors(nc: float, nq: float, ngamma: float, method: str)[source]
Bases:
objectDimensionless bearing-capacity factors Nc, Nq, Ngamma for a given friction angle and method.
- class civilpy.geotech.shallow_foundation.BearingCapacityResult(q_ult: float, factors: BearingCapacityFactors, b_eff: float, l_eff: float, terms: dict = <factory>, modifiers: dict = <factory>)[source]
Bases:
objectUltimate bearing capacity and the pieces an engineer would tabulate.
q_ultis the gross ultimate unit bearing pressure (psf);termsholds the cohesion, surcharge, and self-weight contributions.- factored_load(phi_b: float = 0.45) float[source]
Factored bearing resistance (lb), AASHTO LRFD 10.5.5.2.2;
phi_bdefaults to 0.45 (theoretical/semi-empirical methods).
- factors: BearingCapacityFactors
- class civilpy.geotech.shallow_foundation.ConsolidationLayer(layer_index: int, cc: float, e0: float, cr: float = 0.0, sigma_pc: float | None = None)[source]
Bases:
objectConsolidation parameters for one compressible stratum (by index into a
SoilProfile).
- class civilpy.geotech.shallow_foundation.ContactPressure(q_max: float, q_min: float, width: float, length: float, eccentricity: float, contact_length: float, uplift: bool)[source]
Bases:
objectSoil contact-pressure distribution under axial load
p(lb) at eccentricitye(ft) on a footing of widthwidth(ft, in the direction of the moment) and lengthlength(ft).
- civilpy.geotech.shallow_foundation.GAMMA_WATER = 62.4
Unit weight of water, pcf.
- class civilpy.geotech.shallow_foundation.SettlementResult(settlement_in: float, c1: float = 1.0, c2: float = 1.0, contributions: list = <factory>)[source]
Bases:
objectTotal settlement (in) and the correction factors / per-sublayer contributions that produced it.
- civilpy.geotech.shallow_foundation.bearing_capacity_factors(phi_deg: float, method: str = 'vesic') BearingCapacityFactors[source]
Bearing-capacity factors for friction angle
phi_deg.NqandNcfor Meyerhof/Hansen/Vesic are the Prandtl-Reissner formsNq = e^(pi*tan phi)*tan^2(45 + phi/2)andNc = (Nq - 1)*cot phi(5.14 at phi = 0). Terzaghi uses his ownNq = a^2/(2 cos^2(45 + phi/2))witha = e^((3pi/4 - phi/2) tan phi)andNc = 5.7at phi = 0.Ngammadiffers by method:Terzaghi –
2 (Nq + 1) tan phi / (1 + 0.4 sin 4phi)(approximation)Meyerhof –
(Nq - 1) tan(1.4 phi)Hansen –
1.5 (Nq - 1) tan phiVesic –
2 (Nq + 1) tan phi
- civilpy.geotech.shallow_foundation.bearing_water_table(gamma: float, gamma_sat: float, d: float, b: float, water_table: float) tuple[float, float][source]
Surcharge
qat footing level and the unit weight to use in the0.5*gamma*B*Ngammaterm, accounting for a water table at depthwater_table(ft below ground).gammais the moist weight above the table,gamma_satthe saturated weight below it. Three cases per Das: table below the failure wedge (d + b), within the wedge, and above footing level.
- civilpy.geotech.shallow_foundation.consolidation_settlement(profile: SoilProfile, layers: list[ConsolidationLayer], delta_sigma, n_slices: int = 1) SettlementResult[source]
One-dimensional primary consolidation settlement (in) of the compressible
layerswithinprofile.For each layer the initial effective stress
sigma'0is read at the layer midpoint fromprofileand the stress increasedelta_sigma(a constant psf or a callabledsigma(depth_ft)) is added. Normally consolidated soil (or no preconsolidation given) uses the virgin curveCc/(1+e0)*H*log10((s0+ds)/s0); over-consolidated soil uses the recompression indexCrwhile the final stress stays belowsigma_pcand splits acrosssigma_pcwhen it is exceeded.n_slicessub-divides each layer for a better midpoint stress.
- civilpy.geotech.shallow_foundation.contact_pressure(p: float, m: float, width: float, length: float) ContactPressure[source]
Bearing-pressure distribution from a vertical load
p(lb) and momentm(lb-ft) on a rectangular footing.With eccentricity
e = M/Pinside the middle third (e <= L/6) the pressure is trapezoidal,q = P/A * (1 +/- 6e/width). Outside the kern the heel lifts off and a triangular distribution develops over a contact length3*(width/2 - e)with peak2P/(length*contact)(the resultant must pass through the centroid of the triangle).
- civilpy.geotech.shallow_foundation.depth_factors(d: float, b: float, phi_deg: float) tuple[float, float, float][source]
Hansen embedment-depth factors (dc, dq, dgamma). For
d/b <= 1the factork = d/b; for deeper footingsk = arctan(d/b)(radians) so the modifier stays bounded.dgamma = 1.
- civilpy.geotech.shallow_foundation.footing_flexure(q_net: float, length: float, col_width: float, a_s: float, thickness_in: float, cover_in: float, f_c: float, f_y: float = 60.0, bar_dia_in: float = 1.0) CheckResult[source]
Flexural check of the footing cantilever, reusing
rc_rectangular_flexural_resistance().a_sis the reinforcement area in a 12-in design strip (in^2/ft);length/col_width(ft) set the cantilever moment. Effective depthd = thickness - cover - db/2.
- civilpy.geotech.shallow_foundation.footing_flexure_demand(q_net: float, length: float, col_width: float) float[source]
Factored cantilever moment
Mu(kip-in per foot of width) at the column face on a footing under net pressureq_net(psf). Span is(length - col_width)/2(ft).
- civilpy.geotech.shallow_foundation.footing_one_way_shear(q_net: float, width: float, length: float, col_width: float, thickness_in: float, cover_in: float, f_c: float, bar_dia_in: float = 1.0) CheckResult[source]
One-way shear check of a spread footing, reusing
rc_shear_resistance().thickness_inis the footing depth;d = thickness - cover - db/2. The full footingwidth(ft) is the shear widthbv. Returns the LRFD CheckResult (capacity phi*Vn vs demand Vu).
- civilpy.geotech.shallow_foundation.footing_punching_shear(p_u: float, col_b_in: float, col_l_in: float, thickness_in: float, cover_in: float, f_c: float, beta_c: float | None = None, bar_dia_in: float = 1.0, q_net: float = 0.0, lam: float = 1.0, phi_v: float = 0.9) CheckResult[source]
Two-way (punching) shear resistance at a footing (AASHTO 5.12.8.6.3):
Vn = (0.063 + 0.126/beta_c)*lam*sqrt(f’c)*b0*dv <= 0.126*lam*sqrt(f’c)*b0*dv
p_uis the factored column load (kip); the critical perimeterb0is takend/2outside a rectangular columncol_bxcol_l(in).beta_cis the column aspect ratio (defaults to the long/short side). The net upward pressure within the critical perimeter (q_netpsf) is credited back, so the demand isPuminus that relief. Result is in kip; phi_v = 0.9.
- civilpy.geotech.shallow_foundation.inclination_factors(h: float, v: float, b: float, l: float, phi_deg: float, c: float, area: float) tuple[float, float, float][source]
Vesic load-inclination factors (ic, iq, igamma) for a horizontal load
hand vertical loadv(consistent force units).areais the effective bearing area,cthe cohesion (same pressure unit as used elsewhere). For frictionless soil (phi = 0) only the cohesion term is reduced. Raises ifhexceeds the available sliding resistance.
- civilpy.geotech.shallow_foundation.nq_from_phi(phi_deg: float) float[source]
Reissner
Nq(used by the inclination factor’s cohesion term).
- civilpy.geotech.shallow_foundation.one_way_shear_demand(q_net: float, width: float, length: float, col_width: float, d_in: float) float[source]
Factored one-way (beam) shear
Vu(kip) at distancedfrom the column face on a footing carrying uniform net pressureq_net(psf).The critical section is at
d_in(in) from the face; the cantilever length is(length - col_width)/2 - d(ft).widthis the footing dimension perpendicular to the span. Returns 0 if the section falls outside the footing.
- civilpy.geotech.shallow_foundation.schmertmann_settlement(net_pressure: float, b: float, l: float, d: float, es_profile, gamma: float = 120.0, years: float = 1.0, n_sublayers: int = 20) SettlementResult[source]
Schmertmann (1978) strain-influence elastic settlement (in).
S = C1*C2*dq * sum( Iz/Es * dz )
net_pressureis the net applied pressure dq (psf);b/lthe footing plan dimensions anddthe embedment (ft).es_profileis either a constant Young’s modulus (psf) or a callableEs(depth_below_ footing_ft). C1 is the embedment correction1 - 0.5*(q'/dq) >= 0.5withq' = gamma*dthe overburden at footing level; C2 the creep factor1 + 0.2*log10(years/0.1). The strain-influence diagram peaks atIzp = 0.5 + 0.1*sqrt(dq/sigma'_vp).
- civilpy.geotech.shallow_foundation.shape_factors(b: float, l: float, phi_deg: float, nq: float, nc: float) tuple[float, float, float][source]
De Beer / Vesic shape factors (sc, sq, sgamma) for an effective footing
bbyl(b is the smaller plan dimension).nq/ncare the bearing-capacity factors.
- civilpy.geotech.shallow_foundation.stress_increase_2to1(q: float, b: float, l: float, z: float) float[source]
Vertical stress increase (same unit as
q) at depthzbelow abxlloaded area by the 2:1 (2 vertical : 1 horizontal) method:dsigma = q*B*L/((B+z)(L+z)).
- civilpy.geotech.shallow_foundation.ultimate_bearing_capacity(b: float, l: float, d: float, gamma: float, phi_deg: float, c: float = 0.0, method: str = 'vesic', shape: bool = True, depth: bool = True, ecc_b: float = 0.0, ecc_l: float = 0.0, h: float = 0.0, v: float | None = None, water_table: float | None = None, gamma_sat: float | None = None) BearingCapacityResult[source]
General bearing-capacity equation (AASHTO LRFD 10.6.3.1.2):
q_ult = c*Nc*sc*dc*ic + q*Nq*sq*dq*iq + 0.5*gamma*B'*Ngamma*sg*dg*ig
bandlare the plan dimensions (ft,b <= l),dthe embedment depth,gammathe soil unit weight (pcf),cthe cohesion (psf). Eccentricitiesecc_b/ecc_l(ft) trigger Meyerhof’s effective-width reductionB' = B - 2e. A horizontal loadhwith verticalv(lb) brings in the inclination factors.water_table(ft) withgamma_sat(pcf) adjusts the surcharge and self-weight terms.
civilpy.geotech.soil_profile module
Soil profiles: boring-log style layer columns and the total/pore/ effective vertical stress diagram every soils course draws.
Units: ft and pcf in, psf out.
Examples
>>> sp = SoilProfile([SoilLayer("Sand", 10, 115), SoilLayer("Clay", 15, 105)])
>>> sp.water_table = 10
>>> total, pore, eff = sp.stresses_at(25)
>>> round(total, 0), round(pore, 0), round(eff, 0)
(2725.0, 936.0, 1789.0)
- class civilpy.geotech.soil_profile.SoilLayer(name, thickness, gamma, color=None)[source]
Bases:
SoilLayerOne stratum:
thicknessft of soil at total unit weightgammapcf;coloroptional for the log plot.
- class civilpy.geotech.soil_profile.SoilProfile(layers: list[SoilLayer], water_table: float | None = None)[source]
Bases:
object- plot(ax=None, spt=None)[source]
Boring-log column with layer names; optional
sptlist of (depth, N) plotted alongside.
civilpy.geotech.spt module
SPT blow-count correlations: the derived-parameter engine that turns a Standard Penetration Test N value into the soil properties the downstream libraries need.
These are published, widely used empirical correlations. They are estimates only – approximate and scatter-prone – and should never replace laboratory testing where it is available; they exist so a boring log with nothing but blow counts can still seed a calculation.
Units are US customary: stresses in psf, unit weights in pcf, moduli in
psi, angles in degrees. N arguments are field blow counts unless the
name says n60 (energy-corrected) or n1_60 (energy- and
overburden-corrected).
References
Liao & Whitman (1986) – overburden correction CN.
Skempton (1986) – N60 corrections and relative density.
Hatanaka & Uchida (1996) – friction angle from (N1)60.
Stroud (1974) – undrained shear strength from N.
Bowles, Foundation Analysis and Design, 5th ed. (1996) – elastic modulus from N.
- civilpy.geotech.spt.PATM_PSF = 2000.0
Atmospheric pressure used to normalise overburden, psf (~1 tsf).
- civilpy.geotech.spt.elastic_modulus_from_spt(n: float, soil_type: str = 'sand') float[source]
Drained Young’s modulus Es (psi) from N (Bowles 1996, Es = a (N + b) in kPa).
soil_typeselects the coefficients:"sand","sand_saturated","gravelly_sand","silty_sand", or"clayey_sand".
- civilpy.geotech.spt.elastic_modulus_from_su(su_psf: float, modulus_ratio: float = 300.0) float[source]
Undrained Young’s modulus Eu (psi) of a clay as
modulus_ratiotimes the undrained shear strength: Eu = beta * Su.modulus_ratiobeta ~ 150 (soft) to 600 (stiff, OC) clays; 300 is a common default.
- civilpy.geotech.spt.friction_angle_from_n(n1_60_value: float) float[source]
Effective friction angle phi’ (degrees) of a sand from (N1)60 (Hatanaka & Uchida 1996): phi’ = sqrt(20 (N1)60) + 20.
- civilpy.geotech.spt.n1_60(n60: float, sigma_v_eff_psf: float, cap: float = 1.7) float[source]
Energy- and overburden-corrected blow count (N1)60 = CN * N60.
- civilpy.geotech.spt.overburden_correction(sigma_v_eff_psf: float, cap: float = 1.7) float[source]
Overburden normalisation factor CN (Liao & Whitman 1986): CN = sqrt(Pa / sigma’_v), capped at
cap(1.7 typical, 2.0 sometimes used).sigma_v_eff_psfis the effective vertical stress at the test depth.
- civilpy.geotech.spt.relative_density_from_n(n1_60_value: float, constant: float = 60.0) float[source]
Relative density Dr (fraction 0-1) of a sand from (N1)60 (Skempton 1986): Dr = sqrt((N1)60 /
constant), clamped to 1.0.
- civilpy.geotech.spt.undrained_shear_strength_from_n(n60: float, factor_psf: float = 92.0) float[source]
Undrained shear strength Su (psf) of a fine-grained soil from N60 (Stroud 1974): Su = f1 * N60.
factor_psff1 ~ 92 psf (4.4 kPa) is a representative value for insensitive clays; it ranges roughly 75-150 psf (3.5-7 kPa) with plasticity.
- civilpy.geotech.spt.unit_weight_from_n(n: float, coarse: bool = True) float[source]
Rough total unit weight (pcf) from N when no laboratory value is available, after the Terzaghi-Peck consistency/density descriptions.
coarseTrue for sands/gravels (by relative density), False for clays/silts (by consistency). These are mid-range representative values, not a substitute for measured unit weights.
Module contents
Geotechnical engineering package.
Re-exports the boring-log data model (Borehole,
samples, SPT results, gradations) and the DIGGS / PDF log parsers from
civilpy.geotech.boring_io, plus quick lateral earth-pressure helpers
(Rankine/Coulomb). Deeper analyses live in the submodules: spt
(corrections and correlations), shallow_foundation / deep_foundation,
axial_load_transfer, lateral_pile / lpile, soil_profile,
lateral_earth, and culmanns.
civilpy.geotech.cande_adapter is intentionally not imported here so
that importing this package does not pull in civilpy.structural.
- civilpy.geotech.coulomb_active_pressure(unit_weight, height, friction_angle, wall_friction_angle, backfill_inclination, wall_inclination)[source]
Calculate active earth pressure against an abutment using the Coulomb method.
Parameters: unit_weight (float): Unit weight of the soil (kN/m³ or lb/ft³) height (float): Height of the abutment (meters or feet) friction_angle (float): Internal friction angle of the soil (degrees) wall_friction_angle (float): Angle of wall friction (delta) (degrees) backfill_inclination (float): Angle of inclination of the backfill surface (theta) (degrees) wall_inclination (float): Inclination of the back side of the wall (beta) (degrees)
Returns: float: Active earth pressure (kN/m² or lb/ft²)
- civilpy.geotech.coulomb_active_pressure_with_surcharge(unit_weight, height, friction_angle, wall_friction_angle, backfill_inclination, wall_inclination, surcharge_load)[source]
Calculate active earth pressure against an abutment using the Coulomb method with a surcharge load.
Parameters: unit_weight (float): Unit weight of the soil (kN/m³ or lb/ft³) height (float): Height of the abutment (meters or feet) friction_angle (float): Internal friction angle of the soil (degrees) wall_friction_angle (float): Angle of wall friction (delta) (degrees) backfill_inclination (float): Angle of inclination of the backfill surface (theta) (degrees) wall_inclination (float): Inclination of the back side of the wall (beta) (degrees) surcharge_load (float): Surcharge load at the surface (kN/m² or lb/ft²)
Returns: float: Active earth pressure (kN/m² or lb/ft²)
- civilpy.geotech.culmann_lateral_pressure(unit_weight, height, cohesion, friction_angle, wall_friction_angle, num_slices=100)[source]
Calculate horizontal lateral earth pressure using Culmann’s method.
Parameters: unit_weight (float): Unit weight of the soil (kN/m³) height (float): Height of the wall (meters) cohesion (float): Cohesion of the soil (kPa) friction_angle (float): Internal friction angle of the soil (degrees) wall_friction_angle (float): Wall friction angle (degrees) num_slices (int): Number of slices for the graphical method
Returns: float: Horizontal lateral earth pressure (kPa)
- civilpy.geotech.culmann_lateral_pressure_with_surcharge(unit_weight, height, cohesion, friction_angle, wall_friction_angle, surcharge_load, num_slices=100)[source]
Calculate horizontal lateral earth pressure using Culmann’s method including a live load surcharge.
Parameters: unit_weight (float): Unit weight of the soil (kN/m³) height (float): Height of the wall (meters) cohesion (float): Cohesion of the soil (kPa) friction_angle (float): Internal friction angle of the soil (degrees) wall_friction_angle (float): Wall friction angle (degrees) surcharge_load (float): Live load surcharge at the surface (kPa) num_slices (int): Number of slices for the graphical method
Returns: float: Horizontal lateral earth pressure (kPa)
- civilpy.geotech.rankine_active_pressure(unit_weight, height, friction_angle)[source]
Calculate active earth pressure against an abutment using the Rankine method.
Parameters: unit_weight (float): Unit weight of the soil (kN/m³ or lb/ft³) height (float): Height of the abutment (meters or feet) friction_angle (float): Internal friction angle of the soil (degrees)
Returns: float: Active earth pressure (kN/m or lb/ft)
- civilpy.geotech.rankine_active_pressure_with_surcharge(unit_weight, height, friction_angle, surcharge_load)[source]
Calculate active earth pressure against an abutment using the Rankine method with a surcharge load.
Parameters: unit_weight (float): Unit weight of the soil (kN/m³ or lb/ft³) height (float): Height of the abutment (meters or feet) friction_angle (float): Internal friction angle of the soil (degrees) surcharge_load (float): Surcharge load at the surface (kN/m² or lb/ft²)
Returns: float: Active earth pressure (kN/m² or lb/ft²)