ifcos-impl-materials
IFC Material Assignment Implementation Guide
Quick Reference
Decision Tree: Which Material Type to Use
What kind of element needs material?
├── Single homogeneous material (e.g., steel column, concrete beam)?
│ └── IfcMaterial → assign_material(type="IfcMaterial")
│
├── Layered construction (wall, slab, roof with defined layers)?
│ └── IfcMaterialLayerSet → add_material_set(set_type="IfcMaterialLayerSet")
│ └── Each layer has a thickness (LayerThickness in meters)
│
├── Profiled structural element (beam, column with cross-section)?
│ └── IfcMaterialProfileSet → add_material_set(set_type="IfcMaterialProfileSet")
│ └── Each profile has an IfcProfileDef defining the cross-section
│
├── Composite element with named parts (window: frame+glazing)?
│ ├── IFC4+ → IfcMaterialConstituentSet
│ │ └── add_material_set(set_type="IfcMaterialConstituentSet")
│ └── IFC2X3 → IfcMaterialList (legacy, no named parts)
│ └── add_material_set(set_type="IfcMaterialList")
│
└── Legacy unordered material list (IFC2X3 only)?
└── IfcMaterialList → add_material_set(set_type="IfcMaterialList")
Decision Tree: Assign Material to Type or Occurrence?
Where to assign the material?
├── Element type (IfcWallType, IfcSlabType, etc.)? [RECOMMENDED]
│ └── Assign to type → all occurrences inherit the material
│ └── ifcopenshell.api.material.assign_material(model,
│ products=[wall_type], type="IfcMaterialLayerSet", material=layer_set)
│
└── Individual occurrence (IfcWall, IfcSlab, etc.)?
└── Assign to occurrence → overrides type material for this element only
└── ifcopenshell.api.material.assign_material(model,
products=[wall], material=concrete)
Critical Warnings
- ALWAYS assign materials to element types (IfcWallType, IfcSlabType), not individual occurrences. Occurrences inherit from their type. Assign to occurrences only when overriding type material.
- ALWAYS use
ifcopenshell.api.material.*functions for material operations. NEVER create IfcMaterial or IfcRelAssociatesMaterial entities directly withcreate_entity(). - NEVER use
IfcMaterialConstituentSetwith IFC2X3 schema. It does not exist in IFC2X3. UseIfcMaterialListinstead. - ALWAYS check
model.schemabefore using schema-specific material types. - NEVER assign multiple materials directly to the same product. Use material sets (layer, profile, constituent) for composite materials.
assign_material()automatically unassigns previous materials. - ALWAYS set
LayerThicknesson layers after creation usingedit_layer(). Layers without thickness are invalid. - ALWAYS provide a profile definition (
IfcProfileDef) when adding profiles to a profile set. A material profile without a profile curve is incomplete. - NEVER set material relationships via direct attribute assignment (e.g.,
wall.HasAssociations = ...). ALWAYS use the API.
Essential Patterns
Pattern 1: Create and Assign a Single Material
# IfcOpenShell — all schema versions
import ifcopenshell
import ifcopenshell.api
# Create a material with category
concrete = ifcopenshell.api.material.add_material(model,
name="Concrete C30/37", category="concrete")
# Assign to a wall (single material, no layers)
ifcopenshell.api.material.assign_material(model,
products=[wall], material=concrete)
Pattern 2: Create a Layered Wall Material (IfcMaterialLayerSet)
# IfcOpenShell — all schema versions
import ifcopenshell.api
# Step 1: Create individual materials
brick = ifcopenshell.api.material.add_material(model,
name="Facing Brick", category="brick")
insulation = ifcopenshell.api.material.add_material(model,
name="Mineral Wool", category="glass")
block = ifcopenshell.api.material.add_material(model,
name="Concrete Block", category="block")
# Step 2: Create layer set container
layer_set = ifcopenshell.api.material.add_material_set(model,
name="External Wall 300mm", set_type="IfcMaterialLayerSet")
# Step 3: Add layers (order = outside to inside)
layer1 = ifcopenshell.api.material.add_layer(model,
layer_set=layer_set, material=brick)
ifcopenshell.api.material.edit_layer(model,
layer=layer1, attributes={"LayerThickness": 0.102})
layer2 = ifcopenshell.api.material.add_layer(model,
layer_set=layer_set, material=insulation)
ifcopenshell.api.material.edit_layer(model,
layer=layer2, attributes={"LayerThickness": 0.100})
layer3 = ifcopenshell.api.material.add_layer(model,
layer_set=layer_set, material=block)
ifcopenshell.api.material.edit_layer(model,
layer=layer3, attributes={"LayerThickness": 0.100})
# Step 4: Assign to wall TYPE (best practice)
ifcopenshell.api.material.assign_material(model,
products=[wall_type], type="IfcMaterialLayerSet", material=layer_set)
Pattern 3: Create a Profiled Beam Material (IfcMaterialProfileSet)
# IfcOpenShell — all schema versions
import ifcopenshell.api
# Step 1: Create material
steel = ifcopenshell.api.material.add_material(model,
name="S355", category="steel")
# Step 2: Create profile set
profile_set = ifcopenshell.api.material.add_material_set(model,
name="HEA 200", set_type="IfcMaterialProfileSet")
# Step 3: Create profile definition (cross-section shape)
profile_def = ifcopenshell.api.profile.add_parameterised_profile(model,
ifc_class="IfcIShapeProfileDef",
OverallWidth=0.200, OverallDepth=0.190,
WebThickness=0.0065, FlangeThickness=0.010)
# Step 4: Add profile item to set
profile_item = ifcopenshell.api.material.add_profile(model,
profile_set=profile_set, material=steel, profile=profile_def)
# Step 5: Assign to column TYPE
ifcopenshell.api.material.assign_material(model,
products=[column_type], type="IfcMaterialProfileSet", material=profile_set)
Pattern 4: Constituent Set for Composite Elements (IFC4+ Only)
# IfcOpenShell — IFC4 and IFC4X3 ONLY (NOT IFC2X3)
import ifcopenshell.api
# Step 1: Create materials
aluminium = ifcopenshell.api.material.add_material(model,
name="Aluminium Frame", category="aluminium")
glass = ifcopenshell.api.material.add_material(model,
name="Double Glazing", category="glass")
# Step 2: Create constituent set
constituent_set = ifcopenshell.api.material.add_material_set(model,
name="Window Assembly", set_type="IfcMaterialConstituentSet")
# Step 3: Add named constituents
frame = ifcopenshell.api.material.add_constituent(model,
constituent_set=constituent_set, material=aluminium, name="Frame")
glazing = ifcopenshell.api.material.add_constituent(model,
constituent_set=constituent_set, material=glass, name="Glazing")
# Step 4: Assign to window TYPE
ifcopenshell.api.material.assign_material(model,
products=[window_type], type="IfcMaterialConstituentSet",
material=constituent_set)
Pattern 5: Query Material from an Element
# IfcOpenShell — all schema versions
import ifcopenshell.util.element
# Get material (returns IfcMaterial, IfcMaterialLayerSet, etc.)
material = ifcopenshell.util.element.get_material(wall)
if material is None:
print("No material assigned")
elif material.is_a("IfcMaterial"):
print(f"Single material: {material.Name}")
elif material.is_a("IfcMaterialLayerSet"):
for layer in material.MaterialLayers:
print(f"Layer: {layer.Material.Name}, Thickness: {layer.LayerThickness}")
elif material.is_a("IfcMaterialLayerSetUsage"):
layer_set = material.ForLayerSet
for layer in layer_set.MaterialLayers:
print(f"Layer: {layer.Material.Name}, Thickness: {layer.LayerThickness}")
elif material.is_a("IfcMaterialProfileSet"):
for profile in material.MaterialProfiles:
print(f"Profile: {profile.Material.Name}")
elif material.is_a("IfcMaterialConstituentSet"):
for constituent in material.MaterialConstituents:
print(f"Constituent: {constituent.Name} - {constituent.Material.Name}")
Pattern 6: Add Visual Style to a Material
# IfcOpenShell — all schema versions
import ifcopenshell.api
# Create a surface style (visual appearance)
style = ifcopenshell.api.style.add_style(model, name="Concrete Grey")
ifcopenshell.api.style.add_surface_style(model, style=style,
ifc_class="IfcSurfaceStyleShading",
attributes={
"SurfaceColour": {"Name": None, "Red": 0.7, "Green": 0.7, "Blue": 0.7}
})
# Assign style to a representation
ifcopenshell.api.style.assign_representation_styles(model,
shape_representation=body_rep, styles=[style])
Common Operations
Material Categories (Standard Values)
| Category | Use For |
|---|---|
"concrete" |
Concrete elements, precast |
"steel" |
Structural steel, reinforcement |
"aluminium" |
Window frames, curtain walls |
"brick" |
Masonry walls |
"block" |
Concrete blocks |
"stone" |
Natural stone elements |
"wood" |
Timber construction |
"glass" |
Glazing, insulation (glass wool) |
"gypsum" |
Plasterboard, gypsum finishes |
"plastic" |
PVC pipes, synthetic membranes |
"earth" |
Foundation fill, landscaping |
Material Set Type Selection Guide
| Element Type | Material Set | Schema |
|---|---|---|
| Walls (layered) | IfcMaterialLayerSet |
All |
| Slabs (layered) | IfcMaterialLayerSet |
All |
| Roofs (layered) | IfcMaterialLayerSet |
All |
| Beams | IfcMaterialProfileSet |
All |
| Columns | IfcMaterialProfileSet |
All |
| Members | IfcMaterialProfileSet |
All |
| Windows | IfcMaterialConstituentSet |
IFC4+ |
| Doors | IfcMaterialConstituentSet |
IFC4+ |
| Curtain walls | IfcMaterialConstituentSet |
IFC4+ |
| Furniture | IfcMaterial (single) |
All |
| Equipment | IfcMaterial (single) |
All |
| Windows (legacy) | IfcMaterialList |
IFC2X3 |
Remove Material from Element
# IfcOpenShell — all schema versions
ifcopenshell.api.material.unassign_material(model, products=[wall])
Copy a Material with All Properties
# IfcOpenShell — all schema versions
new_material = ifcopenshell.api.material.copy_material(model,
material=existing_material)
# Copies psets and styles. Set items are copied but underlying materials reused.
Edit Material Properties
# IfcOpenShell — all schema versions
ifcopenshell.api.material.edit_material(model,
material=concrete, attributes={"Name": "Concrete C35/45", "Category": "concrete"})
Reorder Layers in a Layer Set
# IfcOpenShell — all schema versions
ifcopenshell.api.material.reorder_set_item(model,
material_set=layer_set, old_index=2, new_index=0)
Edit Layer Usage (Offset from Reference Line)
# IfcOpenShell — all schema versions
# Get the usage from the element
material = ifcopenshell.util.element.get_material(wall)
if material.is_a("IfcMaterialLayerSetUsage"):
ifcopenshell.api.material.edit_layer_usage(model,
usage=material, attributes={"OffsetFromReferenceLine": -0.1})
Delete Material and Material Set
# IfcOpenShell — all schema versions
# First unassign from all products
ifcopenshell.api.material.unassign_material(model, products=[wall_type])
# Then remove the material set
ifcopenshell.api.material.remove_material_set(model, material_set=layer_set)
# Remove individual materials (only if not used elsewhere)
ifcopenshell.api.material.remove_material(model, material=brick)
Version Notes
IFC2X3 vs IFC4+ Material Differences
| Feature | IFC2X3 | IFC4 / IFC4X3 |
|---|---|---|
| IfcMaterial | Yes | Yes |
| IfcMaterialLayerSet | Yes | Yes |
| IfcMaterialProfileSet | Yes | Yes |
| IfcMaterialConstituentSet | No | Yes |
| IfcMaterialList | Yes (primary) | Yes (legacy) |
| Material category attribute | No | Yes |
| Material description attribute | No | Yes |
Schema-Aware Material Assignment
# IfcOpenShell — all schema versions
import ifcopenshell.util.element
if model.schema == "IFC2X3":
# IFC2X3: Use IfcMaterialList for composite elements
material_list = ifcopenshell.api.material.add_material_set(model,
name="Window Materials", set_type="IfcMaterialList")
ifcopenshell.api.material.add_list_item(model,
material_list=material_list, material=aluminium)
ifcopenshell.api.material.add_list_item(model,
material_list=material_list, material=glass)
else:
# IFC4+: Use IfcMaterialConstituentSet for named parts
constituent_set = ifcopenshell.api.material.add_material_set(model,
name="Window Assembly", set_type="IfcMaterialConstituentSet")
ifcopenshell.api.material.add_constituent(model,
constituent_set=constituent_set, material=aluminium, name="Frame")
ifcopenshell.api.material.add_constituent(model,
constituent_set=constituent_set, material=glass, name="Glazing")
Material + Style Integration
Materials define physical properties. Styles define visual appearance. These are separate concepts in IFC. ALWAYS apply both together for visual BIM models.
Workflow: Material + Visual Style
1. Create IfcMaterial → physical definition
2. Create IfcSurfaceStyle → visual appearance (color, texture)
3. Assign style to representation → visual display
4. Assign material to product → physical association
Materials and styles are NOT linked automatically. A material named "Concrete" does not automatically render as grey. The style must be explicitly created and assigned to the element's representation.
Reference Links
- API Method Signatures — Complete signatures for all material API methods
- Working Code Examples — End-to-end examples for all material operations
- Anti-Patterns — Common material assignment mistakes and how to avoid them
More from openaec-foundation/computational-design-day-delft-march-2026
blender-core-api
Guides Blender Python API usage including bpy module structure, RNA data access, context system, dependency graph, and operator invocation. Activates when writing bpy scripts, creating Blender addons, or accessing Blender data blocks programmatically.
1blender-syntax-panels
Defines Blender UI panel creation including bpy.types.Panel, draw() method, UILayout API (row/column/box/split), bl_space_type, bl_region_type, bl_category, sub-panels, draw_header, menus, and UIList. Activates when creating custom Blender panels, building addon interfaces, or working with UILayout elements.
1ifcos-syntax-api
Documents the ifcopenshell.api module system with all 30+ API modules, invocation patterns via api.run() and direct module calls, parameter conventions, and module categorization. Activates when creating IFC entities, modifying properties, managing spatial structure, or using any ifcopenshell.api function.
1bonsai-impl-bcf
Guides implementation of BIM Collaboration Format (BCF) workflows in Bonsai including creating BCF topics, adding viewpoints with camera snapshots, managing comments, importing/exporting BCF files (v2.1 and v3.0), and integrating BCF issue tracking with IFC element references. Activates when working with BCF files, BIM issue tracking, clash report management, or collaboration workflows in Bonsai.
1ifcos-impl-mep
Guides MEP (Mechanical, Electrical, Plumbing) modeling in IFC using ifcopenshell.api.system including IfcSystem, IfcDistributionElement, ports, connections, flow segments, fittings, and MEP-specific property sets. Activates when creating HVAC systems, piping networks, electrical circuits, or MEP elements in IFC models.
1ifcos-impl-cost
Guides IFC cost management using ifcopenshell.api.cost including cost schedules, cost items, cost values, cost quantities, and 5D BIM workflows. Activates when implementing cost estimation in IFC models, creating cost schedules, or linking quantities to cost items.
1