L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Productivité · SKILL.md

ifcos-impl-mep

ifcos-impl-mep

Use when modeling MEP (Mechanical, Electrical, Plumbing) systems in IFC -- HVAC, piping, electrical circuits, distribution elements, ports, and connections. Prevents the common mistake of not creating ports for flow connections between elements. Covers IfcSystem, IfcDistributionElement, flow segments, fittings, and MEP property sets. Keywords: MEP, HVAC, pi…

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: ifcos-impl-mep description: > Use when modeling MEP (Mechanical, Electrical, Plumbing) systems in IFC -- HVAC, piping, electrical circuits, distribution elements, ports, and connections. Prevents the common mistake of not creating ports for flow connections between elements. Covers IfcSystem, IfcDistributionElement, flow segments, fittings, and MEP property sets. Keywords: MEP, HVAC, piping, electrical, IfcSystem, IfcDistributionElement, port, connection, flow segment, fitting, mechanical, plumbing, duct, ventilation, connect pipes. license: MIT compatibility: "Designed for Claude Code. Requires IfcOpenShell Python library." metadata: author: OpenAEC-Foundation version: "1.0"

MEP System Implementation Guide

Quick Reference

Critical Warnings

  • ALWAYS create ports on distribution elements BEFORE attempting to connect them. Elements without ports cannot participate in flow networks.
  • ALWAYS create at least two ports per segment element (one inlet, one outlet). Segments are flow-through elements.
  • NEVER connect two ports with the same flow direction. A SOURCE port MUST connect to a SINK port.
  • NEVER use IfcDistributionSystem in IFC2X3 models. Use ifc_class="IfcSystem" for IFC2X3 compatibility.
  • ALWAYS use ifcopenshell.api.run("system.add_system", ...) to create systems. NEVER use model.create_entity("IfcDistributionSystem") directly — it skips required relationship setup.
  • ALWAYS assign elements to a system AFTER creating port connections. The system is a logical grouping; ports define the physical topology.
  • NEVER assume system.remove_system deletes contained elements. It ONLY removes the system grouping; elements and their ports remain in the model.
  • ALWAYS use ifcopenshell.api.run("root.create_entity", ...) for MEP elements, not model.create_entity(). The API sets GlobalId, ownership, and validates predefined types.
  • ALWAYS pass products as a list to system.assign_system (v0.8+ convention).

Decision Tree: MEP Workflow

Creating an MEP system?
├── Step 1: What IFC schema version?
│   ├── IFC2X3 → Use ifc_class="IfcSystem" for add_system
│   └── IFC4 / IFC4X3 → Use ifc_class="IfcDistributionSystem" (default)
│
├── Step 2: Create the system
│   └── system.add_system → system.edit_system (set Name + PredefinedType)
│
├── Step 3: Create distribution elements
│   ├── Duct/Pipe/Cable? → IfcDuctSegment, IfcPipeSegment, IfcCableSegment
│   ├── Elbow/Tee/Junction? → IfcDuctFitting, IfcPipeFitting, IfcCableFitting
│   ├── Air terminal/Fixture? → IfcAirTerminal, IfcSanitaryTerminal
│   ├── Valve/Damper/Switch? → IfcValve, IfcDamper, IfcSwitchingDevice
│   ├── Pump/Fan? → IfcPump, IfcFan
│   ├── Boiler/Chiller? → IfcBoiler, IfcChiller
│   └── Tank/Vessel? → IfcTank
│
├── Step 4: Create ports on each element
│   └── system.add_port (per connection point)
│
├── Step 5: Connect ports between elements
│   └── system.connect_port (port1, port2, direction)
│
├── Step 6: Assign elements to system
│   └── system.assign_system (products=[...], system=system)
│
├── Step 7: Assign flow controls (optional)
│   └── system.assign_flow_control (damper→duct, valve→pipe)
│
└── Step 8: Add properties and placement
    ├── pset.add_pset / pset.edit_pset (MEP property sets)
    └── geometry (placement, representation)

