# Ifc Core Relationships

> Use when wiring IFC objects together: aggregating parts into a whole, containing elements in a storey, attaching property sets or a type, assigning a material, cutting an opening, or filling it with a door. Prevents pointing a relationship the wrong way, using IfcRelAggregates where IfcRelContainedInSpatialStructure is required, putting an element in two spatial parents, swapping the void and fill anchors, and treating a relationship as a plain pointer attribute. Covers the objectified relationship pattern, the six IfcRelationship families, the Relating versus Related direction convention, the full IfcRel star reference table, the IfcRelVoidsElement then IfcRelFillsElement door-in-wall pattern, and traversal through INVERSE attributes. Keywords: IfcRel, IfcRelationship, IfcRelAggregates, IfcRelNests, IfcRelContainedInSpatialStructure, IfcRelDefinesByProperties, IfcRelDefinesByType, IfcRelAssociatesMaterial, IfcRelConnectsElements, IfcRelVoidsElement, IfcRelFillsElement, IfcRelSpaceBoundary, objectified relati

- Skill: `impertio-studio/ifc-core-relationships` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/ifc-core-relationships`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/ifc-core-relationships/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: Impertio-Studio (https://skillmd.com/u/impertio-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/impertio-studio/ifc-core-relationships

---


# IFC Relationships

IFC does not connect objects with plain pointer attributes. Every
connection between objects is a separate, identifiable entity: an
`IfcRelationship`. This is the objectified relationship pattern. This
skill covers why IFC objectifies relationships, the six relationship
families, the `Relating` versus `Related` direction convention, the
concrete `IfcRel*` entities, and how to traverse them.

Verified against the IFC 4.3.2 specification (ISO 16739-1:2024) with
IFC4 and IFC2x3 deltas noted inline. Applies to IFC2x3, IFC4, IFC4.3.

## Quick Reference

### The objectified relationship pattern

`IfcRelationship` is a direct subtype of `IfcRoot`, so every relationship
instance carries its own `GlobalId`, `OwnerHistory`, `Name`, and
`Description`. A relationship is a node in the model, not an attribute on
the connected objects.

Consequences that drive every rule in this skill:

- A relationship can carry its own data: connection geometry, priorities,
  boundary type. That data lives ON the relationship, not on the objects.
- A relationship is added or removed WITHOUT editing the connected
  objects. ALWAYS edit the relationship instance, NEVER the participants.
- A relationship is itself identifiable and versionable through its
  `GlobalId`.
- The cost is indirection: to reach a wall's property sets you follow the
  wall's `IsDefinedBy` INVERSE to `IfcRelDefinesByProperties` instances,
  then read `RelatingPropertyDefinition`. NEVER expect a direct attribute.

### The six relationship families

`IfcRelationship` is abstract with exactly six direct subtypes (verified).
NEVER instantiate `IfcRelationship` or any abstract family supertype.

| Family | Purpose | Concrete entities used most |
|--------|---------|-----------------------------|
| `IfcRelAssigns` | Cross-domain assignment of objects to a group, process, resource, control, actor, or product | `IfcRelAssignsToGroup` |
| `IfcRelAssociates` | Associate external information with objects | `IfcRelAssociatesMaterial`, `IfcRelAssociatesClassification` |
| `IfcRelConnects` | Connectivity, containment, fills, space boundaries | `IfcRelContainedInSpatialStructure`, `IfcRelConnectsElements`, `IfcRelFillsElement` |
| `IfcRelDeclares` | Declare objects or types into an `IfcContext` (project or library) | `IfcRelDeclares` |
| `IfcRelDecomposes` | Whole and part decomposition, plus feature subtraction | `IfcRelAggregates`, `IfcRelNests`, `IfcRelVoidsElement` |
| `IfcRelDefines` | Assign a type or a property set to objects | `IfcRelDefinesByType`, `IfcRelDefinesByProperties` |

### The Relating versus Related convention

Every relationship has one `Relating...` role and one `Related...` role.
The direction is part of the semantics. A backwards relationship is a
structurally valid but meaningless model.

- The `Relating...` side is the single anchor: the whole, the type, the
  spatial container, the property set, the opening.
- The `Related...` side is the dependent participant. In one-to-many
  relationships it is an aggregate (`SET` or `LIST`, cardinality `1..n`).

ALWAYS read the entity attribute documentation to know which object goes
on which side. NEVER guess the direction.

### Key IfcRel* reference table

All entities and attribute types below are verified against the IFC4.3
specification. Full positional signatures are in `references/methods.md`.

| Entity | Supertype | Relating side | Related side |
|--------|-----------|---------------|--------------|
| `IfcRelAggregates` | `IfcRelDecomposes` | `RelatingObject`: `IfcObjectDefinition` (the whole) | `RelatedObjects`: `SET [1:?] OF IfcObjectDefinition` (the parts) |
| `IfcRelNests` | `IfcRelDecomposes` | `RelatingObject`: `IfcObjectDefinition` (the whole) | `RelatedObjects`: `LIST [1:?] OF IfcObjectDefinition` (ordered parts) |
| `IfcRelContainedInSpatialStructure` | `IfcRelConnects` | `RelatingStructure`: `IfcSpatialElement` | `RelatedElements`: `SET [1:?] OF IfcProduct` |
| `IfcRelReferencedInSpatialStructure` | `IfcRelConnects` | `RelatingStructure`: `IfcSpatialElement` | `RelatedElements`: `SET [1:?] OF IfcSpatialReferenceSelect` |
| `IfcRelDefinesByProperties` | `IfcRelDefines` | `RelatingPropertyDefinition`: `IfcPropertySetDefinitionSelect` | `RelatedObjects`: `SET [1:?] OF IfcObjectDefinition` |
| `IfcRelDefinesByType` | `IfcRelDefines` | `RelatingType`: `IfcTypeObject` | `RelatedObjects`: `SET [1:?] OF IfcObject` |
| `IfcRelAssociatesMaterial` | `IfcRelAssociates` | `RelatingMaterial`: `IfcMaterialSelect` | `RelatedObjects`: `SET [1:?] OF IfcDefinitionSelect` |
| `IfcRelAssociatesClassification` | `IfcRelAssociates` | `RelatingClassification`: `IfcClassificationSelect` | `RelatedObjects`: `SET [1:?] OF IfcDefinitionSelect` |
| `IfcRelConnectsElements` | `IfcRelConnects` | `RelatingElement`: `IfcElement` | `RelatedElement`: `IfcElement` |
| `IfcRelConnectsPathElements` | `IfcRelConnectsElements` | inherits `RelatingElement` | inherits `RelatedElement` |
| `IfcRelVoidsElement` | `IfcRelDecomposes` | `RelatingBuildingElement`: `IfcElement` | `RelatedOpeningElement`: `IfcFeatureElementSubtraction` |
| `IfcRelFillsElement` | `IfcRelConnects` | `RelatingOpeningElement`: `IfcOpeningElement` | `RelatedBuildingElement`: `IfcElement` |
| `IfcRelSpaceBoundary` | `IfcRelConnects` | `RelatingSpace`: `IfcSpaceBoundarySelect` | `RelatedBuildingElement`: `IfcElement` |

Note the reversed anchor between `IfcRelVoidsElement` and
`IfcRelFillsElement`: see the door-in-wall pattern below.

## Decision Trees

### Which relationship do I use?

```
What am I trying to express?
|
+- A whole made of parts, order does NOT matter
|    -> IfcRelAggregates  (spatial tree, element assemblies)
|
+- A whole made of parts, order DOES matter
|    -> IfcRelNests  (ordered ports, ordered cost items, ordered tasks)
|
+- Place a physical element into a spatial level (storey, space)
|    -> IfcRelContainedInSpatialStructure
|
+- Reference an element from a second spatial structure
|    -> IfcRelReferencedInSpatialStructure
|
+- Attach a property set or quantity set to objects
|    -> IfcRelDefinesByProperties
|
+- Link occurrences to their shared type object
|    -> IfcRelDefinesByType
|
+- Assign a material to elements or element types
|    -> IfcRelAssociatesMaterial
|
+- Assign a classification reference (Uniclass, OmniClass)
|    -> IfcRelAssociatesClassification
|
+- Connect two elements physically or logically
|    -> IfcRelConnectsElements  (or IfcRelConnectsPathElements for wall joins)
|
+- Cut an opening into an element
|    -> IfcRelVoidsElement
|
+- Fill an opening with a door or window
|    -> IfcRelFillsElement
|
+- Define the surfaces that bound a space
|    -> IfcRelSpaceBoundary (or its 1stLevel / 2ndLevel subtypes)
|
+- Group objects across domains (a system, a zone, a schedule)
     -> IfcRelAssignsToGroup
```

### Aggregate or nest?

```
Does the order of the parts carry meaning?
|
+- No  -> IfcRelAggregates : RelatedObjects is a SET, order is irrelevant.
|         The spatial tree (Project, Site, Building, Storey) ALWAYS uses
|         IfcRelAggregates.
|
+- Yes -> IfcRelNests : RelatedObjects is a LIST, position is meaningful.
          Use for ordered distribution ports, ordered cost items, ordered
          subtasks.
```

NEVER use `IfcRelNests` for the spatial tree. NEVER use `IfcRelAggregates`
when the consumer depends on part order.

### Containment or aggregation for the spatial tree?

```
What are the two objects?
|
+- Both are spatial elements (Site inside Project, Storey inside Building)
|    -> IfcRelAggregates : spatial element decomposes spatial element.
|
+- A physical element placed into a spatial element (a wall in a storey)
|    -> IfcRelContainedInSpatialStructure : NEVER IfcRelAggregates.
|
+- A physical element that also belongs to a second structure
     -> add IfcRelReferencedInSpatialStructure for the secondary link.
        The single primary containment stays IfcRelContainedInSpatialStructure.
```

A physical element ALWAYS sits in exactly ONE
`IfcRelContainedInSpatialStructure` (the WR31 rule on that entity enforces
at-most-once). Extra spatial links ALWAYS go through
`IfcRelReferencedInSpatialStructure`. See `ifc-core-spatial-structure`.

## Patterns

Every snippet uses STEP physical file syntax. `$` marks an unset optional
attribute. Attribute order is the EXPRESS declared order. Full verified
signatures are in `references/methods.md`; runnable instances are in
`references/examples.md`.

### Pattern: aggregate parts into a whole

`IfcRelAggregates` has 6 positional attributes: the 4 from `IfcRoot`, then
`RelatingObject` (the whole), then `RelatedObjects` (the SET of parts).

```step
#30=IFCRELAGGREGATES(
  '1Hkj5pQ9X8x9bq0d6FZ7yA',  /* GlobalId        */
  #5,                        /* OwnerHistory    */
  $,                         /* Name            */
  $,                         /* Description     */
  #10,                       /* RelatingObject : IfcBuilding (the whole) */
  (#11,#12)                  /* RelatedObjects : the IfcBuildingStorey parts */
);
```

ALWAYS put the whole on `RelatingObject` and the parts on `RelatedObjects`.
A reversed instance describes a storey aggregating a building.

### Pattern: contain elements in a spatial structure

`IfcRelContainedInSpatialStructure` places physical elements into one
spatial level. `RelatedElements` comes BEFORE `RelatingStructure` in the
declared order.

```step
#40=IFCRELCONTAINEDINSPATIALSTRUCTURE(
  '2k7sB$Qe9X8x9bq0d6FZ7y',  /* GlobalId        */
  #5,                        /* OwnerHistory    */
  'Storey contents',         /* Name            */
  $,                         /* Description     */
  (#21,#22),                 /* RelatedElements : the IfcWall occurrences */
  #11                        /* RelatingStructure : the IfcBuildingStorey */
);
```

Each physical element appears in `RelatedElements` of exactly one such
relationship. NEVER list the same element in two
`IfcRelContainedInSpatialStructure` instances.

### Pattern: attach a property set

`IfcRelDefinesByProperties` links an `IfcPropertySet` or `IfcElementQuantity`
to objects. `RelatedObjects` precedes `RelatingPropertyDefinition`.

```step
#50=IFCRELDEFINESBYPROPERTIES(
  '3mNp7rTf0Y9y0cr1e7GA8z',  /* GlobalId                    */
  #5,                        /* OwnerHistory                */
  $,                         /* Name                        */
  $,                         /* Description                 */
  (#21,#22),                 /* RelatedObjects : the elements */
  #48                        /* RelatingPropertyDefinition : the IfcPropertySet */
);
```

One relationship can serve many objects (N-to-N). See
`ifc-syntax-property-sets` for building the `IfcPropertySet` itself.

### Pattern: link occurrences to a type

`IfcRelDefinesByType` is 1-to-N: one type, many occurrences.

```step
#52=IFCRELDEFINESBYTYPE(
  '4pQr9sUg1Z0z1ds2f8HB9$',  /* GlobalId                  */
  #5,                        /* OwnerHistory              */
  $, $,                      /* Name, Description         */
  (#21,#22),                 /* RelatedObjects : IfcWall occurrences */
  #20                        /* RelatingType : the IfcWallType */
);
```

NEVER place a type object in `RelatedObjects`: that slot accepts `IfcObject`
occurrences only. See `ifc-core-entity-hierarchy` for the type model.

### Pattern: associate a material

`IfcRelAssociatesMaterial` inherits `RelatedObjects` from `IfcRelAssociates`
and adds `RelatingMaterial` as the last attribute.

```step
#54=IFCRELASSOCIATESMATERIAL(
  '5qRs0tVh2$1$2et3g9IC0_',  /* GlobalId                    */
  #5,                        /* OwnerHistory                */
  $, $,                      /* Name, Description           */
  (#21,#22),                 /* RelatedObjects : the elements */
  #53                        /* RelatingMaterial : IfcMaterial or IfcMaterialLayerSet... */
);
```

`RelatingMaterial` accepts the `IfcMaterialSelect` choices: `IfcMaterial`,
`IfcMaterialLayerSet`, `IfcMaterialLayerSetUsage`, `IfcMaterialProfileSet`,
`IfcMaterialProfileSetUsage`, `IfcMaterialConstituentSet`, `IfcMaterialList`.
See `ifc-syntax-materials`.

### Pattern: the door-in-wall void then fill

The canonical opening pattern uses two relationships, in this order:

1. `IfcRelVoidsElement` subtracts an `IfcOpeningElement` from the wall.
2. `IfcRelFillsElement` places the `IfcDoor` into that opening.

```step
/* step 1 : the wall voids the opening */
#60=IFCRELVOIDSELEMENT(
  '6rSt1uWi3_2_3fu4h0JD1A',  /* GlobalId               */
  #5, $, $,                  /* OwnerHistory, Name, Description */
  #21,                       /* RelatingBuildingElement : the IfcWall */
  #58                        /* RelatedOpeningElement : the IfcOpeningElement */
);
/* step 2 : the opening is filled by the door */
#62=IFCRELFILLSELEMENT(
  '7sTu2vXj4A3A4gv5i1KE2B',  /* GlobalId               */
  #5, $, $,                  /* OwnerHistory, Name, Description */
  #58,                       /* RelatingOpeningElement : the IfcOpeningElement */
  #59                        /* RelatedBuildingElement : the IfcDoor */
);
```

The anchor reverses between the two relationships. The wall is the
`Relating` side of `IfcRelVoidsElement`; the SAME opening (`#58`) is the
`Relating` side of `IfcRelFillsElement`. ALWAYS create the void first, then
the fill. NEVER point `IfcRelFillsElement` straight from wall to door:
the door fills the opening, not the wall.

Version note: `IfcRelVoidsElement` is a subtype of `IfcRelDecomposes` in
IFC4 and IFC4.3. In IFC2x3 it sat under the connectivity branch. The
attribute names and order are stable across all three versions.

### Pattern: traverse through INVERSE attributes

Objects do not store relationships as forward attributes. They expose
INVERSE attributes that the parser populates by scanning relationship
instances. To find what defines an object, follow its inverses:

| From object | INVERSE attribute | Reaches |
|-------------|-------------------|---------|
| `IfcObject` | `IsDefinedBy` | `IfcRelDefinesByProperties`, `IfcRelDefinesByType` |
| `IfcObjectDefinition` | `IsDecomposedBy` | `IfcRelAggregates` where this is the whole |
| `IfcObjectDefinition` | `Decomposes` | `IfcRelAggregates` where this is a part |
| `IfcObjectDefinition` | `HasAssociations` | `IfcRelAssociatesMaterial`, `IfcRelAssociatesClassification` |
| `IfcElement` | `ContainedInStructure` | `IfcRelContainedInSpatialStructure` |
| `IfcElement` | `HasOpenings` | `IfcRelVoidsElement` |
| `IfcOpeningElement` | `HasFillings` | `IfcRelFillsElement` |

To read a wall's property sets: take `wall.IsDefinedBy`, keep the
`IfcRelDefinesByProperties` instances, then read each
`RelatingPropertyDefinition`. NEVER look for a direct `PropertySets`
attribute on the wall: it does not exist.

