Skip to content

Ontology Working Group Notes

Gabe Fierro edited this page Sep 2, 2021 · 8 revisions

2021-09-02

Heat Pumps!

We produced a prototype and took notes on where to go forward

@prefix : <urn:heat_pump_impl#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

# TODO:
# - use at BIND in the SPARQL queries to figure out what state you are in
# - maybe start working on standard enumerations for open/close, heat/cool, etc
# - explore dynamic RDF graphs
# - incorporate terms from https://github.com/BrickSchema/Brick/issues/250

# equipment to capture
# - cassette (terminal unit subclass) or convector:
#   - cassette and convector are sibling classes, subclass of terminal unit
# - heat pump (the block that is outside):
#   - hasPart compressor
# - minisplit (whole system): hasPart heat pump, cassette
# - fan

######## Example #############

:my-mode a brick:Mode_Command ;
    brick:timeseries [
        brick:hasTimeseriesId "abc123" ;
    ] ;
. # heat cool mode

:my-minisplit a brick:MiniSplit ;
    brick:hasPoint :my-mode ;
    brick:hasPart :my-heatpump, :my-cassette1, :my-convector1 .

:my-compressor a brick:Compressor .

:my-heatpump a brick:ReversibleHeatPump ;
    brick:hasPart :my-compressor .
# what do we need to know for heat pump:
# - heat source, heat sink
# - current mode (heat/cool/fan/off)

:my-tempsensor1 a brick:Air_Temperature_Sensor .
:my-tempsp1 a brick:Air_Temperature_Setpoint .
:my-cassette1 a brick:Cassette, brick:Terminal_Unit ;
    brick:hasPoint :my-tempsensor1, :my-tempsp1 ;
    brick:hasPart :my-fan1, :my-valve1 ;
    brick:hasLocation :my-room1 ;
    brick:feeds :my-room1 .

:my-fanspeed1 a brick:Speed_Setpoint .
:my-fan1 a brick:Supply_Fan ;
    brick:hasPoint :my-fanspeed1 ;
.

:my-valve-position1 a brick:Valve_Command ;
    brick:timeseries [
        brick:hasTimeseriesId "91239812392" ;
    ]
.

:my-valve1 a brick:Valve ;
    brick:hasPoint :my-valve-position1 ;
    brick:hasConfiguration [
        brick:mode "heating" ;
        a brick:Heating_Valve ;
        brick:dependsOn :my-mode ;
    ] ;
    brick:hasConfiguration [
        brick:mode "cooling" ;
        a brick:Cooling_Valve ;
        brick:dependsOn :my-mode ;
    ] ;
.

# what do we need to know?:
# - location
# - current mode
# - temperature sensor + setpoint

:my-convector1 a brick:Convector, brick:Terminal_Unit ;
    brick:hasLocation :my-room2 ;
    brick:feeds :my-room2 .

:my-room1 a brick:Room .
:my-room2 a brick:Room .
import brickschema
g = brickschema.Graph(load_brick_nightly=True)
g.load_file("2021-09-02.ttl")

# get the timeseries data for the heat/cool mode
q = """SELECT ?mode ?id WHERE {
    ?unit a brick:Terminal_Unit .
    ?unit brick:feeds :my-room1 .
    ?hp brick:hasPart ?unit .
    ?hp a brick:MiniSplit .
    ?hp brick:hasPoint ?mode .
    ?mode a brick:Mode_Command ;
          brick:timeseries/brick:hasTimeseriesId ?id 
}"""
for row in g.query(q):
    print(row)

# assuming we're in heating mode, here's how to get the valve position
# for the unit that heats room 1
q = """SELECT ?id ?valve ?unit WHERE {
    ?unit a brick:Terminal_Unit .
    ?unit brick:feeds :my-room1 .
    ?unit brick:hasPart ?valve .
    ?valve brick:hasPoint ?point .
    ?point a brick:Valve_Command ;
        brick:timeseries/brick:hasTimeseriesId ?id .
    ?valve brick:hasConfiguration/rdf:type brick:Heating_Valve
}"""

