Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap ZoneHVAC:EvaporativeCoolerUnit #215

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from

Conversation

joseph-robertson
Copy link
Contributor

@joseph-robertson joseph-robertson commented Jan 7, 2025

Pull request overview

Companion PR:

Link to relevant GitHub Issue(s) if appropriate:

Link to the Ubuntu 22.04 .deb installer to use for CI Testing. If not set, it will default to latest official release.
[OpenStudio Installer]: http://openstudio-ci-builds.s3-website-us-west-2.amazonaws.com/PR-5326/OpenStudio-3.9.1-alpha%2B73365b115a-Ubuntu-22.04-x86_64.deb

This Pull Request is concerning:

  • Case 1 - NewTest: a new test for a new model API class,
  • Case 2 - TestFix: a fix for an existing test. The GitHub issue should be referenced in the PR description
  • Case 3 - NewTestForExisting: a new test for an already-existing model API class
  • Case 4 - Other: Something else, like maintenance of the repo, or just committing test results with a new OpenStudio version.

Depending on your answer, please fill out the required section below, and delete the three others.
Leave the review checklist in place.


Case 1: New test for a new model API class

This pull request is in relation with the Pull Request:

and will specifically test for the following classes:

  • ZoneHVACEvaporativeCoolerUnit

Work Checklist

The following has been checked to ensure compliance with the guidelines:

  • Tests pass either:

    • with official OpenStudio release (include version):

      • A matching OSM test has been added from the successful run of the Ruby one with the official OpenStudio release
      • The label AddedOSM has been added to this PR
      • All new out.osw have been committed
    • with current develop (incude SHA):

      • The label PendingOSM has been added to this PR
      • A matching OSM test has not yet been added because the official release is pending, but model_tests.rb has a TODO.
        def test_airterminal_cooledbeam_rb
          result = sim_test('airterminal_cooledbeam.rb')
        end
        
        # TODO: To be added in the next official release after: 2.5.0
        # def test_airterminal_fourpipebeam_osm
        #   result = sim_test('airterminal_fourpipebeam.osm')
        # end
      • No out.osw have been committed as they need to be run with an official OpenStudio version
  • Ruby test is stable: when run multiple times on the same machine, it produces the same total site kBTU.
    Please paste the heatmap png generated after running the following commands:

    • I ensured that I assign systems/loads/etc in a repeatable manner (eg: if I assign stuff to thermalZones, I do model.getThermalZones.sort_by{|z| z.name.to_s}.each do ... so I am sure I put the same ZoneHVAC systems to the same zones regardless of their order)
    • I tested stability using process_results.py (see python process_results.py --help for usage).
  • Object has been added to autosize_hvac.rb to ensure the autosizedXXX values methods do work


Review Checklist

  • Code style (indentation, variable names, strip trailing spaces)
  • Functional code review (it has to work!)
  • Matching OSM test has been added or # TODO added to model_tests.rb
  • Appropriate out.osw have been committed
  • Test is stable
  • Object is tested in autosize_hvac as appropriate
  • The appropriate labels have been added to this PR:
    • One of: NewTest, TestFix, NewTestForExisting, Other
    • If NewTest: add PendingOSM or AddedOSM

@joseph-robertson joseph-robertson added NewTest PR type: a new test for a new model API class PendingOSM A matching OSM test has yet to be added with the next official OpenStudio Release labels Jan 7, 2025
@joseph-robertson joseph-robertson self-assigned this Jan 7, 2025
…on 1f4d455848) [x86_64-linux], Rubocop 0.81.0)
@jmarrec jmarrec force-pushed the zonehvac-evap-cooler branch 2 times, most recently from 9c7f8bf to 0aba90c Compare January 9, 2025 13:24
@jmarrec jmarrec force-pushed the zonehvac-evap-cooler branch from 0aba90c to 75f4ccc Compare January 16, 2025 10:39
Comment on lines 41 to 46
# Add ZoneHVACEvaporativeCoolerUnit
zoneHVACEvaporativeCoolerUnit = OpenStudio::Model::ZoneHVACEvaporativeCoolerUnit.new(model)
direct_evap = zoneHVACEvaporativeCoolerUnit.firstEvaporativeCooler
indirect_evap = OpenStudio::Model::EvaporativeCoolerIndirectResearchSpecial.new(model)
zoneHVACEvaporativeCoolerUnit.setSecondEvaporativeCooler(indirect_evap)
zoneHVACEvaporativeCoolerUnit.addToThermalZone(z)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should exercise the other setters for demonstration purposes

model_tests.rb Outdated
Comment on lines 2154 to 2156
# def test_zone_hvac_evaporative_cooler_py
# result = sim_test('zone_hvac_evaporative_cooler.py')
# end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: once happy with he ruby test, the python one needs to be added now in this PR

# result = sim_test('zone_hvac_evaporative_cooler.py')
# end

# def test_zone_hvac_evaporative_cooler_osm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MISSING the # TODO: To be added in the next official release after: 3.9.0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@jmarrec
Copy link
Contributor

jmarrec commented Jan 16, 2025

Also needs to be added to autosize_hvac test since the Design Supply Air Flow Rate is autosizable

@jmarrec
Copy link
Contributor

jmarrec commented Jan 16, 2025

   **   ~~~   ** For explicit details on each unused construction, use Output:Diagnostics,DisplayExtraWarnings;
   ** Severe  ** Missing temperature setpoint for Evap Cooler unit EVAPORATIVE COOLER DIRECT RESEARCH SPECIAL 1
   **   ~~~   **  use a Setpoint Manager to establish a setpoint at the unit control node.
   ** Severe  ** Missing temperature setpoint for Evap Cooler unit EVAPORATIVE COOLER DIRECT RESEARCH SPECIAL 1
   **   ~~~   **  use a Setpoint Manager to establish a setpoint at the unit control node.

@jmarrec jmarrec marked this pull request as ready for review January 16, 2025 15:26
Comment on lines +1218 to +1222
when 44
zoneHVACEvaporativeCoolerUnit = OpenStudio::Model::ZoneHVACEvaporativeCoolerUnit.new(model)
zoneHVACEvaporativeCoolerUnit.autosizeDesignSupplyAirFlowRate
zoneHVACEvaporativeCoolerUnit.addToThermalZone(zn)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to the autosize_hvac! Which told me the method was not implemented correctly so did NREL/OpenStudio@c969110

# result = sim_test('zone_hvac_evaporative_cooler.py')
# end

# def test_zone_hvac_evaporative_cooler_osm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines +8 to +14
# make a 8 stories, 100m X 50m, 8 zone building
model.add_geometry({ 'length' => 100,
'width' => 50,
'num_floors' => 8,
'floor_to_floor_height' => 4,
'plenum_height' => 0,
'perimeter_zone_depth' => 0 })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I found the node connections to be broken, I'm using 8 zones...

Comment on lines +34 to +93
def make_zone_hvac_cooler(z, direct_is_first: false, add_secondary: true, fan_placement: 'BlowThrough')
model = z.model
indirect_evap = nil
direct_evap = nil
if direct_is_first
# There is a default ctor
zoneHVACEvaporativeCoolerUnit = OpenStudio::Model::ZoneHVACEvaporativeCoolerUnit.new(model)
direct_evap = zoneHVACEvaporativeCoolerUnit.firstEvaporativeCooler
supplyAirFan = zoneHVACEvaporativeCoolerUnit.supplyAirFan

fan_system = OpenStudio::Model::FanSystemModel.new(model)
zoneHVACEvaporativeCoolerUnit.setSupplyAirFan(fan_system)
supplyAirFan.remove
supplyAirFan = fan_system
# An optional Second EvaporativeCooler
if add_secondary
indirect_evap = OpenStudio::Model::EvaporativeCoolerIndirectResearchSpecial.new(model)
zoneHVACEvaporativeCoolerUnit.setSecondEvaporativeCooler(indirect_evap)
end
else
# And an explicit Ctor:
# ZoneHVACEvaporativeCoolerUnit(const Model& model, Schedule& availabilitySchedule, HVACComponent& supplyAirFan, HVACComponent& firstEvaporativeCooler);
supplyAirFan = OpenStudio::Model::FanSystemModel.new(model)

