# Ifc Syntax Units

> Use when you need to declare, read, or debug the units of an IFC model : the project unit assignment, SI units with a prefix (millimetre = METRE + MILLI), imperial units via a conversion factor, compound units like velocity, monetary currency, and how a property value resolves to a concrete unit. Prevents a model that is off by 1000x because millimetres were declared as metres, a duplicate unit type that breaks the WR01 rule, inventing a separate "millimetre" unit name, and embedding a currency string in a numeric value. Covers IfcUnitAssignment, IfcSIUnit, IfcConversionBasedUnit and the WithOffset subtype, IfcDerivedUnit with IfcDerivedUnitElement, IfcContextDependentUnit, IfcMonetaryUnit, IfcMeasureWithUnit, the unit-propagation chain, and IFC2x3 / IFC4 / IFC4.3 version differences. Keywords: IFC units, IfcUnitAssignment, IfcSIUnit, IfcSIPrefix, IfcSIUnitName, IfcConversionBasedUnit, IfcDerivedUnit, IfcDerivedUnitElement, IfcContextDependentUnit, IfcMonetaryUnit, IfcMeasureWithUnit, IfcUnitEnum, IfcDerivedU

- Skill: `impertio-studio/ifc-syntax-units` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/ifc-syntax-units`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/ifc-syntax-units/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-syntax-units

---


# IFC Syntax : Units

An IFC model declares its units once, at the project level, and every measure value
rides on that declaration. This skill covers the unit entities, how they are
assembled, and how a property value resolves to a concrete unit.

Applies to IFC2x3, IFC4, and IFC4.3. One entity changed type across versions :
see the Version Differences section.

## Quick Reference

### The project unit assignment

`IfcUnitAssignment` is the project-global unit set. Verified verbatim (IFC4.3) :

```
ENTITY IfcUnitAssignment;
	Units : SET [1:?] OF IfcUnit;
 WHERE
	WR01 : IfcCorrectUnitAssignment(Units);
END_ENTITY;
```

It is referenced by `IfcContext` (the supertype of `IfcProject`) through the
attribute `UnitsInContext`. The `WR01` rule enforces that each unit type appears
**only once** : one length unit, one area unit, one monetary unit, and so on.

ALWAYS attach exactly one `IfcUnitAssignment` to the project via `UnitsInContext`.
NEVER place two units of the same type in it : that breaks `WR01`.

### The IfcUnit select tree

`IfcUnit` is the select that every unit slot accepts :

```
IfcUnit (SELECT)
├── IfcNamedUnit (abstract)        attributes : Dimensions, UnitType (IfcUnitEnum)
│   ├── IfcSIUnit                  an SI unit, optionally prefixed
│   ├── IfcConversionBasedUnit     a non-SI unit defined by a conversion factor
│   │   └── IfcConversionBasedUnitWithOffset   adds a ConversionOffset
│   └── IfcContextDependentUnit    a unit with no SI conversion (context-defined)
├── IfcDerivedUnit                 a compound unit built from exponents
└── IfcMonetaryUnit                a currency
```

### IfcSIUnit

Verified verbatim (IFC4.3), `IfcSIUnit` is a subtype of `IfcNamedUnit` :

```
ENTITY IfcSIUnit
 SUBTYPE OF (IfcNamedUnit);
	Prefix : OPTIONAL IfcSIPrefix;
	Name : IfcSIUnitName;
 DERIVE
	SELF\IfcNamedUnit.Dimensions : IfcDimensionalExponents
		:= IfcDimensionsForSIUnit (SELF.Name);
END_ENTITY;
```

- `Name` is an `IfcSIUnitName` enumeration value (29 values : `METRE`,
  `SQUARE_METRE`, `CUBIC_METRE`, `GRAM`, `SECOND`, `RADIAN`, `NEWTON`, `PASCAL`,
  `WATT`, `DEGREE_CELSIUS`, ...).
- `Prefix` is an optional `IfcSIPrefix` enumeration value (16 values : `KILO`,
  `MILLI`, `MICRO`, `CENTI`, `DECI`, `MEGA`, `GIGA`, ...).
- `Dimensions` is DERIVED : it is computed from `Name`, NEVER serialized.
- `UnitType` is inherited from `IfcNamedUnit` and is an `IfcUnitEnum` value.

A millimetre is `Name = METRE` with `Prefix = MILLI`. ALWAYS express a metric scale
with the `Prefix` enumeration. NEVER invent a `MILLIMETRE` name : there is no such
`IfcSIUnitName` value.

Full enum lists : see `references/methods.md`.

### IfcConversionBasedUnit

For a non-SI unit (inch, foot, pound) defined by a conversion from an SI unit.
Subtype of `IfcNamedUnit`. Attributes : `Name` (`IfcLabel`), `ConversionFactor`
(`IfcMeasureWithUnit`). An inch is a `ConversionFactor` of `25.4` expressed in
millimetres.

`IfcConversionBasedUnitWithOffset` is a subtype that adds `ConversionOffset`
(`IfcReal`), applied after the factor. It exists for temperature scales such as
Fahrenheit, where a conversion needs both a factor and an offset.

### IfcDerivedUnit and IfcDerivedUnitElement

For a compound unit built from products and quotients of other units. Verified
verbatim (IFC4.3) :

```
ENTITY IfcDerivedUnit;
	Elements : SET [1:?] OF IfcDerivedUnitElement;
	UnitType : IfcDerivedUnitEnum;
	UserDefinedType : OPTIONAL IfcLabel;
	Name : OPTIONAL IfcLabel;
 DERIVE
	Dimensions : IfcDimensionalExponents := IfcDeriveDimensionalExponents(Elements);
 WHERE
	WR1 : (SIZEOF (Elements) > 1) OR
		((SIZEOF (Elements) = 1) AND (Elements[1].Exponent <> 1));
	WR2 : (UnitType <> IfcDerivedUnitEnum.USERDEFINED) OR
		((UnitType = IfcDerivedUnitEnum.USERDEFINED) AND
		 (EXISTS(SELF.UserDefinedType)));
END_ENTITY;
```

Each `IfcDerivedUnitElement` pairs a `Unit` with an `Exponent` (`INTEGER`). A linear
velocity is a length unit with exponent `1` plus a time unit with exponent `-1`.

`UnitType` is an `IfcDerivedUnitEnum` value (52 values : `LINEARVELOCITYUNIT`,
`MASSDENSITYUNIT`, `THERMALTRANSMITTANCEUNIT`, `ACCELERATIONUNIT`, `TORQUEUNIT`,
`USERDEFINED`, ...). When `UnitType = USERDEFINED`, `UserDefinedType` is required by
`WR2`.

### IfcContextDependentUnit and IfcMonetaryUnit

- `IfcContextDependentUnit` : a named unit with no conversion to SI, defined by
  context (subtype of `IfcNamedUnit`).
- `IfcMonetaryUnit` : carries a currency. In **IFC4 and IFC4.3** its `Currency`
  attribute is an `IfcLabel` holding a three-letter ISO 4217 code (`EUR`, `USD`,
  `GBP`). In **IFC2x3** `Currency` was an `IfcCurrencyEnum` enumeration. See the
  Version Differences section.

### IfcMeasureWithUnit : pairing a value with a unit

`IfcMeasureWithUnit` pairs one value with one unit. Attributes : `ValueComponent`
(`IfcValue`, the magnitude) and `UnitComponent` (`IfcUnit`, the unit). It is the
bridge entity used inside `IfcConversionBasedUnit.ConversionFactor` and anywhere a
single value must explicitly carry its own unit.

### The unit-propagation chain

A measure value almost never carries its unit inline. The unit is resolved through a
chain :

```
A property value (IfcPropertySingleValue.NominalValue)
  carries a MEASURE TYPE (for example IfcLengthMeasure)
        |
        v
The measure type maps to a UNIT TYPE (IfcUnitEnum, for example LENGTHUNIT)
        |
        v
The project IfcUnitAssignment holds exactly ONE unit per unit type
        |
        v
That unit is the value's unit  --  UNLESS the property's own Unit
attribute (an IfcUnit) overrides it locally.
```

ALWAYS resolve a value's unit through this chain. NEVER assume a bare number is in
metres : the measure type plus the project `IfcUnitAssignment` give it a unit.

### Version differences (compact)

| Item | IFC2x3 | IFC4 | IFC4.3 |
|------|--------|------|--------|
| `IfcMonetaryUnit.Currency` type | `IfcCurrencyEnum` (enum) | `IfcLabel` (ISO 4217 string) | `IfcLabel` |
| `IfcConversionBasedUnit.HasExternalReference` inverse | absent | present | present |
| `IfcConversionBasedUnitWithOffset` | absent | present | present |

## Decision Trees

### Which unit entity for a given unit?

```
What kind of unit do you need?
|
+-- A pure SI unit (metre, gram, second, newton, pascal)
|   --> IfcSIUnit. Use Prefix for a scale (MILLI, KILO).
|
+-- A non-SI unit with a fixed conversion (inch, foot, pound)
|   --> IfcConversionBasedUnit. ConversionFactor is an IfcMeasureWithUnit.
|       Needs an offset too (Fahrenheit)? --> IfcConversionBasedUnitWithOffset.
|
+-- A compound unit (velocity, density, U-value)
|   --> IfcDerivedUnit with one IfcDerivedUnitElement per factor.
|
+-- A currency
|   --> IfcMonetaryUnit.
|
+-- A unit with no SI conversion, defined only by project context
    --> IfcContextDependentUnit.
```

### How does a value get its unit?

```
Does the property carry an explicit Unit attribute?
|
+-- YES --> that explicit IfcUnit is the value's unit (local override).
|
+-- NO  --> the value's measure type selects an IfcUnitEnum unit type;
            the project IfcUnitAssignment holds the one unit of that type;
            that unit applies.
```

### Millimetre : prefix or new name?

```
Need millimetres / centimetres / kilometres?
|
+-- ALWAYS : IfcSIUnit with Name = METRE and Prefix = MILLI / CENTI / KILO.
|
+-- NEVER : there is no MILLIMETRE, CENTIMETRE, or KILOMETRE in IfcSIUnitName.
            Inventing one is not a valid enumeration value.