for row in g.query(q):
    print(row)

2021-07-22

= Location Discussion again =

  • "symbolic" locations are already in Brick:
    • coarse-grained --- do we need more?
  • not intended to support geospatial queries directly over the Brick model:
    • pull information out, query elsewhere
    • not a given; if we use GeoSPARQL representation, then we have the option of querying directly over RDF. This is a nice feature, but would also support pulling the geospatial data out and putting in a separate store
  • 3 questions:
    • support queries in the database, or not?
    • global or relative? or both?
    • what coordinate system?
    • what serialization format?
  • one participant:
    • global coordinates for the whole building
    • used for showing where buildings are on a map
    • two levels:
      • w/n the building, use floor plans
      • probably a relative coordinate system
  • another participant:
    • use global coordinates everywhere
    • just have one kind of system
  • another participant:
  • for the location of a building:
  • look at use cases from solar studies:
    • when are buildings in the sun, when are they shaded?
    • office towers all around the building
    • is this in our purview?
    • daylighting use cases

2021-07-13

  • Jason's summary notes: https://docs.google.com/document/d/1zqziYcSg7U-Ibz83BRgsLzmgj98UUjGYPM6OUDWRGhA/edit#heading=h.poeupb2sm2mk
  • need to be careful not to "boil the ocean"
  • what are the intended use cases?:
    • some listed in the document
    • one key question is whether we expect users to do geo queries on the Brick model directly, or whether they will use the Brick model to retrieve the geometry and load into another tool
    • the first option (geo queries directly on the Brick model) seems unrealistic; depends on the SPARQL store having support for GeoSPARQL or other format
    • second option is probably the way to go: encode geometry in a common form so that it can be manipulated using external tools
  • two main modes of use:
    • GIS use cases: you actually care about the coordinate accuracy
    • "floor plan coordinates": defined in linear distance; can be converted to global coordinates w/ a reference point
  • Considering the use cases:
    • attach a coordinate to a thing
      • this is probably WKT or GeoJSON in WGS84 in SRID 4326
      • we can represent a latitutde / longitude location of a thing
    • we will also get location data from sources that don't have GIS coords:
      • BIM has good location, but it isn't GIS
      • Autodesk Forge 3D BIM viewer
      • support the JOIN: click in the BIM -> what Brick object is this?
      • analogous to the DOM + onClick/mouseOver handlers in the browser
  • standardizing the approach:
    • option 1: each Brick entity has GCS coordinates; how you get there is your problem
    • option 2: each Brick entity has relative coordinates with a GCS anchor point:
      • would need a standard for representing relative coordinates
      • do we also need a "reference frame" specifying the rotation off of the x/y frame?
    • do we allow both? it is up to you if you want one or both, and if you have both it is up to you to keep them consistent
  • other references:
    • how does Google SketchUp do this?
    • Apple Indoor Map format?

2021-06-01

  • PRs for feedback:
  • related to geocoordinates:
    • so we can encode a lat/lon point for an entity, but what about other kinds of locations?
    • what about referring to bounding boxes on a floor plan PDF?
    • need to light up an asset in some visualization
    • bounds of a room on a document, UBID (https://ubid.pnnl.gov/)
    • need bounding box for an entity for each viz tool
    • should gather use cases from the community (GABE todo):
      • these are all fairly similar: coordinates + coordinate system
  • heat pumps:
    • still a disaster; even more variety in how the term is used
    • anything with a compressor is an AC unit?
    • add a "reverse cycle" tag?
    • "mode context":
      • a generic way of capturing statements that are true when a mode is active

2021-04-29

  • Good uses for "collections":
    • maybe some generic thing that allows the user to define? use hasPart
    • Mario: One set of use cases to consider are those that require arbitrary collections to be instantiated (i.e., some that don't have a physical analogous mapping, such as fluid loops or equipment in a system). For example, one may think of arbitrary collections derived from analysis of time series data; or arbitrary collections derived from point mapping processes; or arbitrary collections from analysis of the ontology graph itself.
  • heat pumps:
    • "commercial chiller" as a subclass of heat pump
    • this can get broken down into centrifugal chiller, screw chiller, etc
    • other kinds to include:
      • absorption/adsorption chillers
      • mini-split systems

2021-04-20

Collections:

  • develop and document an algorithm for placing equipment into systems and loops and other collections based on their properties, definitions and usage; a sort of "pre-processor" for a Brick model

  • keep Collections and the subclasses in the Brick ontology ; use hasPart/isPartOf to indicate membership

  • these kinds of objects might help for commissioning the Brick model -- you can organize equipment into different loops. Maybe have the contents of the loop act as a template for making a Brick model

  • gbXML-like use cases:

    • uses loop constructs
    • an important use case is to be able to tell when two loops intersect
    • for example, a hot water coil can exist in an air loop and a water loop
  • Heat Pumps:

    • adopting a thermodynamic approach to modeling the behavior of different equipment
    • this is in contrast to a product-based approach
    • a few cases feel a little awkward:
      • my gigantic chiller is also a 'heat pump', even though those two terms are colloquially refer to different kinds of thigns
      • what about the AC unit attached to houses?
    • other properties that we want to model:
      • make/model
      • weight / tonnage?
    • specifically, we may have equipment that meet the characteristics of one subclass, but are not nominally identified as that kind of thing:
      • e.g. a water to water heat pump that is considered a chiller vs one that isn't
      • the thermodynamic process isn't sufficient to differentiate!
      • other properties must be considered:
        • e.g. cooling tower installed, feeds an AHU ("chiller")
        • e.g. packaged, standalone unit ("heat pump", "AC unit")
    • to a certain extent everything here is an "edge case":
      • all sorts of configurations
    • how to handle partial information?
      • what if we know it is a chiller, but we don't know what the load-side resource is or what it is connected to?

Related research:

2021-04-15

Chiller Plants and Heat Pumps

  • Agenda:
    • heat pump implementation discussion
    • systems / loops
  • reversing valve commands:
    • does 1 mean 'heating' and 0 mean 'cooling'? or some other configuration
    • some role for an 'entity property' that says normally 'heat' vs normally 'cool'; normally 'left' vs 'right'?
    • need some sort of enumeration that defines what the values of the reversing valve mean
    • another approach: an Reversible X to Y heat pump will source heat from X to heat Y. If the valve is reversed, then heat flows in the other direction
    • need to be able to express what the "reversed" direction means
  • for the class structure:
    • maybe over-specialized?
    • have a Reversible Heat Pump and NonReversible Heat Pump class
    • these could be parents of the X to Y heat pumps; an entity is a member of two classes
    • Alternative: reversible vs non-reversible could be entity properties
  • complications:
    • water to water heat pump:
      • pulling energy otu of space, running chiller at a higher pressure
      • can use the hot water coming out of the chiller as a hot water source
    • "four pipe systems":
      • air to air systems but it can suck and distribute heat in different directions
      • can reject heat into any of the loops at one point in time
      • if you have heating and cooling demands in the building at the same time, this can be much more efficient
    • this needs the ability to express loops
    • condenser water loop:
      • can contain either hot water or cold water depending on the seasonality
      • could be pulling heat out or putting heat in
      • harder to express the idea of a "hot water" loop or a "chilled water" loop because what is in the loop will change over time depending on the configuration + season
  • people think of an equipment as "pushing" heat or "pushing" cool into the loop:
    • or it is reversible; reversible is part of that enumeration
    • if the heat flow is reversible, then you need to query some other point to tell you what state it is in
    • could represent this as a "heating/cooling" mode:
      • either a static property or a Point
  • can refer to two sides as "outdoor coil" and "indoor coil":
    • function of the two coils changes when the valve switches
    • however these terms don't generalize to water to water and water to air
  • questions:
    • who is feeding that coil?
    • which equipment should I dispatch to get the hot or cold water to that coil in the most efficient or cost-effective manner?
  • Articles for background:

2021-04-06

Chiller Plants and Heat Pumps

Goal: to arrive at a coherent and flexible class-based representation of heat pumps and chiller plants in Brick.

The way that I propose to approach this is to make a list of the broad types of equipment that will need to be modeled. For each of these, we will make a list of the properties and enumerations that must be captured. Some of these will be folded into the class organization; others will be implemented as entity properties.

Competency Questions:

  • "what thermal machine is providing the heating/cooling in this building?"
  • "where does room/VAV/zone X get its hot air from?" "what heats that hot air?"

Outline of the solution:

  • Class structure:

    • Establish a Heat Pump class, which subclasses from HVAC Equipment.
    • Define subclasses of Water-Sourced, Air-Sourced and Ground-Sourced heat pumps:
      • organizes heat pumps by the non-load-side resource
    • Define subclasses of the above which indicate the load-side resource, e.g. Water-To-Air Heat Pump:
      • some of these are further subclassed as reversible or non-reversible
    • Class structure contains Chillers as a subclass of Heat Pump:
      • some Chiller subtypes are also listed under the X-to-Y Heat Pump classes
    • see all classes at https://github.com/BrickSchema/Brick/pull/252
  • Semantic properties of classes:

    • When you build a model, it is easiest to indicate the asset type:
      • e.g. "X is a water-cooled chiller"
    • When you query a model, want the option of identifying equipment by its function
      • e.g. "what resource is cooling the water going to the cooling coil?"
      • or you can query by type: "which kinds of chillers does the site have?"
    • Use SHACL or OWL inference to provide this property
  • Key to this implementation will be the ability to describe a particular heat pump using either the class name (for well-known configurations) or a set of properties.

  • Then the system will be able to figure out when those two different methods of expression are equivalent

How to parameterize heat pumps?:

  • heat flow direction:

    • heat or cool
    • this may be a static property, e.g. for non-reversible heat pumps
    • or it maybe a dynamic property for reversible heat pumps
  • reversible vs non-reversible:

    • a static property that tells whether or not the heat pump is reversible
  • load-side resource:

    • what is heated or cooled: Air, Water, Refrigerant
  • non-load-side resource:

    • what is the medium acting as the reservoir of heat or the sink?
    • we could not think of a good industry-standard term that is generic to whether the heat pump is heating or cooling
    • if cooling, the non-load is a "sink"
    • if heating, the non-load is a "source"
    • if in a reversible system, the non-load may be a source or a sink!
    • in certain kinds of systems, the two sides are called evaporator-side and condenser-side
    • Given that many technical documents refer to "Air-Source" or "Ground-Source" heat pump, even in cooling configurations, it makes sense for the non-load resource to be referred to as a "source"
  • heat pump composition and topology:

    • most heat pumps are single package units
    • as a result, we expect most heat pumps models to simply instantiate the correct heat pump class and attach Point instances using brick:hasPoint
    • in more advanced use cases, one may instantiate some components of the heat pump and attach them to the heat pump using brick:hasPart:
      • e.g. for modeling reversing valves
    • in even more advanced use cases, one may model the connections between the components of the heat pump using brick:feeds. However, this raises an issue as we will see below

Example models:

  • each of these builds on the previous ones

  • instantiating a reversible air-to-air heat pump

    @prefix brick: <https://brickschema.org/schema/Brick#> .
    @prefix bldg: <urn:bldg#> .
    
    bldg:heatPump1  a   brick:Reversible_Air_To_Air_Heat_Pump ;
        brick:hasPoint  bldg:dis_air_sensor .
    bldg:dis_air_sensor a   brick:Discharge_Air_Temperature_Sensor .
  • modeling the reversing valve w/ direction

    @prefix brick: <https://brickschema.org/schema/Brick#> .
    @prefix bldg: <urn:bldg#> .
    
    bldg:heatPump1  a   brick:Reversible_Air_To_Air_Heat_Pump ;
        brick:hasPoint  bldg:dis_air_sensor ;
        brick:hasPart   bldg:rv .
    bldg:dis_air_sensor a   brick:Discharge_Air_Temperature_Sensor .
    bldg:rv a   brick:Reversing_Valve ;
        brick:hasPoint  bldg:rv_cmd .
    bldg:rv_cmd     a   brick:Reversing_Valve_Command .  # determines heat/cool mode
  • modeling more internal composition of the heat pump

    @prefix brick: <https://brickschema.org/schema/Brick#> .
    @prefix bldg: <urn:bldg#> .
    
    bldg:heatPump1  a   brick:Reversible_Air_To_Air_Heat_Pump ;
        brick:hasPoint  bldg:dis_air_sensor ;
        brick:hasPart   bldg:rv, bldg:evaporator1, bldg:condenser1, bldg:compressor1 .
        
    bldg:dis_air_sensor a   brick:Discharge_Air_Temperature_Sensor .
    
    bldg:rv a   brick:Reversing_Valve ;
        brick:hasPoint  bldg:rv_cmd .
    bldg:rv_cmd     a   brick:Reversing_Valve_Command .  # determines heat/cool mode
    
    bldg:evaporator1    a   brick:Evaporator .
    bldg:condenser1     a   brick:Condenser .
    bldg:compressor1    a   brick:Compressor ;
        brick:hasPoint  bldg:comp_start ;
    .
    bldg:comp_start a brick:Start_Stop_Command .
  • adding internal topology of the heat pump

    @prefix brick: <https://brickschema.org/schema/Brick#> .
    @prefix bldg: <urn:bldg#> .
    
    bldg:heatPump1  a   brick:Reversible_Air_To_Air_Heat_Pump ;
        brick:hasPoint  bldg:dis_air_sensor ;
        brick:hasPart   bldg:rv, bldg:evaporator1, bldg:condenser1, bldg:compressor1 .
        
    bldg:dis_air_sensor a   brick:Discharge_Air_Temperature_Sensor .
    
    bldg:rv a   brick:Reversing_Valve ;
        brick:hasPoint  bldg:rv_cmd .
    bldg:rv_cmd     a   brick:Reversing_Valve_Command .  # determines heat/cool mode
    
    bldg:evaporator1    a   brick:Evaporator .
    bldg:condenser1     a   brick:Condenser .
    bldg:compressor1    a   brick:Compressor ;
        brick:hasPoint  bldg:comp_start ;
    .
    bldg:comp_start a brick:Start_Stop_Command .
    
    # this is where we run into modeling issues. There are two "correct" ways
    # to model the topology, depending on which mode the heat pump is in: heat/cool
    # if in heating configuration...
    bldg:evaporator1    brick:feeds bldg:compressor1 .
    bldg:compressor1    brick:feeds bldg:condenser1 .
    bldg:condenser1     brick:feeds bldg:evalve1 .
    bldg:evalve1        brick:feeds bldg:rvalve1 .
    bldg:rvalve1        brick:feeds bldg:evaporator1 .
    
    # if in cooling configuration...
    bldg:evaporator1    brick:isFedBy bldg:compressor1 .
    bldg:compressor1    brick:isFedBy bldg:condenser1 .
    bldg:condenser1     brick:isFedBy bldg:evalve1 .
    bldg:evalve1        brick:isFedBy bldg:rvalve1 .
    bldg:rvalve1        brick:isFedBy bldg:evaporator1 .
    
    # one solution is to introduce a *new* relationship which
    # captures topology but not direction
    brick:connectedTo   a   owl:ObjectProperty .
    brick:feeds rdfs:subPropertyOf  brick:connectedTo .
    brick:isFedBy rdfs:subPropertyOf  brick:connectedTo .
    
    # rather than feeds/isFedBy, the model can just capture
    # the connections instead of direction. This is now correct
    # in either configuration
    bldg:evaporator1    brick:connectedTo bldg:compressor1 .
    bldg:compressor1    brick:connectedTo bldg:condenser1 .
    bldg:condenser1     brick:connectedTo bldg:evalve1 .
    bldg:evalve1        brick:connectedTo bldg:rvalve1 .
    bldg:rvalve1        brick:connectedTo bldg:evaporator1 .