Decision Tree: Which Distribution Element Class

What type of MEP element?
├── Carries flow (segments)?
│   ├── Air/gas → IfcDuctSegment
│   ├── Liquid → IfcPipeSegment
│   ├── Electrical → IfcCableSegment
│   └── Cable carrier → IfcCableCarrierSegment
│
├── Changes direction/splits (fittings)?
│   ├── Air/gas → IfcDuctFitting
│   ├── Liquid → IfcPipeFitting
│   ├── Electrical → IfcCableFitting
│   └── Cable carrier → IfcCableCarrierFitting
│
├── End point (terminals)?
│   ├── Air supply/return → IfcAirTerminal
│   ├── Plumbing fixture → IfcSanitaryTerminal
│   ├── Electrical outlet → IfcOutlet
│   ├── Light fixture → IfcLightFixture
│   ├── Fire sprinkler → IfcFireSuppressionTerminal
│   └── Communication jack → IfcCommunicationsAppliance
│
├── Controls flow (controllers)?
│   ├── Airflow → IfcDamper
│   ├── Liquid flow → IfcValve
│   ├── Electrical → IfcSwitchingDevice / IfcProtectiveDevice
│   └── Flow meter → IfcFlowMeter
│
├── Moves medium (movers)?
│   ├── Air → IfcFan
│   ├── Liquid → IfcPump
│   └── Gas → IfcCompressor
│
├── Converts energy?
│   ├── Heating → IfcBoiler
│   ├── Cooling → IfcChiller
│   ├── Heat exchange → IfcHeatExchanger
│   ├── Cooling tower → IfcCoolingTower
│   ├── Air handling → IfcAirToAirHeatRecovery / IfcUnitaryEquipment
│   └── Electrical → IfcTransformer / IfcElectricGenerator
│
├── Stores medium?
│   ├── Liquid → IfcTank
│   └── Electrical → IfcElectricFlowStorageDevice
│
├── Treats medium?
│   ├── Air filter → IfcFilter
│   └── Grease/oil trap → IfcInterceptor
│
└── Senses/monitors (control elements)?
    ├── Temperature → IfcSensor (TEMPERATURESENSOR)
    ├── Pressure → IfcSensor (PRESSURESENSOR)
    ├── Flow rate → IfcSensor (FLOWSENSOR)
    ├── Smoke → IfcSensor (SMOKESENSOR)
    └── Actuator → IfcActuator

Essential Patterns

Pattern 1: Complete HVAC System (IFC4)

# IFC4 / IFC4X3
import ifcopenshell
import ifcopenshell.api

model = ifcopenshell.api.run("project.create_file", version="IFC4")

# Bootstrap (project, units, contexts, spatial hierarchy)
project = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcProject", name="MEP Project")
ifcopenshell.api.run("unit.assign_unit", model)
model3d = ifcopenshell.api.run("context.add_context", model, context_type="Model")
body = ifcopenshell.api.run("context.add_context", model,
    context_type="Model", context_identifier="Body",
    target_view="MODEL_VIEW", parent=model3d)
site = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcSite", name="Site")
building = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcBuilding", name="Building A")
storey = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcBuildingStorey", name="Level 1")
ifcopenshell.api.run("aggregate.assign_object", model,
    products=[site], relating_object=project)
ifcopenshell.api.run("aggregate.assign_object", model,
    products=[building], relating_object=site)
ifcopenshell.api.run("aggregate.assign_object", model,
    products=[storey], relating_object=building)

# Step 1: Create distribution system
hvac = ifcopenshell.api.run("system.add_system", model,
    ifc_class="IfcDistributionSystem")
ifcopenshell.api.run("system.edit_system", model,
    system=hvac,
    attributes={"Name": "Supply Air System", "PredefinedType": "VENTILATION"})