## Anti-Patterns

Full detail with the failure mechanism is in `references/anti-patterns.md`.
The five that matter most:

- Reversing `Relating` and `Related`. The model parses but states the
  wrong fact (a storey aggregating a building, a part owning the whole).
- Using `IfcRelAggregates` to place a physical element into a storey.
  Containment of physical elements ALWAYS uses
  `IfcRelContainedInSpatialStructure`.
- Listing one element in two `IfcRelContainedInSpatialStructure` instances.
  Violates WR31; the element belongs to the spatial tree once only.
- Pointing `IfcRelFillsElement` from the wall to the door directly,
  skipping the `IfcOpeningElement`. The door has nothing to fill.
- Treating a relationship as a pointer and editing the participants to
  "connect" them. Connections ALWAYS exist only as `IfcRel*` instances.

## Reference Links

### This skill

- `references/methods.md`: full positional attribute signatures for every
  `IfcRel*` entity in this skill, with supertypes and version notes.
- `references/examples.md`: verified STEP physical file instances.
- `references/anti-patterns.md`: failure modes and their root causes.

### Related skills

- `ifc-core-entity-hierarchy`: `IfcRoot` and the object inheritance tree
  that relationships connect.
- `ifc-core-spatial-structure`: `IfcProject`, the spatial tree, the
  containment versus reference rule.
- `ifc-syntax-property-sets`: building the `IfcPropertySet` attached via
  `IfcRelDefinesByProperties`.
- `ifc-syntax-building-elements`: the concrete elements that participate
  as `Relating` and `Related` objects.

### Official sources

- IfcRelationship: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelationship.htm
- IfcRelAggregates: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelAggregates.htm
- IfcRelContainedInSpatialStructure: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelContainedInSpatialStructure.htm
- IfcRelDefinesByProperties: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelDefinesByProperties.htm
- IfcRelVoidsElement: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelVoidsElement.htm
- IfcRelFillsElement: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelFillsElement.htm

