Skip to main content

Structural Engineering Utilities

Project description

alt text

What's PyCivil

A Python library for structural engineers that aims to make them as free as possible from commercial software while preserving their knowledge.

Version: 0.2.21 | Python: 3.9 - 3.13 | License: BSD-3-Clause

Source Code: GitLab

Features

  1. EXAGeometry - Low-level geometry classes for 2D/3D spatial calculations: Point2d, Point3d, Vector2d, Vector3d, Polyline2d, Polyline3d, Edge, Node, ShapeRect, ShapeCircle, ShapePoly

  2. EXAStructural - Core structural engineering domain models:

    • sections.py - Reinforced concrete section models (RectangularShape, TShape, IShape, polygonal shapes) with reinforcement disposers
    • materials.py - Concrete and Steel material definitions with code-based properties
    • loads.py - Load and force representations with limit state enums
    • codes.py - Code management system for EC2, NTC2008, NTC2018
    • templateRCRect.py - RC rectangular section template with SLS/SLU analysis and fire design
  3. EXAStructural/lawcodes - Implementation of structural codes with rules, strength formulas, loads and materials:

    • codeEC211.py - Eurocode 2-1-1 (concrete in compression)
    • codeEC212.py - Eurocode 2-1-2 (fire design rules)
    • codeNTC2018.py - Italian NTC2018 standard
  4. EXAStructural/rcrecsolver - Solver for checking rectangular reinforced concrete sections under bending, axial and shear forces

  5. EXAStructural/rcgensolver - Solver for checking generic shaped reinforced concrete sections under bending, axial and shear forces

  6. EXAStructuralModel - FEM-agnostic finite element modeler (FEModel) with support for various load types, materials, section shapes, GMSH mesh generation, and MIDAS export

  7. EXAStructuralCheckable - Structural verification against design codes with multiple criteria: SLE-NM, SLE-F, SLU-NM, SLU-T, SLU-NM-FIRE, and crack severity classification

  8. EXAParametric - Parametric structural analysis for box and tube sections

  9. EXAGeotechnical - Geotechnical formulas and soil mechanics: Young's modulus tables, Poisson's ratio tables, Winkler foundation model, Bussinesque formulas

  10. EXAUtils - Utilities and tools:

    • strand7PostPro.py - Post-processor for Strand7 FEM results
    • ucasefe.py - High-level RC section calculator API
    • latexReportMakers.py - LaTeX-based report generation (PDF output)
    • typstReportMakers.py - Typst-based report generation (PDF output, no LaTeX required)
    • report.py - Report infrastructure with Reporter (LaTeX), MarkdownReporter (Markdown/HTML), and TypstReporter (Typst/PDF)
    • latexCheatSheets.py - Quick reference sheet generation
    • vtk.py - VTK visualization wrapper
    • gmsh.py - GMSH mesh generation wrapper

Quick Start

Geometry Basics

from pycivil.EXAGeometry.geometry import Point2d, Point3d, Vector2d, Polyline2d, Node2d

# 2D Points
p1 = Point2d(0, 0)
p2 = Point2d(100, 200)
distance = p1.distance(p2)
midpoint = p1.midpoint(p2)

# 2D Vectors
v = Vector2d(p1, p2)
v.normalize()

# Polylines
nodes = [
    Node2d(0.0, 0.0, 1),
    Node2d(300.0, 0.0, 2),
    Node2d(300.0, 500.0, 3),
    Node2d(0.0, 500.0, 4),
]
poly = Polyline2d(nodes)
poly.setClosed()

RC Section Analysis (SLS)

from pycivil.EXAStructural.codes import Code
from pycivil.EXAStructural.materials import Concrete, ConcreteSteel
from pycivil.EXAStructural.templateRCRect import RCTemplRectEC2

# Set code and materials
code = Code("NTC2018")

concrete = Concrete(descr="My concrete")
concrete.setByCode(code, "C25/30")

steel = ConcreteSteel(descr="My steel")
steel.setByCode(code, "B450C")

# Create rectangular RC section
rcSection = RCTemplRectEC2(1, "Beam Section")
rcSection.setDimH(600)  # height in mm
rcSection.setDimW(300)  # width in mm

# Add reinforcement (LINE-MB = bottom, LINE-MT = top)
rcSection.addSteelArea("LINE-MB", dist=50, d=20, nb=4, sd=40)  # 4Ø20 bottom
rcSection.addSteelArea("LINE-MT", dist=50, d=20, nb=4, sd=40)  # 4Ø20 top

# Calculate section properties
print(f"Concrete area: {rcSection.calConcreteArea()} mm²")
print(f"Steel area: {rcSection.calSteelArea():.0f} mm²")
print(f"Ideal area: {rcSection.calIdealArea():.0f} mm²")

# SLS analysis under N and M
KN = 1000
KNm = 1000 * 1000
N = -1000 * KN   # axial force (negative = compression)
M = 150 * KNm    # bending moment

