# Ifc Impl Data Enrichment

> Use when adding descriptive data to elements that already exist in an IFC model: attaching a property set, an element quantity, a material, or a classification reference, without touching geometry or spatial structure. Prevents pointing IfcRelDefinesByProperties at a type object, putting a material usage entity on a type instead of an occurrence, naming a custom property set with the reserved Pset_ prefix, conflating quantities with properties, and duplicating one relationship per element. Covers the occurrence versus type attachment split, the HasPropertySets type mechanism, IfcRelAssociatesMaterial set-on-type usage-on-occurrence, IfcRelAssociatesClassification, and the Pset_ and Qto_ naming rules. Keywords: IFC enrichment, attach property set, IfcRelDefinesByProperties, IfcPropertySet, HasPropertySets, IfcElementQuantity, attach material, IfcRelAssociatesMaterial, IfcMaterialLayerSet, IfcMaterialLayerSetUsage, IfcRelAssociatesClassification, IfcClassificationReference, Pset_ prefix, Qto_ prefix, type versu

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

---


# IFC Data Enrichment

Data enrichment is the write-side workflow of attaching descriptive data to
elements that already exist in a model: property sets, measured quantities,
materials, and classification references. Enrichment NEVER changes geometry
or spatial structure; it only adds the semantic layer that downstream tools
read for quantity take-off, cost, analysis, and compliance.

This skill covers the four enrichment targets, the occurrence-versus-type
attachment split, the `Pset_` and `Qto_` naming rules, and the material
set-on-type usage-on-occurrence pattern.

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 four enrichment targets

| Target | Container entity | Attachment to an occurrence | Attachment to a type |
|--------|------------------|-----------------------------|----------------------|
| Properties | `IfcPropertySet` | `IfcRelDefinesByProperties` | `HasPropertySets` explicit attribute |
| Quantities | `IfcElementQuantity` | `IfcRelDefinesByProperties` | `HasPropertySets` explicit attribute |
| Material | `IfcMaterial` and the structured material entities | `IfcRelAssociatesMaterial` | `IfcRelAssociatesMaterial` |
| Classification | `IfcClassificationReference` | `IfcRelAssociatesClassification` | `IfcRelAssociatesClassification` |

Properties and quantities share one attachment machinery: `IfcElementQuantity`
is an `IfcQuantitySet`, which is an `IfcPropertySetDefinition`, the same
supertype as `IfcPropertySet`. Both ride `IfcRelDefinesByProperties`.

### The occurrence versus type rule

`IfcRelDefinesByProperties` carries a `WHERE` rule `NoRelatedTypeObject`:
its `RelatedObjects` SET MUST NOT contain an `IfcTypeObject`.

- ALWAYS attach a property or quantity set to an OCCURRENCE through
  `IfcRelDefinesByProperties`.
- ALWAYS attach a property or quantity set to a TYPE through the type's
  `HasPropertySets` explicit attribute. NEVER point
  `IfcRelDefinesByProperties` at a type object.

`HasPropertySets` is `OPTIONAL SET [1:?] OF IfcPropertySetDefinition`,
declared directly on `IfcTypeObject`. A type holds its sets inline; an
occurrence holds them through a relationship.

### The material set versus usage rule

`IfcRelAssociatesMaterial` attaches a material to BOTH occurrences and
types, but the material object differs:

- The TYPE (`IfcWallType`, `IfcBeamType`) ALWAYS takes the bare set:
  `IfcMaterialLayerSet` or `IfcMaterialProfileSet`.
- The OCCURRENCE ALWAYS takes the usage entity:
  `IfcMaterialLayerSetUsage` or `IfcMaterialProfileSetUsage`, which points
  back at the same bare set via `ForLayerSet` or `ForProfileSet` and adds
  placement. NEVER associate a usage entity with a type.

### Naming rules

- `Pset_` is RESERVED for the standardised property set library
  (`Pset_WallCommon`, `Pset_BeamCommon`). A custom property set NEVER uses
  the `Pset_` prefix; a `Pset_`-prefixed custom set collides with the
  standard library and is silently misread.
- `Qto_` is the standardised quantity set prefix (`Qto_WallBaseQuantities`).
  This convention is IFC4 and later. IFC2x3 used a `BaseQuantities`-style
  convention; ALWAYS check the schema before writing a `Qto_` name.

## Decision Trees

### Which enrichment do I need?

```
What am I adding to the element?
|
+- A descriptive or design attribute (fire rating, IsExternal,
|  LoadBearing flag, thermal transmittance)
|    -> IfcPropertySet, attached by IfcRelDefinesByProperties
|
+- A measured magnitude derived from geometry (gross area, net
|  volume, count, weight, length)
|    -> IfcElementQuantity, attached by IfcRelDefinesByProperties
|
+- The substance the element is made of
|    -> IfcRelAssociatesMaterial (see the material decision tree)
|
+- A code from an external classification system (Uniclass,
   OmniClass, MasterFormat, ETIM)
     -> IfcRelAssociatesClassification
```

NEVER store a measured quantity inside an `IfcPropertySet`, and NEVER store
a design property inside an `IfcElementQuantity`. The two containers are
read by different tools.

### Occurrence or type?

```
Is the data the same for every occurrence of this type?
|
+- Yes, it is shared by all occurrences (a wall type's standard
|  layer build-up, a door type's fire rating)
|    -> attach to the TYPE.
|       Properties / quantities -> type.HasPropertySets
|       Material               -> IfcRelAssociatesMaterial with the
|                                  bare set on the type
|
+- No, it varies per placed instance (this specific wall's
   as-built area, this door's tag)
     -> attach to the OCCURRENCE.
        Properties / quantities -> IfcRelDefinesByProperties
        Material               -> IfcRelAssociatesMaterial with the
                                   usage entity on the occurrence
```

When the same property name exists on both type and occurrence, the
OCCURRENCE value wins. Type values are defaults. See
`ifc-impl-property-extraction` for the read-side resolution.

### Standard or custom property set?

```
Does a published Pset_ definition already cover this data?
|
+- Yes -> use the exact standard name (Pset_WallCommon) and the
|         property names and value types it defines. NEVER alter
|         the standard property names.
|
+- No  -> create a custom property set. Its Name NEVER starts with
          Pset_. Use a project or company prefix instead.
```

### Which material structure?

```
How is the element made of its material(s)?
|
+- One homogeneous substance
|    -> IfcMaterial directly as RelatingMaterial
|
+- Parallel layers (wall, slab, roof, plate)
|    -> IfcMaterialLayerSet on the type,
|       IfcMaterialLayerSetUsage on each occurrence
|
+- An extruded cross-section profile (beam, column, member, pile)
|    -> IfcMaterialProfileSet on the type,
|       IfcMaterialProfileSetUsage on each occurrence
|       (IFC4+ only; this family does not exist in IFC2x3)
|
+- Named parts that are neither layered nor profiled (window
   frame plus glazing, door panel plus hardware)
     -> IfcMaterialConstituentSet (IFC4+; replaces IfcMaterialList)
```

In IFC2x3 a non-layered composite uses the legacy `IfcMaterialList` (a bare
`LIST OF IfcMaterial`). ALWAYS use `IfcMaterialConstituentSet` when
authoring IFC4 or IFC4.3.

## 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: attach a property set to an occurrence

```step
#48=IFCPROPERTYSINGLEVALUE('IsExternal',$,IFCBOOLEAN(.T.),$);
#49=IFCPROPERTYSET(
  '1Hkj5pQ9X8x9bq0d6FZ7yA',  /* GlobalId      */
  #5,                        /* OwnerHistory  */
  'Pset_WallCommon',         /* Name          */
  $,                         /* Description   */
  (#48)                      /* HasProperties */
);
#50=IFCRELDEFINESBYPROPERTIES(
  '2k7sB$Qe9X8x9bq0d6FZ7y',  /* GlobalId                   */
  #5, $, $,                  /* OwnerHistory, Name, Desc   */
  (#21,#22),                 /* RelatedObjects : occurrences */
  #49                        /* RelatingPropertyDefinition  */
);
```

`RelatedObjects` is a `SET [1:?]`: one relationship serves many occurrences.
NEVER place an `IfcWallType` in `RelatedObjects`.

### Pattern: attach a property set to a type

A type holds its sets inline through `HasPropertySets`. No relationship is
created.

```step
#46=IFCPROPERTYSET(
  '3mNp7rTf0Y9y0cr1e7GA8z',#5,'Pset_WallCommon',$,(#48));
#20=IFCWALLTYPE(
  '4pQr9sUg1Z0z1ds2f8HB9$',  /* GlobalId             */
  #5, 'Exterior 300mm', $,   /* OwnerHistory,Name,Desc */
  $,                         /* ApplicableOccurrence */
  (#46),                     /* HasPropertySets      */
  $,                         /* RepresentationMaps   */
  $,                         /* Tag                  */
  $,                         /* ElementType          */
  .STANDARD.                 /* PredefinedType       */
);
```

`HasPropertySets` is the 6th explicit attribute of any `IfcTypeObject`
subtype. NEVER attach a type's properties with `IfcRelDefinesByProperties`.

### Pattern: attach an element quantity

`IfcElementQuantity` uses the SAME relationship as a property set.

```step
#70=IFCQUANTITYAREA('NetSideArea',$,$,12.5,$);
#71=IFCELEMENTQUANTITY(
  '5qRs0tVh2$1$2et3g9IC0_',  /* GlobalId            */
  #5, 'Qto_WallBaseQuantities', $,
  $,                         /* MethodOfMeasurement */
  (#70)                      /* Quantities          */
);
#72=IFCRELDEFINESBYPROPERTIES(
  '6rSt1uWi3_2_3fu4h0JD1A',
  #5, $, $,
  (#21),                     /* RelatedObjects             */
  #71                        /* RelatingPropertyDefinition */
);
```

NEVER store a measured area as an `IfcPropertySingleValue` inside an
`IfcPropertySet`: quantity take-off tools read `IfcElementQuantity` only.

