IfcTester not properly check PredefinedType requirements
My colleagues and I are being challenged with limiting PredefinedTypes in a model. The small example I have to illustrate is attached along with the IDS. We want to, in this example case, limit all IfcBeam entities to have PredefinedType to be either BEAM or PILECAP. BEAM is an official predefined type and PILECAP is user defined.
For the attached file, I expect four IfcBeam entities to pass because their predefined type is BEAM or PILECAP, either directly on the IfcBeam entity, or inherited through an IfcBeamType entity. Two IfcBeam entities are expected to fail because their types are JOIST and GRADEBEAM.
Only the single entity with IfcBeam.PredefinedType=BEAM is passing.
Is this a bug in IfcTester? Is this a misunderstanding on our part on how IDS is supposed to work?
Comments
@Moult any ideas as to why IfcTester (and other IDS checkers) can identify entities from a predefined type enumeration for applicability but not requirements?
By sheer luck, I got this to work. The key was to have IfcBeam be the requirement and IfcBeam with predefined type enumeration {BEAM;PILECAP}.
I don't know why this works instead my original attempt, so if someone has an explanation, please share.
IDS itself is a checker..IDS is used mainly for this purposes.
I'm not sure, but here's an AI breakdown...
Why your IDS only passes one beam — Attribute facet vs. Entity facet for
PredefinedTypeShort answer: This is not a bug in IfcTester. The original IDS uses an Attribute facet to test
PredefinedType, which only reads the raw, literal attribute value off a single instance. The working IDS uses the Entity facet'spredefinedType, which is the mechanism the IDS spec intends for this job. The Entity facet resolves the two things a predefined-type check actually needs, and the Attribute facet does not.What the original IDS does
The Attribute facet reads the literal value of the
PredefinedTypeattribute on that one instance and compares it to the restriction. It does not:.USERDEFINED.to theObjectTypestring (e.g.PILECAP).IfcBeamType.That single fact explains every row in the report:
.BEAM."BEAM".USERDEFINED.,ObjectType = PILECAP"USERDEFINED"$, type is.BEAM.None(empty)$, type isPILECAP/.USERDEFINED.None(empty).JOIST."JOIST".USERDEFINED.,ObjectType = GRADEBEAM"USERDEFINED"So Beams 2–4 conceptually satisfy your rule, but the attribute facet has no way to know that — it is faithfully reporting the literal stored values.
Why the "lucky" IDS works
The Entity facet's
predefinedTypegoes through a completely different evaluation. Internally it calls IfcOpenShell'sget_predefined_type()/is_userdefined_type()helpers, which:ObjectTypestring when the value isUSERDEFINED, andIfcBeamType) when the instance itself has none.That's why Beams 1–4 all pass and only
JOIST/GRADEBEAMfail — exactly the result you expected.The takeaway
In IFC, a "predefined type" is a composite concept: the instance's enumerated value, plus the
ObjectTypeoverride when it'sUSERDEFINED, plus inheritance from the element's type. The Entity facet'spredefinedTypeis built to evaluate all three; the Attribute facet is a literal, single-instance attribute check and was never designed to.So your second attempt isn't luck — it's the correct, spec-intended way to constrain predefined types. IfcTester is behaving consistently with the IDS specification.
This is really interesting. Up until now I always thought you had to test Occurence and Type attributes independently (as attributes are not inherited). Thanks for sharing.