```

## Patterns

### Pattern : Declare one IfcUnitAssignment per project

ALWAYS attach exactly one `IfcUnitAssignment` to the project through
`IfcContext.UnitsInContext`. Populate its `Units` set with one unit per unit type
the model uses : a length unit, an area unit, a volume unit, a plane-angle unit, and
so on.
NEVER place two units of the same unit type in one `IfcUnitAssignment` : the `WR01`
rule (`IfcCorrectUnitAssignment`) rejects a duplicate unit type and the file is
schema-invalid.
ALWAYS declare every unit type the model's measure values need : a value whose unit
type is absent from the assignment cannot be resolved.

See `ifc-core-spatial-structure` for `IfcProject` and `UnitsInContext`.

### Pattern : Express a metric scale with the prefix

ALWAYS express millimetres, centimetres, and kilometres as `IfcSIUnit` with
`Name = METRE` and the `Prefix` enumeration (`MILLI`, `CENTI`, `KILO`). The same
holds for other quantities : a square millimetre is `Name = SQUARE_METRE`,
`Prefix = MILLI`.
NEVER write a `Name` value that is not in the 29-value `IfcSIUnitName` enumeration.
`MILLIMETRE` is not a valid name ; `METRE` plus `Prefix = MILLI` is the only correct
form.

### Pattern : Express a non-SI unit via a conversion

ALWAYS model a non-SI unit (inch, foot, pound) as an `IfcConversionBasedUnit` whose
`ConversionFactor` is an `IfcMeasureWithUnit` : the magnitude plus the SI unit it
converts from. An inch is `25.4` paired with a millimetre `IfcSIUnit`.
ALWAYS use `IfcConversionBasedUnitWithOffset` when the conversion needs an offset as
well as a factor : a Fahrenheit scale needs both. Its `ConversionOffset` (`IfcReal`)
is applied after the inherited factor.

### Pattern : Build a compound unit

ALWAYS build a compound unit as an `IfcDerivedUnit` whose `Elements` set holds one
`IfcDerivedUnitElement` per factor, each pairing a `Unit` with an `INTEGER`
`Exponent`. A linear velocity is a length unit at exponent `1` and a time unit at
exponent `-1`.
ALWAYS set `UserDefinedType` when `UnitType = IfcDerivedUnitEnum.USERDEFINED` : the
`WR2` rule requires it.
NEVER write a single-element `IfcDerivedUnit` whose one element has exponent `1` :
the `WR1` rule forbids it (such a unit is just the base unit, not a derived one).

### Pattern : Resolve a value's unit through the propagation chain

ALWAYS resolve the unit of a measure value through the chain : measure type to unit
type, unit type to the project `IfcUnitAssignment`, unless an explicit `Unit`
attribute on the property overrides it.
ALWAYS treat an explicit `Unit` on a property as a local override of the project-
global unit for that one property only.
NEVER assume a bare numeric value is in metres, millimetres, or any specific unit
without resolving it : the number is unit-agnostic.

See `ifc-syntax-data-types` for measure types and `ifc-syntax-property-sets` for the
property entities that carry the `Unit` attribute.

### Pattern : Honour the version differences

ALWAYS write `IfcMonetaryUnit.Currency` as an `IfcLabel` (an ISO 4217 string such as
`'EUR'`) in IFC4 and IFC4.3.
ALWAYS write `IfcMonetaryUnit.Currency` as an `IfcCurrencyEnum` value in IFC2x3 : in
that version the attribute was a fixed enumeration, not a free string.
NEVER carry a currency inside a monetary value : `IfcMonetaryMeasure` is a bare
number, and `IfcMonetaryUnit` carries the currency separately.

## Reference Links

- `references/methods.md` : the complete verified entity definitions, the full
  `IfcUnitEnum` (30 values), `IfcDerivedUnitEnum` (52 values), `IfcSIUnitName`
  (29 values), `IfcSIPrefix` (16 values), the `IfcUnit` select, and the per-version
  difference table.
- `references/examples.md` : worked STEP scenarios : a unit assignment, a millimetre
  unit, an inch conversion unit, a velocity derived unit, a Fahrenheit offset unit,
  a monetary unit, and reading a value through the propagation chain.
- `references/anti-patterns.md` : the failure modes this skill prevents, each with
  the reason it fails.

### Official sources

- IfcUnitAssignment : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcUnitAssignment.htm
- IfcSIUnit : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcSIUnit.htm
- IfcConversionBasedUnit : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcConversionBasedUnit.htm
- IfcDerivedUnit : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcDerivedUnit.htm
- IfcMonetaryUnit : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcMonetaryUnit.htm
- IfcMeasureWithUnit : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcMeasureWithUnit.htm

### Related skills

- `ifc-syntax-data-types` : measure types and how a measure type implies a unit type.
- `ifc-syntax-property-sets` : the property entities whose `Unit` attribute overrides
  the project-global unit.
- `ifc-errors-property-set-mistakes` : the unit-related failure modes in real models.

