SuperAPI AI Directory

ifc-syntax-units

Testing & quality

View repository

Updated 10-15 22:18

About this skill

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

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.