Skip to content

Validation failure when Equipment feeds a Loop (e.g. Heat Exchanger → Hot Water Loop) #729

@LiMingchen159

Description

@LiMingchen159

Hi @gtfierro , @carlosduarteroa👋

First, thank you both for the great work on the Brick schema — I’ve been using it in my current project and it’s been very helpful.
I’m currently collaborating with @carlosduarteroa and working with a model based on his implementation (thanks, @carlosduarteroa! 🙏).


Context

During validation, I found a case that cannot be validated successfully — when a piece of equipment feeds a hot water loop.
Example below:

hhws:building29.heat_exchanger a brick:Heat_Exchanger ;
    rdfs:label "Heat Exchanger - Building 29" ;
    brick:feeds hhws:building29.hws.secondary_loop .

hhws:building29.hws.secondary_loop a brick:Hot_Water_Loop ;
    rdfs:label "Hot Water Loop - Building 29" ;

This modeling seems semantically correct (the heat exchanger provides heat to the secondary loop),
but the SHACL validation fails because brick:Equipment’s feeds property does not currently allow brick:Loop as a valid target class.


Proposed Change

To better reflect this common and physically valid relationship (e.g., Heat Exchanger → Loop, Boiler → Hot Water Loop),
I suggest allowing brick:Loop as a valid target for both brick:Equipment and brick:HVAC_Equipment.


1️⃣ Updated brick:Equipment

brick:Equipment a owl:Class,
        sh:NodeShape ;
    rdfs:label "Equipment"^^xsd:string ;
    rdfs:subClassOf brick:Class,
        brick:Entity,
        rec:Asset ;
    skos:definition "devices that serve all or part of the building and may include electric power, lighting, transportation, or service water heating, including, but not limited to, furnaces, boilers, air conditioners, heat pumps, chillers, water heaters, lamps, luminaires, ballasts, elevators, escalators, or other devices or installations."@en ;
    sh:not [ sh:class brick:Location ;
            sh:message "Instances of Equipment cannot be Locations." ],
        [ sh:class brick:Substance ;
            sh:message "Instances of Equipment cannot be Substances." ],
        [ sh:class brick:Quantity ;
            sh:message "Instances of Equipment cannot be Quantities." ],
        [ sh:class brick:Collection ;
            sh:message "Instances of Equipment cannot be Collections." ],
        [ sh:class brick:Point ;
            sh:message "Instances of Equipment cannot be Points." ],
        [ sh:class brick:EntityProperty ;
            sh:message "Instances of Equipment cannot be EntityProperties." ] ;
    sh:property [ sh:class brick:Equipment ;
            sh:message "A piece of Equipment's parts should be always other Equipment." ;
            sh:path brick:hasPart ],
        [ sh:class brick:Point ;
            sh:message "A piece of Equipment can have Points." ;
            sh:path brick:hasPoint ],
        [ sh:message "Equipment can be part of a Collection, System or other Equipment." ;
            sh:or ( [ sh:class brick:System ] [ sh:class brick:Equipment ] [ sh:class brick:Collection ] ) ;
            sh:path brick:isPartOf ],
        [ sh:message "A piece of Equipment can be located only at a Location/Space" ;
            sh:or ( [ sh:class brick:Location ] [ sh:class rec:Space ] ) ;
            sh:path brick:hasLocation ],
        [ sh:message "A piece of Equipment can feed a Equipment or Location/Space." ;
-            sh:or ( [ sh:class brick:Equipment ] [ sh:class brick:Location ] [ sh:class rec:Space ] )  ;
+            sh:or ( [ sh:class brick:Equipment ] [ sh:class brick:Location ] [ sh:class rec:Space ] [shc:class brick:Loop ] )  ;
            sh:path brick:feeds ],

2️⃣ Updated brick:HVAC_Equipment

brick:HVAC_Equipment a owl:Class,
        sh:NodeShape ;
    rdfs:label "HVAC Equipment"@en ;
    rdfs:subClassOf brick:Equipment ;
    skos:definition "See Heating_Ventilation_Air_Conditioning_System"@en ;\
-     sh:property [ sh:or ( [ sh:class brick:HVAC_Equipment ] [ sh:class brick:Valve ] [ sh:class rec:Space ] ) ;
+    sh:property [ sh:or ( [ sh:class brick:HVAC_Equipment ] [ sh:class brick:Valve ] [ sh:class rec:Space ] [sh:class brick:Loop] ) ;
            sh:path brick:feeds ],
        [ sh:or ( [ sh:class brick:HVAC_Equipment ] [ sh:class brick:Valve ] ) ;
            sh:path brick:hasPart ] ;
    sh:rule [ a sh:TripleRule ;
            sh:object tag:Equipment ;
            sh:predicate brick:hasTag ;
            sh:subject sh:this ],
        [ a sh:TripleRule ;
            sh:object tag:HVAC ;
            sh:predicate brick:hasTag ;
            sh:subject sh:this ] ;
    brick:hasAssociatedTag tag:Equipment,
        tag:HVAC .

Summary

  • Issue: SHACL validation fails when Equipment feeds a Loop (e.g., Heat Exchanger → Hot Water Loop).

  • Proposal: Add brick:Loop as a valid target for the feeds property of both brick:Equipment and brick:HVAC_Equipment.

  • Rationale: This reflects common HVAC semantics, aligns with physical reality, and prevents false negatives due to overly strict parent class constraints.

  • Impact: Minimal, backward-compatible schema change that improves modeling flexibility and validation consistency.

If this makes sense, I’d be happy to open a PR for review.
Thanks again for your great work on Brick!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions