计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
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, H…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
SOURCE port MUST connect to a SINK port.IfcDistributionSystem in IFC2X3 models. Use ifc_class="IfcSystem" for IFC2X3 compatibility.ifcopenshell.api.run("system.add_system", ...) to create systems. NEVER use model.create_entity("IfcDistributionSystem") directly — it skips required relationship setup.system.remove_system deletes contained elements. It ONLY removes the system grouping; elements and their ports remain in the model.ifcopenshell.api.run("root.create_entity", ...) for MEP elements, not model.create_entity(). The API sets GlobalId, ownership, and validates predefined types.products as a list to system.assign_system (v0.8+ convention).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)
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
# 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)
# 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)
# 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")
# 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"})
Set via PredefinedType attribute on IfcDistributionSystem:
| PredefinedType | Domain | Description |
|---|---|---|
VENTILATION | HVAC | Supply/return/exhaust air systems |
HEATING | HVAC | Hot water heating, radiator circuits |
COOLING | HVAC | Chilled water, refrigerant loops |
AIRCONDITIONING | HVAC | Combined heating/cooling air systems |
EXHAUST | HVAC | Kitchen/fume exhaust systems |
DOMESTICHOTWATER | Plumbing | Hot water supply |
DOMESTICCOLDWATER | Plumbing | Cold water supply |
DRAINAGE | Plumbing | Gravity drainage, waste water |
WASTEWATER | Plumbing | Waste water systems |
STORMWATER | Plumbing | Rainwater drainage |
SEWAGE | Plumbing | Sewer connections |
RAINWATER | Plumbing | Rainwater collection |
ELECTRICAL | Electrical | Power distribution |
LIGHTING | Electrical | Lighting circuits |
POWERGENERATION | Electrical | On-site power generation |
LIGHTNINGPROTECTION | Electrical | Lightning protection systems |
EARTHING | Electrical | Grounding/earthing |
FIREPROTECTION | Fire | Sprinklers, fire suppression |
SECURITY | Security | Access control, CCTV |
COMMUNICATION | Comms | Data/telephone networks |
DATA | Comms | Data networks |
TV | Comms | Television distribution |
SIGNAL | Controls | Signal/control systems |
CONTROL | Controls | Building automation |
GAS | Fuel | Natural gas distribution |
FUEL | Fuel | Fuel supply systems |
COMPRESSEDAIR | Pneumatic | Compressed air distribution |
VACUUM | Pneumatic | Vacuum systems |
REFRIGERATION | HVAC | Refrigeration systems |
CHILLEDWATER | HVAC | Chilled water distribution |
CONDENSERWATER | HVAC | Condenser water loops |
CHEMICAL | Process | Chemical distribution |
DISPOSAL | Waste | Waste disposal systems |
HAZARDOUS | Safety | Hazardous material systems |
CONVEYING | Transport | Material conveying |
USERDEFINED | Custom | Set ObjectType attribute |
NOTDEFINED | Default | Unspecified |
| Direction | Meaning | When to Use |
|---|---|---|
SOURCE | Flow exits through this port | Outlet ports, downstream direction |
SINK | Flow enters through this port | Inlet ports, upstream direction |
SOURCEANDSINK | Bidirectional flow | Reversible systems, heat exchangers |
NOTDEFINED | Direction not specified | When 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.
# 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)
# 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,
})
| Element Type | Property Set | Key Properties |
|---|---|---|
| Duct segments | Pset_DuctSegmentTypeCommon | NominalDiameter, Length |
| Pipe segments | Pset_PipeSegmentTypeCommon | NominalDiameter, WorkingPressure |
| Air terminals | Pset_AirTerminalTypeCommon | AirFlowRateRange, NominalAirFlowRate |
| Valves | Pset_ValveTypeCommon | ValvePattern, WorkingPressure |
| Pumps | Pset_PumpTypeCommon | FlowRateRange, NominalRotationSpeed |
| Fans | Pset_FanTypeCommon | NominalAirFlowRate, NominalTotalPressure |
| Boilers | Pset_BoilerTypeCommon | NominalEnergyConsumption, WaterTemperatureRange |
| Feature | IFC2X3 | IFC4 | IFC4X3 |
|---|---|---|---|
| System class | IfcSystem | IfcDistributionSystem | IfcDistributionSystem |
| PredefinedType on system | Not available | Full enum (37 values) | Full enum + additions |
| Building system | Not available | IfcBuildingSystem | IfcBuildingSystem |
| Port nesting | IfcRelNests | IfcRelNests | IfcRelNests |
| Port connection | IfcRelConnectsPorts | IfcRelConnectsPorts | IfcRelConnectsPorts |
| Flow direction enum | Same | Same | Same |
# 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")
This skill depends on:
api.run() invocation patterns, module table, and parameter conventions