sigmac, sigmas, xi = rcSection.solverSLS_NM(N, M, uncracked=True)
print(f"Concrete stress: {sigmac:.2f} MPa")
print(f"Steel stress: {sigmas:.2f} MPa")
print(f"Neutral axis: {xi:.2f} mm")

Section Modeler

from pycivil.EXAStructural.modeler import SectionModeler

# Create modeler
md = SectionModeler()
md.addSection(1, True)

# Define concrete shape (300x600 rectangle)
md.addNode(1, 0, 0)
md.addNode(2, 300, 0)
md.addNode(3, 300, 600)
md.addNode(4, 0, 600)
md.addTriangle(1, 1, 2, 3)
md.addTriangle(2, 3, 4, 1)

# Add bottom reinforcement (4Ø28)
for i, x in enumerate([60, 120, 180, 240]):
    md.addNode(20 + i, x, 40)
    md.addCircle(20 + i, 20 + i, 28 / 2)

# Add top reinforcement (4Ø16)
for i, x in enumerate([60, 120, 180, 240]):
    md.addNode(10 + i, x, 560)
    md.addCircle(10 + i, 10 + i, 16 / 2)

# Calculate properties
print(f"Solid barycenter: {md.calcSolidBarycenter()}")
print(f"Solid area: {md.calcSolidArea()} mm²")
print(f"Point area (rebars): {md.calcPointArea():.0f} mm²")

ULS Interaction Domain (N-M)

from pycivil.EXAStructural.codes import Code
from pycivil.EXAStructural.materials import Concrete, ConcreteSteel
from pycivil.EXAStructural.templateRCRect import RCTemplRectEC2

# Set code and materials
code = Code("NTC2018")

concrete = Concrete(descr="My concrete")
concrete.setByCode(code, "C25/30")

steel = ConcreteSteel(descr="My steel")
steel.setByCode(code, "B450C")

# Create rectangular RC section
rcSection = RCTemplRectEC2(1, "Beam Section")
rcSection.setDimH(600)  # height in mm
rcSection.setDimW(300)  # width in mm

# Add reinforcement
rcSection.addSteelArea("LINE-MB", dist=50, d=20, nb=4, sd=40)  # 4Ø20 bottom
rcSection.addSteelArea("LINE-MT", dist=50, d=16, nb=4, sd=40)  # 4Ø16 top

# Build ULS interaction domain (N-M)
pointCloud, bounding = rcSection.interactionDomainBuild2d(
    nbPoints=100, SLS=False, bounding=True
)

# Bounding box: [Nmin, Nmax, Mmin, Mmax]
print(f"N range: {bounding[0]/1000:.0f} to {bounding[1]/1000:.0f} kN")
print(f"M range: {bounding[2]/1e6:.0f} to {bounding[3]/1e6:.0f} kNm")

# Check if a load point is inside the domain
N_ed = -200.0 * 1000  # -200 kN (compression)
M_ed = 100.0 * 1e6    # 100 kNm

contained, pintersect, intfactor, pindex = pointCloud.contains(
    N_ed, M_ed, rayFromCenter=True,
    ro=(bounding[1] - bounding[0], bounding[3] - bounding[2])
)

print(f"Load N_Ed={N_ed/1000:.0f} kN, M_Ed={M_ed/1e6:.0f} kNm")
print(f"Inside domain: {contained}")
print(f"Utilization factor: {1/intfactor:.2f}")

Critical Moment (Cracking Moment)

from pycivil.EXAStructural.codes import Code
from pycivil.EXAStructural.materials import Concrete, ConcreteSteel
from pycivil.EXAStructural.templateRCRect import RCTemplRectEC2

# Set code and materials
code = Code("NTC2018")

concrete = Concrete(descr="My concrete")
concrete.setByCode(code, "C25/30")

steel = ConcreteSteel(descr="My steel")
steel.setByCode(code, "B450C")

# Create rectangular RC section
rcSection = RCTemplRectEC2(1, "Beam Section")
rcSection.setDimH(600)  # height in mm
rcSection.setDimW(300)  # width in mm

# Add reinforcement
rcSection.addSteelArea("LINE-MB", dist=50, d=20, nb=4, sd=40)  # 4Ø20 bottom
rcSection.addSteelArea("LINE-MT", dist=50, d=16, nb=4, sd=40)  # 4Ø16 top

# Calculate critical moment (moment that cracks the section)
KN = 1000
KNm = 1000 * 1000

# Without axial force
mcr_pos, mcr_neg = rcSection.calCriticalMoment()
print(f"Mcr+ = {mcr_pos/KNm:.2f} kNm")   # 63.16 kNm
print(f"Mcr- = {mcr_neg/KNm:.2f} kNm")   # -59.87 kNm

# With compressive axial force (N = -500 kN)
mcr_pos, mcr_neg = rcSection.calCriticalMoment(N=-500 * KN)
print(f"Mcr+ (with N) = {mcr_pos/KNm:.2f} kNm")  # 122.59 kNm
print(f"Mcr- (with N) = {mcr_neg/KNm:.2f} kNm")  # -116.19 kNm

RC Section Checker (ucasefe)

from pycivil.EXAUtils.ucasefe import RCRectCalculator

# Create calculator
calc = RCRectCalculator("My Project", "Beam B1")
calc.setLogLevel(0)  # quiet mode
calc.setJobPath("/path/to/output")  # where reports will be saved

# Units
KN = 1000
KNm = 1000000

# Section dimensions (mm)
calc.setDimensions(w=300, h=600)

# Materials
calc.setMaterialConcrete("NTC2018", "C25/30", "not aggressive")
calc.setMaterialRebars("NTC2018", "B450C", "not sensitive")

# Reinforcement
calc.addRebarsFromTop(num=4, diam=20, dist_from_top=40, dist_rebars=40)
calc.addRebarsFromBot(num=4, diam=20, dist_from_bot=40, dist_rebars=40)
calc.setStirrup(area=100, step=150, angle=90)

# Add load cases with checks
calc.addForce(N=-100*KN, M=145*KNm, T=120*KN,
              limit_state="serviceability", frequency="quasi-permanent",
              check_required=["SLE-NM", "SLE-F"], descr="Load case 1")

calc.addForce(N=-200*KN, M=200*KNm, T=200*KN,
              limit_state="ultimate",
              check_required=["SLU-T", "SLU-NM"], descr="Load case 2")

# Run analysis and build report
if calc.run():
    # Choose your preferred output format:
    calc.buildReport()          # LaTeX/PDF report (requires LaTeX installation)
    calc.buildMarkdownReport()  # Markdown report (no external dependencies)
    calc.buildHtmlReport()      # HTML report with MathJax for formulas
    calc.buildTypstReport()     # Typst/PDF report (no LaTeX required)

Install

For production with Windows or Linux

PyCivil releases are available as wheel packages for Windows and Linux on PyPI:

pip install pycivil

For development in Windows

Install uv

$installDir = "$env:USERPROFILE\.local\bin"
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
$env:UV_NATIVE_TLS = "true"
setx UV_NATIVE_TLS true

Prerequisites

  1. LaTeX installation (optional - only needed for PDF reports via LaTeX; Markdown/HTML reports work without it)
  2. Docker Engine (optional - useful if you need to generate thermal maps or use Code Aster)

Changelog

See CHANGELOG.md for version history.

Docs

The documentation is built with MkDocs and the Material theme.

Serve documentation locally

Start a local development server with live-reload:

task docs

This will start a server at http://127.0.0.1:8000 where you can browse the documentation.

Build static documentation

To build the static HTML documentation:

uv run --only-group docs mkdocs build

The output will be generated in the site/ directory.

NOTE: The documentation is still being written. In the meantime, check the tutorials and the tests for practical examples.

Development

  • Install task
  • run task init do initialize the python environment and install the pre-commit hooks
  • before committing code changes, you can run task to perform automated checks. You can also run them separately:
    • task lint fixes and checks the code and documentation
    • task mypy performs type checking
    • task test runs the tests with pytest
    • task security scans the dependencies for known vulnerabilities

NOTE: the lint task is executed automatically when you commit the changes to ensure that only good quality code is added to the repository.

Docker container

If you're a docker-compose guy, you can run the docker-compose.yml file with:

docker-compose up --build

This will also create Code_Aster containers, and you will be able to use Code_Aster as FEM solver.

Remove all volumes

This remove all volumes and data. Next relaunch the volumes will be build

docker-compose down -v

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pycivil-0.2.22.tar.gz (3.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pycivil-0.2.22-py3-none-any.whl (358.1 kB view details)

Uploaded Python 3

File details

Details for the file pycivil-0.2.22.tar.gz.

File metadata

  • Download URL: pycivil-0.2.22.tar.gz
  • Upload date:
  • Size: 3.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pycivil-0.2.22.tar.gz
Algorithm Hash digest
SHA256 50789cd4857c985f634cd8b37951d05fb41ce238f3da69612e7aa050ca4e2f90
MD5 c127c63000f6eb8721ec74b502e7127c
BLAKE2b-256 e457d85cfadf0e8033202e9f78fcd44c0a4a3d55bd37f35bc8bbae4d4fd3b856

See more details on using hashes here.

File details

Details for the file pycivil-0.2.22-py3-none-any.whl.

File metadata

  • Download URL: pycivil-0.2.22-py3-none-any.whl
  • Upload date:
  • Size: 358.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pycivil-0.2.22-py3-none-any.whl
Algorithm Hash digest
SHA256 bb1f339e7b30ef5aff15fb32b4a9daffbda5156c31aee060cb602463ead9623e
MD5 0de754dd89f018182df436cad22ae630
BLAKE2b-256 608625e6930834a6ac0701853fb80051832791a8879eddfb6e455f1b70ff65ac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page