### Pattern: associate a simple material

```step
#80=IFCMATERIAL('Concrete C30/37',$,'concrete');
#81=IFCRELASSOCIATESMATERIAL(
  '7sTu2vXj4A3A4gv5i1KE2B',
  #5, $, $,
  (#21,#22),                 /* RelatedObjects   */
  #80                        /* RelatingMaterial */
);
```

`RelatingMaterial` accepts any `IfcMaterialSelect` choice. `IfcMaterial` is
the simplest. `IfcRelAssociatesMaterial` carries a `WHERE` rule
`NoVoidElement`: a material is NEVER associated with an `IfcOpeningElement`
or an `IfcVirtualElement`.

### Pattern: associate a layered material

The bare set goes on the type; the usage goes on each occurrence.

```step
/* bare set, associated with the IfcWallType */
#90=IFCMATERIALLAYER(#80,0.3,$,'Core',$,'LoadBearing',$);
#91=IFCMATERIALLAYERSET((#90),'EXT-300',$);
#92=IFCRELASSOCIATESMATERIAL(
  '8tUv3wYk5B4B5hw6j2LF3C', #5, $, $, (#20), #91);
/* usage, associated with the IfcWall occurrence */
#93=IFCMATERIALLAYERSETUSAGE(#91,.AXIS2.,.POSITIVE.,-0.15,$);
#94=IFCRELASSOCIATESMATERIAL(
  '9uVw4xZl6C5C6ix7k3MG4D', #5, $, $, (#21), #93);
```

`IfcMaterialLayerSetUsage.ForLayerSet` (`#91`) points back at the same bare
set the type uses. NEVER associate an `IfcMaterialLayerSetUsage` with a
type, and NEVER associate a bare `IfcMaterialLayerSet` with an occurrence
when the type is available.

### Pattern: associate a classification

```step
#60=IFCCLASSIFICATION($,'2015',$,'Uniclass 2015',$,$,$);
#61=IFCCLASSIFICATIONREFERENCE(
  $,                         /* Location        */
  'EF_25_10',                /* Identification  */
  'Walls',                   /* Name            */
  #60,                       /* ReferencedSource: the IfcClassification */
  $, $                       /* Description, Sort */
);
#62=IFCRELASSOCIATESCLASSIFICATION(
  'AvWx5yAm7D6D7jy8l4NH5E',
  #5, $, $,
  (#21,#22),                 /* RelatedObjects        */
  #61                        /* RelatingClassification */
);
```

`IfcClassification` names the SYSTEM; `IfcClassificationReference` names one
CODE inside it. ALWAYS set `ReferencedSource` so a reader can resolve the
code to its system. `RelatingClassification` accepts either entity.

### Pattern: share one definition across many elements

`RelatedObjects` on every enrichment relationship is a `SET [1:?]`. ALWAYS
list every receiving element in ONE relationship rather than cloning the
relationship per element.

```step
#50=IFCRELDEFINESBYPROPERTIES(
  '2k7sB$Qe9X8x9bq0d6FZ7y', #5, $, $,
  (#21,#22,#23,#24),         /* four walls, one relationship */
  #49);
```

One `IfcRelDefinesByProperties` per property set, not per element. The same
holds for `IfcRelAssociatesMaterial` and `IfcRelAssociatesClassification`.

## Anti-Patterns

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

- Pointing `IfcRelDefinesByProperties` at a type object. The `WHERE` rule
  `NoRelatedTypeObject` rejects it; types use `HasPropertySets`.
- Putting an `IfcMaterialLayerSetUsage` on a type. The usage is occurrence
  only; the type takes the bare `IfcMaterialLayerSet`.
- Naming a custom property set with the `Pset_` prefix. It collides with
  the standard library and is misread or ignored.
- Storing a measured quantity inside an `IfcPropertySet`. Quantity take-off
  tools read `IfcElementQuantity` only.
- Cloning one relationship per element instead of listing every element in
  the single relationship's `RelatedObjects` SET.
- Setting `IfcMaterialLayerSet.TotalThickness` by hand. It is a DERIVED
  attribute computed by the schema.

## Reference Links

### This skill

- `references/methods.md`: full positional attribute signatures for every
  enrichment entity, 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-syntax-property-sets`: building the `IfcPropertySet` and its
  `IfcProperty` value entities.
- `ifc-syntax-materials`: the structured material entities in full.
- `ifc-syntax-classifications`: `IfcClassification` and the external
  classification systems.
- `ifc-impl-property-extraction`: the read-side type-versus-occurrence
  property override resolution.
- `ifc-core-relationships`: the objectified relationship pattern.

### Official sources

- IfcPropertySet: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcPropertySet.htm
- IfcRelDefinesByProperties: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelDefinesByProperties.htm
- IfcTypeObject: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcTypeObject.htm
- IfcElementQuantity: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcElementQuantity.htm
- IfcRelAssociatesMaterial: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelAssociatesMaterial.htm
- IfcRelAssociatesClassification: https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelAssociatesClassification.htm