indirect_evap = OpenStudio::Model::EvaporativeCoolerIndirectResearchSpecial.new(model)
zoneHVACEvaporativeCoolerUnit = OpenStudio::Model::ZoneHVACEvaporativeCoolerUnit.new(
model, model.alwaysOnDiscreteSchedule, supplyAirFan, indirect_evap
)
# An optional Second EvaporativeCooler
if add_secondary
direct_evap = OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial.new(model, model.alwaysOnDiscreteSchedule)
zoneHVACEvaporativeCoolerUnit.setSecondEvaporativeCooler(direct_evap)
end
end
indirect_evap&.setName("#{z.nameString} Indirect Evaporative Cooler")
direct_evap&.setName("#{z.nameString} Direct Evaporative Cooler")
supplyAirFan.setName("#{z.nameString} Supply Fan")
zoneHVACEvaporativeCoolerUnit.setName("#{z.nameString} Evap Unit")
# zoneHVACEvaporativeCoolerUnit.resetSecondEvaporativeCooler
#
# Redoing what the default constructor does for demonstration purposes
# zoneHVACEvaporativeCoolerUnit.setDesignSupplyAirFlowRate(1.0)
zoneHVACEvaporativeCoolerUnit.autosizeDesignSupplyAirFlowRate
zoneHVACEvaporativeCoolerUnit.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
zoneHVACEvaporativeCoolerUnit.setSupplyAirFan(zoneHVACEvaporativeCoolerUnit.supplyAirFan)
zoneHVACEvaporativeCoolerUnit.setFanPlacement(fan_placement)
zoneHVACEvaporativeCoolerUnit.setCoolerUnitControlMethod('ZoneCoolingLoadVariableSpeedFan')
zoneHVACEvaporativeCoolerUnit.setThrottlingRangeTemperatureDifference(1.1)
zoneHVACEvaporativeCoolerUnit.setCoolingLoadControlThresholdHeatTransferRate(100.0)
zoneHVACEvaporativeCoolerUnit.setShutOffRelativeHumidity(100.0)

# Add it to a ThermalZone
zoneHVACEvaporativeCoolerUnit.addToThermalZone(z)

# Rename nodes for clarity
z.zoneAirNode.setName("#{z.nameString} Zone Air Node")
# z.returnAirModelObjects.modelObjects[0].setName("#{z.nameString} Zone Return Air Node")
z.inletPortList.modelObjects[0].setName("#{z.nameString} Zone Air Inlet Node")
z.exhaustPortList.modelObjects[0].setName("#{z.nameString} Zone Air Exhaust Node")
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helper to create a specific configuration

Comment on lines +95 to +121
# In order to produce more consistent results between different runs,
# we sort the zones by names
zones = model.getThermalZones.sort_by { |z| z.name.to_s }

configs = [
{ zone_name: 'DirectFirst', direct_is_first: true, add_secondary: true },

# Mimic SMStore8 from StripMallZoneEvapCoolerAutosized.idf
# https://github.com/NREL/EnergyPlus/blob/31e3c33467c5873371bf48b12a7318215971c315/testfiles/StripMallZoneEvapCoolerAutosized.idf#L4767-L4784
{ zone_name: 'IndirectFirst', direct_is_first: false, add_secondary: true },

{ zone_name: 'DirectOnly', direct_is_first: true, add_secondary: false },

{ zone_name: 'IndirectOnly', direct_is_first: false, add_secondary: false }
]
fan_placements = ['BlowThrough', 'DrawThrough']
raise 'Mismatch' unless configs.size * fan_placements.size == zones.size