# Step 2: Create elements
ahu = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcUnitaryEquipment", name="AHU-01")
duct1 = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcDuctSegment", name="SD-01")
duct2 = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcDuctSegment", name="SD-02")
terminal = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcAirTerminal", name="AT-01")

# Step 3: Place in spatial structure
ifcopenshell.api.run("spatial.assign_container", model,
    products=[ahu, duct1, duct2, terminal], relating_structure=storey)

# Step 4: Create ports (inlet + outlet per segment)
ahu_out = ifcopenshell.api.run("system.add_port", model, element=ahu)
d1_in = ifcopenshell.api.run("system.add_port", model, element=duct1)
d1_out = ifcopenshell.api.run("system.add_port", model, element=duct1)
d2_in = ifcopenshell.api.run("system.add_port", model, element=duct2)
d2_out = ifcopenshell.api.run("system.add_port", model, element=duct2)
term_in = ifcopenshell.api.run("system.add_port", model, element=terminal)

# Step 5: Connect ports (AHU → Duct1 → Duct2 → Terminal)
ifcopenshell.api.run("system.connect_port", model,
    port1=ahu_out, port2=d1_in, direction="SOURCE")
ifcopenshell.api.run("system.connect_port", model,
    port1=d1_out, port2=d2_in, direction="SOURCE")
ifcopenshell.api.run("system.connect_port", model,
    port1=d2_out, port2=term_in, direction="SOURCE")

# Step 6: Assign all elements to the system
ifcopenshell.api.run("system.assign_system", model,
    products=[ahu, duct1, duct2, terminal], system=hvac)

Pattern 2: Piping Network with Fittings

# IFC4 / IFC4X3: requires completed bootstrap
# Create plumbing system
plumbing = ifcopenshell.api.run("system.add_system", model,
    ifc_class="IfcDistributionSystem")
ifcopenshell.api.run("system.edit_system", model,
    system=plumbing,
    attributes={"Name": "Hot Water Supply", "PredefinedType": "DOMESTICHOTWATER"})

# Create pipe elements
pipe1 = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcPipeSegment", name="HWS-P01")
elbow = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcPipeFitting", name="HWS-E01")
pipe2 = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcPipeSegment", name="HWS-P02")
valve = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcValve", name="HWS-V01")

# Ports: pipes need 2, fittings need 2+, terminals need 1
p1_in = ifcopenshell.api.run("system.add_port", model, element=pipe1)
p1_out = ifcopenshell.api.run("system.add_port", model, element=pipe1)
elb_in = ifcopenshell.api.run("system.add_port", model, element=elbow)
elb_out = ifcopenshell.api.run("system.add_port", model, element=elbow)
p2_in = ifcopenshell.api.run("system.add_port", model, element=pipe2)
p2_out = ifcopenshell.api.run("system.add_port", model, element=pipe2)

# Connect: Pipe1 → Elbow → Pipe2
ifcopenshell.api.run("system.connect_port", model,
    port1=p1_out, port2=elb_in, direction="SOURCE")
ifcopenshell.api.run("system.connect_port", model,
    port1=elb_out, port2=p2_in, direction="SOURCE")

# Assign flow control (valve controls pipe)
ifcopenshell.api.run("system.assign_flow_control", model,
    relating_flow_element=pipe1, related_flow_control=valve)

# Assign to system
ifcopenshell.api.run("system.assign_system", model,
    products=[pipe1, elbow, pipe2, valve], system=plumbing)

Pattern 3: Tee Fitting (3 Ports)

# IFC4 / IFC4X3
tee = ifcopenshell.api.run("root.create_entity", model,
    ifc_class="IfcPipeFitting", name="HWS-T01")

# Tee fittings have 3 ports: inlet, outlet-main, outlet-branch
tee_in = ifcopenshell.api.run("system.add_port", model, element=tee)
tee_out1 = ifcopenshell.api.run("system.add_port", model, element=tee)
tee_out2 = ifcopenshell.api.run("system.add_port", model, element=tee)

