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.

    steverugiemiliotassowalpasemhustej
  • 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 PredefinedType

    Short 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's predefinedType, 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

    <ids:attribute cardinality="required">
      <ids:name><ids:simpleValue>PredefinedType</ids:simpleValue></ids:name>
      <ids:value>
        <xs:restriction base="xs:string">
          <xs:enumeration value="BEAM" />
          <xs:enumeration value="PILECAP" />
        </xs:restriction>
      </ids:value>
    </ids:attribute>
    

    The Attribute facet reads the literal value of the PredefinedType attribute on that one instance and compares it to the restriction. It does not:

    1. Resolve .USERDEFINED. to the ObjectType string (e.g. PILECAP).
    2. Inherit the predefined type from the associated IfcBeamType.

    That single fact explains every row in the report:

    Beam IFC definition What the attribute facet sees Result
    Beam1 .BEAM. "BEAM" ✅ pass
    Beam2 .USERDEFINED., ObjectType = PILECAP "USERDEFINED" ❌ "does not match"
    Beam3 $, type is .BEAM. None (empty) ❌ "is empty"
    Beam4 $, type is PILECAP / .USERDEFINED. None (empty) ❌ "is empty"
    Beam5 .JOIST. "JOIST" ❌ correctly fails
    Beam6 .USERDEFINED., ObjectType = GRADEBEAM "USERDEFINED" ❌ correctly fails

    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

    <ids:entity>
      <ids:name><ids:simpleValue>IFCBEAM</ids:simpleValue></ids:name>
      <ids:predefinedType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="BEAM" />
          <xs:enumeration value="PILECAP" />
        </xs:restriction>
      </ids:predefinedType>
    </ids:entity>
    

    The Entity facet's predefinedType goes through a completely different evaluation. Internally it calls IfcOpenShell's get_predefined_type() / is_userdefined_type() helpers, which:

    • Return the ObjectType string when the value is USERDEFINED, and
    • Fall back to the predefined type of the associated type element (IfcBeamType) when the instance itself has none.

    That's why Beams 1–4 all pass and only JOIST / GRADEBEAM fail — exactly the result you expected.


    The takeaway

    In IFC, a "predefined type" is a composite concept: the instance's enumerated value, plus the ObjectType override when it's USERDEFINED, plus inheritance from the element's type. The Entity facet's predefinedType is 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.

    Rule of thumb: To constrain a PredefinedType, always use the Entity facet's predefinedType, not an Attribute facet named PredefinedType.

    semhustej
  • 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.

Sign In or Register to comment.