| name | ifcos-impl-creation |
| description | Use when building IFC models from scratch -- creating projects, spatial structure, walls, slabs, columns, openings, property sets, and type assignments. Prevents the critical mistake of skipping IfcOwnerHistory (required in IFC2X3) or not establishing spatial containment. Covers the complete creation workflow using ifcopenshell.api from project to element level. Keywords: IFC creation, create project, spatial structure, IfcWall, IfcSlab, IfcColumn, IfcOwnerHistory, api.run, root.create_entity, model from scratch, create IFC file, new IFC project.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires IfcOpenShell Python library. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
IFC Model Creation Workflows
Quick Reference
Decision Tree: Starting a New IFC Model
Creating a new IFC model?
├── Production model with proper header/metadata?
│ └── YES → model = ifcopenshell.api.run("project.create_file", version="IFC4")
│
└── Bare-minimum test file?
└── model = ifcopenshell.file(schema="IFC4")
└── WARNING: No header, no project, no units. Add these manually.
Decision Tree: Choosing IFC Schema Version
Which schema version?
├── Building/architecture project?
│ ├── Legacy compatibility needed? → IFC2X3
│ │ └── WARNING: OwnerHistory is REQUIRED on all rooted entities
│ └── Modern project? → IFC4
│
├── Infrastructure project (roads, bridges, tunnels)?
│ └── IFC4X3
│ └── Adds: IfcBridge, IfcRoad, IfcTunnel, IfcAlignment
│
└── Unsure? → Default to IFC4
Decision Tree: Element Creation Order
Building an IFC model from scratch?
Follow this EXACT order:
1. Create file → project.create_file
2. Create IfcProject → root.create_entity
3. Assign units → unit.assign_unit
4. Add contexts → context.add_context (Model + Body subcontext)
5. Create spatial hierarchy:
a. IfcSite → root.create_entity + aggregate.assign_object
b. IfcBuilding → root.create_entity + aggregate.assign_object
c. IfcBuildingStorey → root.create_entity + aggregate.assign_object
6. Create types (optional but recommended):
a. IfcWallType etc. → root.create_entity
b. Assign materials → material.add_material_set + material.assign_material
7. Create elements:
a. Create entity → root.create_entity
b. Add geometry → geometry.add_wall_representation (etc.)
c. Assign geometry → geometry.assign_representation
d. Set placement → geometry.edit_object_placement
e. Assign container → spatial.assign_container
f. Assign type → type.assign_type
8. Add properties → pset.add_pset + pset.edit_pset
9. Write file → model.write("output.ifc")
Critical Warnings
- ALWAYS use
ifcopenshell.api.run() for entity creation. NEVER use model.create_entity() directly — the API handles GlobalId generation, OwnerHistory, and validation automatically.
- ALWAYS create the spatial hierarchy (Project → Site → Building → Storey) before creating physical elements. Elements without spatial containment are invisible in most BIM viewers.
- ALWAYS assign spatial containment via
spatial.assign_container for physical elements (walls, slabs, columns, doors). Without containment, elements float in the model with no spatial context.
- ALWAYS set up geometric contexts (Model → Body subcontext) before creating geometry. Geometry without a context cannot be displayed.
- ALWAYS assign units via
unit.assign_unit immediately after creating the project. Without units, all dimensions are ambiguous.
- NEVER skip
geometry.edit_object_placement after creating an element. Without a placement, the element has no position in 3D space.
- NEVER create physical elements and types with mismatched IFC classes. An IfcWall occurrence MUST use IfcWallType, not IfcSlabType.
- IFC2X3 ONLY: OwnerHistory is REQUIRED on every rooted entity. The
root.create_entity API handles this automatically, but ONLY if an owner/user has been set via owner.set_user. Call owner.set_user before creating any entities in IFC2X3.
Essential Patterns
Pattern 1: Complete IFC4 Model from Scratch
import ifcopenshell
import ifcopenshell.api
model = ifcopenshell.api.run("project.create_file", version="IFC4")
project = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcProject", name="My 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="Default 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="Ground Floor")
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)
wall = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcWall", name="Wall 001")
representation = ifcopenshell.api.run(,
model, context=body, length=, height=, thickness=)
ifcopenshell.api.run(, model,
product=wall, representation=representation)
ifcopenshell.api.run(, model, product=wall)
ifcopenshell.api.run(, model,
relating_structure=storey, products=[wall])
pset = ifcopenshell.api.run(, model,
product=wall, name=)
ifcopenshell.api.run(, model, pset=pset, properties={
: ,
: ,
:
})
model.write()
Pattern 2: IFC2X3 Model with Required OwnerHistory
import ifcopenshell
import ifcopenshell.api
model = ifcopenshell.api.run("project.create_file", version="IFC2X3")
person = ifcopenshell.api.run("owner.add_person", model,
identification="jdoe", family_name="Doe", given_name="John")
org = ifcopenshell.api.run("owner.add_organisation", model,
identification="ACME", name="ACME Engineering")
user = ifcopenshell.api.run("owner.add_person_and_organisation", model,
person=person, organisation=org)
application = ifcopenshell.api.run("owner.add_application", model)
ifcopenshell.api.run("owner.set_user", model, user=user)
project = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcProject", name="Legacy Project")
ifcopenshell.api.run("unit.assign_unit", model)
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")
storey = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcBuildingStorey", name="Ground Floor")
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)
Pattern 3: Spatial Hierarchy with Multiple Storeys
site = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcSite", name="Main Site")
building = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcBuilding", name="Office Block")
basement = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcBuildingStorey", name="Basement")
ground = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcBuildingStorey", name="Ground Floor")
first = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcBuildingStorey", name="First Floor")
roof = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcBuildingStorey", name="Roof")
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=[basement, ground, first, roof], relating_object=building)
import numpy as np
for storey_obj, elevation in [(basement, -3.0), (ground, 0.0),
(first, 3.5), (roof, 7.0)]:
matrix = np.eye(4)
matrix[2][3] = elevation
ifcopenshell.api.run(, model,
product=storey_obj, matrix=matrix)
Pattern 4: Creating Elements with Type Assignment
wall_type = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcWallType", name="WT-200 External")
layer_set = ifcopenshell.api.run("material.add_material_set", model,
name="WT-200", set_type="IfcMaterialLayerSet")
brick = ifcopenshell.api.run("material.add_material", model,
name="Brick", category="brick")
insulation = ifcopenshell.api.run("material.add_material", model,
name="Insulation", category="mineral wool")
plaster = ifcopenshell.api.run("material.add_material", model,
name="Gypsum Plaster", category="gypsum")
layer1 = ifcopenshell.api.run("material.add_layer", model,
layer_set=layer_set, material=brick)
ifcopenshell.api.run("material.edit_layer", model,
layer=layer1, attributes={"LayerThickness": 0.102})
layer2 = ifcopenshell.api.run("material.add_layer", model,
layer_set=layer_set, material=insulation)
ifcopenshell.api.run("material.edit_layer", model,
layer=layer2, attributes={"LayerThickness": 0.080})
layer3 = ifcopenshell.api.run("material.add_layer", model,
layer_set=layer_set, material=plaster)
ifcopenshell.api.run("material.edit_layer", model,
layer=layer3, attributes={"LayerThickness": 0.018})
ifcopenshell.api.run("material.assign_material", model,
products=[wall_type], type="IfcMaterialLayerSet", material=layer_set)
wall1 = ifcopenshell.api.run("root.create_entity", model,
ifc_class=, name=)
wall2 = ifcopenshell.api.run(, model,
ifc_class=, name=)
ifcopenshell.api.run(, model,
related_objects=[wall1, wall2], relating_type=wall_type)
Pattern 5: Creating Openings (Doors and Windows)
opening = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcOpeningElement", name="Door Opening")
opening_rep = ifcopenshell.api.run("geometry.add_wall_representation",
model, context=body, length=0.9, height=2.1, thickness=0.2)
ifcopenshell.api.run("geometry.assign_representation", model,
product=opening, representation=opening_rep)
ifcopenshell.api.run("geometry.edit_object_placement", model,
product=opening)
ifcopenshell.api.run("void.add_opening", model,
opening=opening, element=wall)
door = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcDoor", name="Door 001")
ifcopenshell.api.run("void.add_filling", model,
opening=opening, element=door)
ifcopenshell.api.run("spatial.assign_container", model,
relating_structure=storey, products=[door])
Pattern 6: Property Sets and Quantity Sets
pset = ifcopenshell.api.run("pset.add_pset", model,
product=wall, name="Pset_WallCommon")
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties={
"Reference": "WT-200",
"IsExternal": True,
"LoadBearing": True,
"FireRating": "REI60",
"ThermalTransmittance": 0.28
})
qto = ifcopenshell.api.run("pset.add_qto", model,
product=wall, name="Qto_WallBaseQuantities")
ifcopenshell.api.run("pset.edit_qto", model, qto=qto, properties={
"Length": 5.0,
"Height": 3.0,
"Width": 0.2,
"GrossSideArea": 15.0,
"NetSideArea": 13.11,
"GrossVolume": 3.0
})
custom_pset = ifcopenshell.api.run("pset.add_pset", model,
product=wall, name="ACME_WallData")
ifcopenshell.api.run("pset.edit_pset", model, pset=custom_pset, properties={
"CostCode": "STR-W-001",
"InstallDate": "2026-03-15",
"Inspector": "J. Doe"
})
Pattern 7: Slab and Column Creation
slab = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcSlab", name="Floor Slab", predefined_type="FLOOR")
slab_rep = ifcopenshell.api.run("geometry.add_slab_representation", model,
context=body, depth=0.25,
polyline=[(0.0, 0.0), (10.0, 0.0), (10.0, 8.0), (0.0, 8.0)])
ifcopenshell.api.run("geometry.assign_representation", model,
product=slab, representation=slab_rep)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=slab)
ifcopenshell.api.run("spatial.assign_container", model,
relating_structure=storey, products=[slab])
column = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcColumn", name="Column C1")
profile = ifcopenshell.api.run("profile.add_parameterised_profile", model,
ifc_class="IfcRectangleProfileDef", XDim=0.3, YDim=0.3)
col_rep = ifcopenshell.api.run("geometry.add_profile_representation", model,
context=body, profile=profile, depth=3.0)
ifcopenshell.api.run("geometry.assign_representation", model,
product=column, representation=col_rep)
ifcopenshell.api.run("geometry.edit_object_placement", model, product=column)
ifcopenshell.api.run("spatial.assign_container", model,
relating_structure=storey, products=[column])
Version Notes
IFC2X3 vs IFC4+ Entity Differences
| Feature | IFC2X3 | IFC4 / IFC4X3 |
|---|
| OwnerHistory | REQUIRED on all rooted entities | OPTIONAL |
| IfcWallStandardCase | EXISTS (use for layered walls) | DEPRECATED (use IfcWall with PredefinedType) |
| IfcBuildingStorey | Only valid spatial container | IfcBuildingStorey + IfcSpace + IfcFacility |
| Property set types | IfcPropertySingleValue only | Adds IfcPropertyBoundedValue, IfcPropertyTableValue |
| Material sets | IfcMaterialList (legacy) | IfcMaterialConstituentSet (preferred) |
IFC4X3 Infrastructure Entities (Not Available in IFC2X3/IFC4)
IfcBridge, IfcBridgePart
IfcRoad, IfcRoadPart
IfcRailway, IfcRailwayPart
IfcTunnel, IfcTunnelPart
IfcAlignment, IfcLinearElement
IfcFacility, IfcFacilityPart
Aggregation Hierarchy by Schema
| Schema | Standard Hierarchy |
|---|
| IFC2X3 | IfcProject → IfcSite → IfcBuilding → IfcBuildingStorey → IfcSpace |
| IFC4 | IfcProject → IfcSite → IfcBuilding → IfcBuildingStorey → IfcSpace |
| IFC4X3 | IfcProject → IfcSite → IfcFacility (or IfcBuilding/IfcBridge/IfcRoad) → IfcFacilityPart (or IfcBuildingStorey) → IfcSpace |
Type-to-Occurrence Mapping (Common Elements)
| Element Type | Occurrence Class | Notes |
|---|
| IfcWallType | IfcWall | IFC2X3: also IfcWallStandardCase |
| IfcSlabType | IfcSlab | Use predefined_type: FLOOR, ROOF, BASESLAB, LANDING |
| IfcColumnType | IfcColumn | |
| IfcBeamType | IfcBeam | |
| IfcDoorType | IfcDoor | IFC2X3: IfcDoorStyle (not IfcDoorType) |
| IfcWindowType | IfcWindow | IFC2X3: IfcWindowStyle (not IfcWindowType) |
| IfcCurtainWallType | IfcCurtainWall | |
Common Operations
Set Up Geometric Contexts
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)
axis = ifcopenshell.api.run("context.add_context", model,
context_type="Model", context_identifier="Axis",
target_view="GRAPH_VIEW", parent=model3d)
plan = ifcopenshell.api.run("context.add_context", model,
context_type="Plan")
plan_body = ifcopenshell.api.run("context.add_context", model,
context_type="Plan", context_identifier="Body",
target_view="PLAN_VIEW", parent=plan)
Position Elements with Transformation Matrix
import numpy as np
matrix = np.eye(4)
matrix[0][3] = 5.0
matrix[1][3] = 2.0
matrix[2][3] = 0.0
ifcopenshell.api.run("geometry.edit_object_placement", model,
product=wall, matrix=matrix)
import math
angle = math.radians(90)
rotation_matrix = np.array([
[math.cos(angle), -math.sin(angle), 0, 0],
[math.sin(angle), math.cos(angle), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
ifcopenshell.api.run("geometry.edit_object_placement", model,
product=wall, matrix=rotation_matrix)
Shared Property Sets Across Multiple Elements
pset = ifcopenshell.api.run("pset.add_pset", model,
product=wall1, name="Pset_WallCommon")
ifcopenshell.api.run("pset.edit_pset", model, pset=pset, properties={
"IsExternal": True, "FireRating": "REI90"
})
ifcopenshell.api.run("pset.assign_pset", model,
products=[wall1, wall2, wall3], pset=pset)
Visual Alternative: IfcSverchok
For node-based visual IFC creation, use IfcSverchok (31 nodes). Key nodes: SvIfcCreateProject, SvIfcCreateEntity, SvIfcApi. Refer to: sverchok-impl-ifcsverchok
Reference Links