How-to Guides
Practical recipes for common tasks. Unlike tutorials, each guide assumes you already have EurocodePy installed and focuses on getting one specific thing done.
How to look up a material
import eurocodepy as ec
# Concrete — access all grades via the enum
concrete = ec.Concrete('C25/30')
print(concrete.fck, concrete.fcd, concrete.Ecm)
# Steel
steel = ec.Steel('S275')
print(steel.fyk, steel.fuk)
# Timber
timber = ec.Timber('GL28h')
print(timber.fmk, timber.E0mean)
Alternatively browse the raw database:
# List all available concrete grades
print(list(ec.ConcreteGrades))
# List all reinforcement grades
print(list(ec.ReinforcementGrades))
# List all timber grades
print(list(ec.TimberGrades))
How to access Portuguese national annex parameters
from eurocodepy import NationalParams, get_national_params, seismic_get_params, wind_get_params
# Data of a municipality (seismic zones, accelerations, snow and wind zones, temperatures)
data = get_national_params(concelho='Coimbra')
print(data['ZonaSismica1'], data['Acel1'], data['ZonaVento'])
# Spectrum parameters of the Portuguese NA: code, type, soil, importance class
seismic = seismic_get_params('PT', 'PT1', 'C', 'ii')
print(seismic) # S_max, S_min, a_g1, a_g2, T_B, T_C, T_D, ImportanceCoef
# Wind: vb,0, z_min, z_0 and z_0,II of a zone and terrain category
vb0, z_min, z0, z0_ii = wind_get_params('PT', 'ZonaA', 'II')
# NationalParams holds the locale and the municipality (default: Lisboa)
params = NationalParams(concelho='Braga')
print(params.local, params.concelho)
How to define a unit system
from eurocodepy.units import SI, kN_mm, N_mm, UnitType
# Each system gives the SI value of its units
print(SI.force, SI.distance, SI.pressure) # N, m, Pa
print(kN_mm.force, kN_mm.distance, kN_mm.pressure) # kN, mm, kN/mm²
print(N_mm.force, N_mm.distance, N_mm.pressure) # N, mm, N/mm²
# Factor that converts a value from one system to another
f = SI.convert_to(kN_mm, UnitType.FORCE) # newtons -> kilonewtons: 0.001
How to build load combinations
from eurocodepy.ec1 import Load, LoadType, Loads
loads = Loads()
# name type γ fav γ unf ψ0 ψ1 ψ2
loads.add(Load("G", LoadType.PERMANENT, 1.0, 1.35, 0.0, 0.0, 0.0))
loads.add(Load("Q", LoadType.LIVE, 0.0, 1.50, 0.7, 0.5, 0.3))
loads.add(Load("W", LoadType.WIND, 0.0, 1.50, 0.6, 0.2, 0.0))
values = {"G": 20.0, "Q": 8.0, "W": 4.0} # characteristic values [kN/m²]
# ULS (EN 1990 Eq. 6.10): a dict {name: LoadCombination}; factors = {load name: (Load, factor)}
for name, combo in loads.get_ULS_combos().items():
total = sum(factor * values[k] for k, (_, factor) in combo.factors.items())
print(f"{name:34s} {total:7.2f}")
# SLS characteristic, frequent and quasi-permanent
for name, combo in loads.get_SLS_combos().items():
print(name)
How to calculate creep and shrinkage (EN 1992-1-1:2023, Annex B)
from eurocodepy.ec2.sls.creep import creep_coef
from eurocodepy.ec2.sls.shrinkage import shrink_strain
# C30/37: fcm,28 = 38 MPa; RH = 60 %; hn = 2Ac/u = 200 mm; class CN
# Creep coefficient φ(t, t0): loaded at t0 = 28 days, t = 50 years
phi = creep_coef(t=18250 + 28, t0=28, fcm28=38.0, RH=60, hn=200, t0_T=28, concrete_class="CN")
print(f"φ = {phi:.2f}")
# Total shrinkage strain, drying from ts = 1 day (alpha_NDP_b = alpha_NDP_d = 1: recommended)
eps_cs = shrink_strain(t=18251, ts=1, fcm28=38.0, RH=60, hn=200, concrete_class="CN",
alpha_NDP_b=1.0, alpha_NDP_d=1.0)
print(f"εcs = {eps_cs:.6f}")
How to follow the strain history of a concrete member (EN 1992-1-1:2023, Annex B)
from eurocodepy.ec2 import time_dependent2023 as td
fcm, ecm = 38.0, 33000.0 # C30/37: fcm,28 and Ecm,28 [MPa]
common = dict(fcm28=fcm, ecm28=ecm, rh=60.0, hn=200.0, cls="CN")
# Compressive stress of 10 MPa applied at 28 days, 5 MPa more at 90 days: stress-dependent strain at 50 years
eps = td.strain_history(18278, [(28, -10.0), (90, -5.0)], **common)
# Compliance J(t, t0) and the shrinkage at the same age
j = td.creep_compliance(18278, 28, **common) # 1/MPa
eps_cs = td.shrinkage_total(18278, 1, fcm, rh=60.0, hn=200.0, cls="CN")
How to use the partial factors of another design situation (EN 1992-1-1:2023, Table 4.3)
from eurocodepy.ec2 import Concrete, material_partial_factors
material_partial_factors("2023", "accidental") # γs, γc, γce, γv of the situation
accidental = Concrete("C30/37", edition="2023", situation="accidental")
print(accidental.gamma_c, accidental.fcd)
The check inputs (PunchInput, ShearInput, MembraneInput, …) have from_partial_factors(edition, situation, ...).
How to produce a calculation report
Most checks accept trace= with a CalcReport: each step (symbol, value, unit, clause, expression) is recorded
and the report can be written as a dictionary, JSON or Markdown with LaTeX.
from eurocodepy.calc_report import CalcReport
from eurocodepy.ec2.uls import design_anchorage_length
report = CalcReport(title="Anchorage of a ϕ16 bar")
anchorage = design_anchorage_length(phi=16, fck=30, fyk=500, cd=40, good_bond=True, trace=report)
print(report.to_markdown()) # sections with the clause and the formula of each step
data = report.to_dict() # {'schema_version', 'title', 'meta', 'sections': [...]}
The checks of EC2 (uls, uls2023), EC3 (section_check_profile, member_check_profile,
classify_section) and EC5 take it; with trace=None (the default) nothing is recorded.
How to check shear resistance of a concrete beam (EN 1992)
from eurocodepy.ec2.uls.shear import calc_vrdc, calc_vrd, calc_vrdmax, calc_asws
# Section and material
b_w = 0.30 # web width [m]
d = 0.46 # effective depth [m]
rho = 0.0117 # tensile reinforcement ratio As/(b_w·d)
fck, g_c = 30, 1.5 # [MPa]
fyk, g_s = 500, 1.15 # shear reinforcement [MPa]
# Design shear resistance without shear reinforcement [kN]
vrd_min, vrd_c, vrd = calc_vrdc(b_w, d, fck, g_c, rho)
print(f"VRd,c = {vrd:.1f} kN")
# Required shear reinforcement for VEd = 180 kN, cot θ = 2
asw_s, vrd_max = calc_asws(b_w, d, fck, g_c, fyk, g_s, 2.0, 180.0)
print(f"Asw/s = {asw_s * 1e4:.2f} cm²/m (VRd,max = {vrd_max:.0f} kN)")
How to compute earth pressures (EN 1997)
import numpy as np
from eurocodepy.ec7 import pressure_coefficients, EarthPressureModels
phi = np.radians(30.0) # soil friction angle
delta = np.radians(15.0) # wall friction angle
theta = 0.0 # slope of the backfill
beta = 0.0 # slope of the wall
# Ka, Kp, Kaq, Kpq, dkas1, dkps1, dkas2, dkps2
Ka, Kp, *_ = pressure_coefficients(phi, delta, theta, beta, method=EarthPressureModels.COULOMB)
print(f"Ka = {Ka:.3f}, Kp = {Kp:.3f}")
How to plot and export a seismic spectrum
from eurocodepy.ec8.spectrum import get_spectrum_ec8, draw_spectrum_ec8, write_spectrum_ec8
spec = get_spectrum_ec8(
locale='EU', code='CEN_1',
imp_class='II', soil='B',
zone='.3g', behaviour=4.0,
)
# Display the plot interactively
draw_spectrum_ec8(spec, show=False) # show=True opens the window
# Save a CSV for import into SAP2000, ETABS, etc.
write_spectrum_ec8(spec, filename='spectrum_EU_CEN1_II_B_03g_q4.csv')
How to calculate section properties
from eurocodepy.utils import RectangularCrossSection
section = RectangularCrossSection(0.30, 0.60) # m
print(section.area, section.inertia_y, section.bend_mod_y)
For reinforced sections (cracked and uncracked properties) see
utils.calc_section_rectangular in the utils module.
How to use a National Annex
The values in eurocodes.json are the ones recommended by the Eurocodes. What a National
Annex changes is a patch kept in its own file, data/national_annexes/<COUNTRY>.json
(Portugal's is built in: its wind, seismic and live-load data). The functions that depend on
Nationally Determined Parameters take annex= with the country code:
from eurocodepy.ec2 import Concrete, material_partial_factors
from eurocodepy.ec2.uls2023 import detailing
Concrete("C30/37", edition="2023", annex="PT") # the annex's values, if it has any
material_partial_factors("2023", "persistent") # annex=None: the Eurocode's values
detailing.beam_max_spacings(0.5, annex="PT")
An unknown code raises ValueError and lists the available ones. Add your own annex (a JSON
file or a dict) with register_annex; it has the same shape as the Editions entries of
eurocodes.json, so it patches one value of a table and leaves the rest as recommended:
import eurocodepy as ec
ec.register_annex({
"country": "XX",
"editions": {"ec2": {"2023": {
"partial_factors": {"materials": {"persistent": {"gamma_c": 1.4}}},
"detailing": {"beams": {"s_l_max": 0.7}},
}}},
})
Concrete("C30/37", edition="2023", annex="XX").gamma_c # 1.4
ec.available_annexes() # ['PT', 'XX']
loads (wind, seismic, live) in the file add the country next to EU, so
wind_get_params("XX", ...) and the EC1/EC7/EC8 functions find it. The package only ships the
values it can source; it never invents an annex.