configs.product(fan_placements).zip(zones).each do |(config, fan_placement), z|
z.setName("#{config[:zone_name]} #{fan_placement} Zn")
make_zone_hvac_cooler(
z,
direct_is_first: config[:direct_is_first],
add_secondary: config[:add_secondary],
fan_placement: fan_placement
)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing 8 combinations: for each of these four, I test BlowThrough + DrawThrough

  • DirectOnly
  • IndirectOnly
  • Direct then Indirect
  • Indirect then Direct

@jmarrec
Copy link
Contributor

jmarrec commented Jan 16, 2025

Geez, eplusout.err still shows a node error

   ** Severe  ** Node Connection Error, Node="DIRECTFIRST DRAWTHROUGH ZN EVAP UNIT FIRST EVAPORATIVE COOLER - SECOND EVAPORATIVE COOLER NODE", Inlet node did not find an appropriate matching "outlet" node.
   **   ~~~   ** If this is an outdoor air inlet node, it must be listed in an OutdoorAir:Node or OutdoorAir:NodeList object.
   **   ~~~   ** Reference Object=EvaporativeCooler:Indirect:ResearchSpecial, Name=DIRECTFIRST DRAWTHROUGH ZN INDIRECT EVAPORATIVE COOLER
   ** Severe  ** Node Connection Error, Node="INDIRECTFIRST DRAWTHROUGH ZN EVAP UNIT FIRST EVAPORATIVE COOLER - SECOND EVAPORATIVE COOLER NODE", Inlet node did not find an appropriate matching "outlet" node.
   **   ~~~   ** If this is an outdoor air inlet node, it must be listed in an OutdoorAir:Node or OutdoorAir:NodeList object.
   **   ~~~   ** Reference Object=EvaporativeCooler:Direct:ResearchSpecial, Name=INDIRECTFIRST DRAWTHROUGH ZN DIRECT EVAPORATIVE COOLER

jmarrec added a commit to NREL/OpenStudio that referenced this pull request Jan 16, 2025
@jmarrec
Copy link
Contributor

jmarrec commented Jan 16, 2025

Geez, eplusout.err still shows a node error

   ** Severe  ** Node Connection Error, Node="DIRECTFIRST DRAWTHROUGH ZN EVAP UNIT FIRST EVAPORATIVE COOLER - SECOND EVAPORATIVE COOLER NODE", Inlet node did not find an appropriate matching "outlet" node.
   **   ~~~   ** If this is an outdoor air inlet node, it must be listed in an OutdoorAir:Node or OutdoorAir:NodeList object.
   **   ~~~   ** Reference Object=EvaporativeCooler:Indirect:ResearchSpecial, Name=DIRECTFIRST DRAWTHROUGH ZN INDIRECT EVAPORATIVE COOLER
   ** Severe  ** Node Connection Error, Node="INDIRECTFIRST DRAWTHROUGH ZN EVAP UNIT FIRST EVAPORATIVE COOLER - SECOND EVAPORATIVE COOLER NODE", Inlet node did not find an appropriate matching "outlet" node.
   **   ~~~   ** If this is an outdoor air inlet node, it must be listed in an OutdoorAir:Node or OutdoorAir:NodeList object.
   **   ~~~   ** Reference Object=EvaporativeCooler:Direct:ResearchSpecial, Name=INDIRECTFIRST DRAWTHROUGH ZN DIRECT EVAPORATIVE COOLER

Ok fixed via NREL/OpenStudio@73365b1

@jmarrec
Copy link
Contributor

jmarrec commented Jan 16, 2025

Getting a warning in ONE of the cases, but AFAIK I can't fix that anyways,so I'm going to ignore it (FYI @joseph-robertson )

   ** Severe  ** Missing temperature setpoint for Evap Cooler unit DIRECTFIRST BLOWTHROUGH ZN DIRECT EVAPORATIVE COOLER
   **   ~~~   **  use a Setpoint Manager to establish a setpoint at the unit control node.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is that python version!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NewTest PR type: a new test for a new model API class PendingOSM A matching OSM test has yet to be added with the next official OpenStudio Release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants