A Python library for hydraulic system analysis of IFC (Industry Foundation Classes) building models. ifc-hydro provides tools for analyzing cold water supply systems in building information models, including topology creation, property extraction, and hydraulic calculations.
- Topology Analysis: Create graph representations of hydraulic system connections from IFC models
- Property Extraction: Extract geometric and type properties from pipes, fittings, and valves
- Hydraulic Calculations: Perform flow analysis, pressure drop calculations, and available pressure determination
- Angle-Aware Analysis: Direction change detection in JUNCTION fittings for accurate pressure drop calculations
- Comprehensive Error Handling: Validates IFC elements and provides meaningful error messages
- IFC Integration: Direct integration with IFC models using IfcOpenShell
- Centralized Reference Data: Lookup tables for hydraulic coefficients and design flow rates
- Logging: Built-in logging system for debugging and analysis tracking
git clone https://github.com/andrebmuller/ifc-hydro.git
cd ifc-hydro
pip install -e .- Python 3.7 or higher
- IfcOpenShell library (installed automatically with setup)
import ifcopenshell as ifc
from ifc_hydro import Base, Topology, Pressure
import sys
# Configure logging
Base.configure_log(Base, log_dir="logs", log_name="my-analysis")
# Load IFC model with error handling
try:
model = ifc.open('your_model.ifc')
Base.append_log(Base, f"Successfully loaded IFC model")
except Exception as e:
print(f"ERROR: Failed to open IFC file: {e}")
sys.exit(1)
# Create topology from the model with error handling
try:
topology = Topology(model)
all_paths = topology.all_paths_finder()
except ValueError as e:
print(f"ERROR: Topology creation failed: {e}")
sys.exit(1)
# Initialize pressure calculator
pressure_calc = Pressure()
# Calculate available pressure for all terminals
terminals = model.by_type("IfcSanitaryTerminal")
for terminal in terminals:
try:
available_pressure = pressure_calc.available(terminal, all_paths)
print(f"Terminal {terminal.id()}: {available_pressure:.2f} m")
except Exception as e:
print(f"Warning: Failed to calculate pressure for terminal {terminal.id()}: {e}")
continueFor complete working examples with interactive prompts, see:
ifc_hydro/examples/demo/demo.py- Interactive demonstration scriptifc_hydro/examples/eval/eval.py- Evaluation example script
from ifc_hydro import Pipe, Fitting, Valve
# Extract pipe properties
pipe = model.by_id(5399) # Replace with actual pipe ID
pipe_props = Pipe.properties(pipe)
print(f"Pipe length: {pipe_props['len']} m")
print(f"Pipe diameter: {pipe_props['dim']} m")
# Extract fitting properties (requires path context)
fitting = model.by_id(7020) # Replace with actual fitting ID
# Find the path containing this fitting
for path in all_paths:
if fitting in path:
fitting_props = Fitting.properties(fitting, path)
print(f"Fitting type: {fitting_props['type']}")
breakfrom ifc_hydro import DesignFlow, PressureDrop, Pressure
# Calculate design flow for all components
flow_calc = DesignFlow()
flows = flow_calc.calculate(all_paths)
# Calculate linear pressure drop in a pipe
pressure_drop_calc = PressureDrop()
pipe = model.by_id(5399)
pipe_pressure_drop = pressure_drop_calc.linear(pipe, all_paths)
print(f"Pipe pressure drop: {pipe_pressure_drop:.3f} m")
# Calculate local pressure drop in fittings/valves (requires path context)
fitting = model.by_id(7020)
for path in all_paths:
if fitting in path:
fitting_pressure_drop = pressure_drop_calc.local(fitting, path, all_paths)
print(f"Fitting pressure drop: {fitting_pressure_drop:.3f} m")
break
# Calculate available pressure at a terminal
pressure_calc = Pressure()
terminal = model.by_id(5423)
available_pressure = pressure_calc.available(terminal, all_paths)
print(f"Available pressure: {available_pressure:.2f} m")Base class providing logging functionality and common utilities.
configure_log(log_dir, log_name): Configure log file location and nameappend_log(text): Append timestamped message to logresource_path(relative_path): Get absolute path to resources
Creates hydraulic system topology from IFC models.
Constructor: Topology(model) - Requires an opened IFC model
graph_creator(): Creates a graph representation of the system using IfcRelNests and IfcRelConnectsPortspath_finder(term_guid, tank_guid): Finds path between specific terminal and tankall_paths_finder(): Finds all paths from terminals to tanks- Error Handling: Validates required IFC elements exist before processing:
- Checks for IfcSanitaryTerminal elements
- Checks for IfcTank elements
- Checks for IfcRelNests and IfcRelConnectsPorts relationships
- Raises descriptive ValueError exceptions if critical elements are missing
Provides 3D vector operations for geometric calculations.
create_direction_vector(from_point, to_point): Creates a direction vector between two pointsmagnitude(vector): Calculates the magnitude (length) of a vectornormalize(vector): Normalizes a vector to unit lengthdot_product(vector1, vector2): Calculates the dot product of two vectorsangle_between(vector1, vector2): Calculates the angle between two vectors in degrees
Extracts properties from IFC pipe segments.
properties(pipe): Extracts length and diameter from pipe segments
Extracts properties from IFC pipe fittings.
properties(fitt, path): Extracts dimensions, directions, and type from fittings (requires the path)- Calculates direction change angle using vector analysis
- Returns incoming/outgoing direction vectors for flow analysis
- Validates fitting position in path with error handling
Extracts properties from IFC valves.
properties(valv, path): Extracts dimensions and type from valves (requires the path)
Calculates design flow rates for hydraulic system components.
calculate(all_paths): Calculates design flow for all components based on terminal types
Calculates pressure drops in hydraulic system components.
linear(pipe, all_paths): Calculates linear pressure drop in pipes using Fair Whipple-Hsiao equationlocal(conn, path, all_paths): Calculates local pressure drop in fittings and valves using equivalent length method- Angle-aware junctions: Automatically detects direction changes and applies appropriate coefficients
- 0° direction change (straight): coefficient 0.9
- Other angles: coefficient 2.4
- Uses standardized reference diameter (25mm) for equivalent length calculations
- Angle-aware junctions: Automatically detects direction changes and applies appropriate coefficients
Calculates available pressure at sanitary terminals.
available(term, all_paths): Calculates available pressure at terminals accounting for gravity potential and all losses- Handles multiple IFC representation types (SweptSolid, MappedRepresentation)
- Provides per-component error handling with detailed logging
- Returns pressure in meters of water column
Graph data structure for representing system topology.
add(node1, node2): Adds connection between nodesremove(node): Removes node from graphis_connected(node1, node2): Checks if nodes are connectedfind_path(node1, node2): Finds path between nodes (depth-first, not guaranteed shortest)
Uses standardized design flow rates from lookup tables (input_tables.py):
- Shower: 0.2 L/s
- Wash basin: 0.15 L/s
- WC seat: 1.70 L/s
- Bath, Bidet, Cistern, Fountain, Sink, Toilet Pan, Urinal, and more
- Linear losses: Fair Whipple-Hsiao empirical equation for PVC pipes
- Formula:
pressure_drop = pipe_len × (0.000859 × (flow^1.75) × (diameter^-4.75)) - Recommended for PVC pipes, diameter range 12.5-100mm
- Formula:
- Local losses: Equivalent length method with tabulated coefficients (for 25 mm diameter pipes):
- Junction (straight): 0.9
- Junction (with angle): 2.4
- Bend: 1.2
- Exit: 1.2
- Isolating valve: 0.2
- Regulating valve: 11.4
- Angle detection: Automatically calculates direction change in junctions using 3D vector analysis
- Available pressure: Gravity potential minus total pressure losses
All hydraulic coefficients and design parameters are centralized in input_tables.py for easy maintenance and extension.
ifc-hydro/
├── ifc_hydro/ # Main library package
│ ├── __init__.py # Package initialization and exports
│ ├── core/ # Core classes and data structures
│ │ ├── __init__.py
│ │ ├── base.py # Base class with logging utilities
│ │ ├── graph.py # Graph data structure
│ │ └── vector.py # Vector operations for 3D calculations
│ ├── topology/ # Topology creation module
│ │ ├── __init__.py
│ │ └── topology.py # Topology class with error handling
│ ├── properties/ # Property extraction module
│ │ ├── __init__.py
│ │ ├── pipe.py # Pipe property extraction
│ │ ├── fitting.py # Fitting property extraction
│ │ └── valve.py # Valve property extraction
│ ├── hydraulics/ # Hydraulic calculations module
│ │ ├── __init__.py
│ │ ├── design_flow.py # Design flow calculations
│ │ ├── pressure_drop.py # Pressure drop calculations
│ │ ├── pressure.py # Pressure calculations
│ │ └── input_tables.py # Centralized input parameters tables
│ └── examples/ # Example scripts
│ ├── demo/ # Demo example
│ │ ├── demo.py # Interactive demonstration script
│ │ └── demo-project.ifc # Sample IFC model for demo
│ └── eval/ # Evaluation example
│ ├── eval.py # Interactive evaluation script
│ └── eval-project.ifc # Sample IFC model for evaluation
├── old/ # Legacy versions (1.0.0, 2.0.0, 3.0.0)
├── setup.py # Package setup configuration
├── requirements.txt # Python dependencies
├── LICENSE.md # MIT License
└── README.md # This file
- Python 3.7+
- IfcOpenShell >= 0.7.0
- Standard library modules:
datetime,collections,sys,os
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.
-
1.0.0 (2024) - First version with Hazen-Williams formula implementation
- Basic hydraulic calculations for IFC models
- Monolithic script architecture
-
2.0.0 (2024) - Improved hydraulic calculations
- Switched to Fair Whipple-Hsiao equation for PVC pipes
- Enhanced accuracy for pressure drop calculations
-
3.0.0 (2025) - Added error handling and angle-aware analysis for JUNCTIION fittings
- Angle-aware junction analysis with direction change detection
- Comprehensive error handling and validation throughout
- Model-as-parameter design (no longer hardcoded file paths)
- Per-component error handling with detailed logging
-
4.0.0 (2026) - Major refactoring and feature additions
- Modular library structure: Separated into
core,topology,properties,hydraulicsmodules - Class refactoring:
- Renamed
TopologyCreator→Topology - Split
PropertyExtractorintoPipe,Fitting, andValveclasses - Split
HydroCalculatorintoDesignFlow,PressureDrop, andPressureclasses - Added
VectorandGraphutility classes - Added 'input_tables.py' for centralized reference data
- Interactive demo and evaluation examples with sample IFC models
- Renamed
- Improvements:
- Support for multiple IFC representation types
- Enhanced property extraction with geometric analysis
- Multi-diameter support in pressure drop calculations
- Package installation: Added
setup.pyfor pip installation
- Modular library structure: Separated into
For questions and support, please open an issue on the GitHub repository or send an e-mail to andre@abm.eng.br
- Built for my Master's degree at the Polytechnic School of Universidade de São Paulo