# Connect: upstream pipe → tee inlet
# tee outlet1 → downstream main
# tee outlet2 → downstream branch
ifcopenshell.api.run("system.connect_port", model,
    port1=upstream_pipe_out, port2=tee_in, direction="SOURCE")
ifcopenshell.api.run("system.connect_port", model,
    port1=tee_out1, port2=main_pipe_in, direction="SOURCE")
ifcopenshell.api.run("system.connect_port", model,
    port1=tee_out2, port2=branch_pipe_in, direction="SOURCE")

Pattern 4: IFC2X3 System (Backward Compatible)

# IFC2X3: use IfcSystem instead of IfcDistributionSystem
model = ifcopenshell.api.run("project.create_file", version="IFC2X3")
# ... bootstrap ...

system = ifcopenshell.api.run("system.add_system", model,
    ifc_class="IfcSystem")  # REQUIRED for IFC2X3
ifcopenshell.api.run("system.edit_system", model,
    system=system,
    attributes={"Name": "Heating System"})
# NOTE: PredefinedType is NOT available on IfcSystem in IFC2X3.
# Use ObjectType attribute for classification instead.
ifcopenshell.api.run("attribute.edit_attributes", model,
    product=system,
    attributes={"ObjectType": "HEATING"})

Distribution System Types (IFC4 / IFC4X3)

Set via PredefinedType attribute on IfcDistributionSystem:

PredefinedTypeDomainDescription
VENTILATIONHVACSupply/return/exhaust air systems
HEATINGHVACHot water heating, radiator circuits
COOLINGHVACChilled water, refrigerant loops
AIRCONDITIONINGHVACCombined heating/cooling air systems
EXHAUSTHVACKitchen/fume exhaust systems
DOMESTICHOTWATERPlumbingHot water supply
DOMESTICCOLDWATERPlumbingCold water supply
DRAINAGEPlumbingGravity drainage, waste water
WASTEWATERPlumbingWaste water systems
STORMWATERPlumbingRainwater drainage
SEWAGEPlumbingSewer connections
RAINWATERPlumbingRainwater collection
ELECTRICALElectricalPower distribution
LIGHTINGElectricalLighting circuits
POWERGENERATIONElectricalOn-site power generation
LIGHTNINGPROTECTIONElectricalLightning protection systems
EARTHINGElectricalGrounding/earthing
FIREPROTECTIONFireSprinklers, fire suppression
SECURITYSecurityAccess control, CCTV
COMMUNICATIONCommsData/telephone networks
DATACommsData networks
TVCommsTelevision distribution
SIGNALControlsSignal/control systems
CONTROLControlsBuilding automation
GASFuelNatural gas distribution
FUELFuelFuel supply systems
COMPRESSEDAIRPneumaticCompressed air distribution
VACUUMPneumaticVacuum systems
REFRIGERATIONHVACRefrigeration systems
CHILLEDWATERHVACChilled water distribution
CONDENSERWATERHVACCondenser water loops
CHEMICALProcessChemical distribution
DISPOSALWasteWaste disposal systems
HAZARDOUSSafetyHazardous material systems
CONVEYINGTransportMaterial conveying
USERDEFINEDCustomSet ObjectType attribute
NOTDEFINEDDefaultUnspecified

Port Flow Directions

DirectionMeaningWhen to Use
SOURCEFlow exits through this portOutlet ports, downstream direction
SINKFlow enters through this portInlet ports, upstream direction
SOURCEANDSINKBidirectional flowReversible systems, heat exchangers
NOTDEFINEDDirection not specifiedWhen flow direction is unknown

Rule: When connecting two ports, direction on connect_port describes the relationship from port1's perspective. If port1 is a SOURCE, flow goes from port1 to port2.


System Traversal (ifcopenshell.util.system)

# IFC4 / IFC4X3
import ifcopenshell.util.system

# Get all elements in a system
elements = ifcopenshell.util.system.get_system_elements(hvac)

# Get all systems an element belongs to
systems = ifcopenshell.util.system.get_element_systems(duct1)

# Get ports on an element (optionally filter by direction)
all_ports = ifcopenshell.util.system.get_ports(duct1)
outlets = ifcopenshell.util.system.get_ports(duct1, flow_direction="SOURCE")
inlets = ifcopenshell.util.system.get_ports(duct1, flow_direction="SINK")

# Traverse connections: downstream / upstream
downstream = ifcopenshell.util.system.get_connected_to(duct1)
upstream = ifcopenshell.util.system.get_connected_from(duct1)

# Get element that owns a port
owner = ifcopenshell.util.system.get_port_element(d1_out)

# Get port connected to a given port
partner = ifcopenshell.util.system.get_connected_port(d1_out)

MEP Property Sets

Standard Property Sets for Distribution Elements

# IFC4 / IFC4X3: Add MEP-specific properties
# Duct segment properties
pset = ifcopenshell.api.run("pset.add_pset", model,
    product=duct1, name="Pset_DuctSegmentTypeCommon")
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties={
    "NominalDiameter": 0.315,      # meters
    "InnerDiameter": 0.313,
    "OuterDiameter": 0.315,
    "Length": 3.0,
})

# Pipe segment properties
pset_pipe = ifcopenshell.api.run("pset.add_pset", model,
    product=pipe1, name="Pset_PipeSegmentTypeCommon")
ifcopenshell.api.run("pset.edit_pset", model, pset=pset_pipe, properties={
    "NominalDiameter": 0.025,
    "InnerDiameter": 0.021,
    "OuterDiameter": 0.025,
    "WorkingPressure": 600000.0,    # Pascals
    "FlowRateRange": "0.1 - 0.5",  # m3/s
})

# Quantity set for a duct
qto = ifcopenshell.api.run("pset.add_qto", model,
    product=duct1, name="Qto_DuctSegmentBaseQuantities")
ifcopenshell.api.run("pset.edit_qto", model, qto=qto, properties={
    "Length": 3.0,
    "GrossCrossSectionArea": 0.078,
    "OuterSurfaceArea": 2.97,
})

Common MEP Pset Names

Element TypeProperty SetKey Properties
Duct segmentsPset_DuctSegmentTypeCommonNominalDiameter, Length
Pipe segmentsPset_PipeSegmentTypeCommonNominalDiameter, WorkingPressure
Air terminalsPset_AirTerminalTypeCommonAirFlowRateRange, NominalAirFlowRate
ValvesPset_ValveTypeCommonValvePattern, WorkingPressure
PumpsPset_PumpTypeCommonFlowRateRange, NominalRotationSpeed
FansPset_FanTypeCommonNominalAirFlowRate, NominalTotalPressure
BoilersPset_BoilerTypeCommonNominalEnergyConsumption, WaterTemperatureRange

Version Differences

FeatureIFC2X3IFC4IFC4X3
System classIfcSystemIfcDistributionSystemIfcDistributionSystem
PredefinedType on systemNot availableFull enum (37 values)Full enum + additions
Building systemNot availableIfcBuildingSystemIfcBuildingSystem
Port nestingIfcRelNestsIfcRelNestsIfcRelNests
Port connectionIfcRelConnectsPortsIfcRelConnectsPortsIfcRelConnectsPorts
Flow direction enumSameSameSame

Version-Safe Pattern

# Detect schema and choose correct system class
schema = model.schema
if schema == "IFC2X3":
    system = ifcopenshell.api.run("system.add_system", model,
        ifc_class="IfcSystem")
else:
    system = ifcopenshell.api.run("system.add_system", model,
        ifc_class="IfcDistributionSystem")

Dependency

This skill depends on:

  • ifcos-syntax-api for api.run() invocation patterns, module table, and parameter conventions
  • ifcos-syntax-fileio for file creation, writing, and transaction management

Reference Links

Official Sources

Skills enregistrées