urbanopt-cli 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/release.yml +24 -0
- data/.github/workflows/nightly_ci_build.yml +39 -29
- data/.gitignore +1 -0
- data/CHANGELOG.md +17 -0
- data/CMakeLists.txt +7 -7
- data/FindOpenStudioSDK.cmake +8 -8
- data/LICENSE.md +8 -35
- data/README.md +25 -10
- data/example_files/Gemfile +9 -9
- data/example_files/example_project_combined.json +6 -2
- data/example_files/example_project_with_ghe.json +859 -0
- data/example_files/mappers/Baseline.rb +39 -415
- data/example_files/mappers/ChilledWaterStorage.rb +1 -1
- data/example_files/mappers/CreateBar.rb +1 -1
- data/example_files/mappers/EvCharging.rb +1 -1
- data/example_files/mappers/FlexibleHotWater.rb +1 -1
- data/example_files/mappers/Floorspace.rb +1 -1
- data/example_files/mappers/HighEfficiency.rb +1 -1
- data/example_files/mappers/HighEfficiencyCreateBar.rb +1 -1
- data/example_files/mappers/HighEfficiencyFloorspace.rb +1 -1
- data/example_files/mappers/PeakHoursMelsShedding.rb +1 -1
- data/example_files/mappers/PeakHoursThermostatAdjust.rb +1 -1
- data/example_files/mappers/ThermalStorage.rb +1 -1
- data/example_files/mappers/base_workflow.osw +11 -4
- data/example_files/mappers/residential/template/util.rb +138 -0
- data/example_files/mappers/residential/util.rb +276 -0
- data/example_files/measures/BuildResidentialModel/measure.rb +118 -230
- data/example_files/measures/BuildResidentialModel/measure.xml +344 -233
- data/example_files/measures/BuildResidentialModel/resources/geometry.rb +7 -2
- data/example_files/measures/BuildResidentialModel/resources/unit_conversions.rb +5 -0
- data/example_files/measures/BuildResidentialModel/resources/util.rb +5 -0
- data/example_files/measures/BuildResidentialModel/tests/test_build_residential_model.rb +344 -0
- data/example_files/measures/BuildResidentialModel/tests/xml_building/17/feature1.xml +2112 -0
- data/example_files/measures/BuildResidentialModel/tests/xml_building/17/feature2.xml +2112 -0
- data/example_files/osm_building/7.osm +0 -2
- data/example_files/osm_building/8.osm +0 -2
- data/example_files/osm_building/9.osm +0 -2
- data/example_files/python_deps/dependencies.json +4 -3
- data/example_files/resources/hpxml-measures/.gitattributes +3 -0
- data/example_files/resources/hpxml-measures/.github/pull_request_template.md +2 -2
- data/example_files/resources/hpxml-measures/.github/workflows/add_to_project.yml +17 -0
- data/example_files/resources/hpxml-measures/.github/workflows/config.yml +37 -8
- data/example_files/resources/hpxml-measures/.gitignore +1 -0
- data/example_files/resources/hpxml-measures/.readthedocs.yml +6 -2
- data/example_files/resources/hpxml-measures/BuildResidentialHPXML/README.md +5596 -0
- data/example_files/resources/hpxml-measures/BuildResidentialHPXML/README.md.erb +41 -0
- data/example_files/resources/hpxml-measures/BuildResidentialHPXML/measure.rb +1324 -1035
- data/example_files/resources/hpxml-measures/BuildResidentialHPXML/measure.xml +325 -236
- data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/geometry.rb +119 -152
- data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{build_residential_hpxml_test.rb → test_build_residential_hpxml.rb} +225 -107
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/README.md +96 -0
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/README.md.erb +41 -0
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/measure.rb +73 -31
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/measure.xml +60 -40
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/resources/README.md +48 -23
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/resources/constants.rb +5 -0
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/resources/schedules.rb +6 -12
- data/example_files/resources/hpxml-measures/BuildResidentialScheduleFile/tests/{build_residential_schedule_file_test.rb → test_build_residential_schedule_file.rb} +162 -35
- data/example_files/resources/hpxml-measures/Changelog.md +57 -1
- data/example_files/resources/hpxml-measures/Gemfile +1 -1
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/README.md +83 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/README.md.erb +41 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/measure.rb +1081 -878
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/measure.xml +258 -204
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/airflow.rb +205 -178
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/battery.rb +43 -18
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/constants.rb +37 -112
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/constructions.rb +34 -73
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/data/Xing_okstate_0664D_13659_Table_A-3.csv +4165 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/data/unavailable_periods.csv +2 -2
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/energyplus.rb +5 -1
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/generator.rb +13 -7
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/geometry.rb +95 -42
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hotwater_appliances.rb +132 -108
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hpxml.rb +1695 -1267
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hpxml_defaults.rb +668 -589
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hpxml_schema/HPXML.xsd +304 -553
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml +197 -112
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hvac.rb +1140 -1745
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hvac_sizing.rb +412 -325
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/lighting.rb +56 -48
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/location.rb +49 -38
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/materials.rb +5 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/meta_measure.rb +17 -1
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/minitest_helper.rb +5 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/misc_loads.rb +94 -78
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/output.rb +60 -2
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/psychrometrics.rb +6 -1
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/pv.rb +11 -5
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedule_files/occupancy-non-stochastic.csv +1 -1
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic-30-mins.csv +52561 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_2.csv +8761 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_3.csv +8761 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_4.csv +8761 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_5.csv +8761 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_6.csv +8761 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedules.rb +129 -137
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/simcontrols.rb +12 -21
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/unit_conversions.rb +5 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/util.rb +7 -2
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/utility_bills.rb +6 -1
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/version.rb +7 -2
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/waterheater.rb +179 -144
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/weather.rb +129 -71
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/xmlhelper.rb +5 -0
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/xmlvalidator.rb +23 -6
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_airflow.rb +129 -118
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_battery.rb +25 -20
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_defaults.rb +2282 -2239
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_enclosure.rb +395 -204
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_generator.rb +12 -7
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_hotwater_appliance.rb +56 -51
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_hvac.rb +369 -230
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_hvac_sizing.rb +371 -191
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_lighting.rb +27 -20
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_location.rb +55 -5
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_miscloads.rb +35 -30
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_pv.rb +13 -8
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_schedules.rb +107 -93
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_simcontrols.rb +11 -6
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_validation.rb +757 -573
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_water_heater.rb +77 -72
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_weather.rb +36 -6
- data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/util.rb +5 -0
- data/example_files/resources/hpxml-measures/README.md +2 -0
- data/example_files/resources/hpxml-measures/Rakefile +10 -3
- data/example_files/resources/hpxml-measures/ReportSimulationOutput/README.md +787 -0
- data/example_files/resources/hpxml-measures/ReportSimulationOutput/README.md.erb +41 -0
- data/example_files/resources/hpxml-measures/ReportSimulationOutput/measure.rb +730 -418
- data/example_files/resources/hpxml-measures/ReportSimulationOutput/measure.xml +1215 -9
- data/example_files/resources/hpxml-measures/ReportSimulationOutput/tests/{output_report_test.rb → test_report_sim_output.rb} +130 -299
- data/example_files/resources/hpxml-measures/ReportUtilityBills/README.md +87 -0
- data/example_files/resources/hpxml-measures/ReportUtilityBills/README.md.erb +41 -0
- data/example_files/resources/hpxml-measures/ReportUtilityBills/measure.rb +261 -89
- data/example_files/resources/hpxml-measures/ReportUtilityBills/measure.xml +179 -94
- data/example_files/resources/hpxml-measures/ReportUtilityBills/resources/simple_rates/Average_retail_price_of_electricity.csv +68 -68
- data/example_files/resources/hpxml-measures/ReportUtilityBills/resources/simple_rates/NG_PRI_SUM_A_EPG0_PRS_DMCF_A.csv +3 -2
- data/example_files/resources/hpxml-measures/ReportUtilityBills/resources/simple_rates/PET_PRI_WFR_A_EPD2F_PRS_DPGAL_W.csv +713 -685
- data/example_files/resources/hpxml-measures/ReportUtilityBills/resources/simple_rates/PET_PRI_WFR_A_EPLLPA_PRS_DPGAL_W.csv +716 -688
- data/example_files/resources/hpxml-measures/ReportUtilityBills/resources/simple_rates/README.md +5 -2
- data/example_files/resources/hpxml-measures/ReportUtilityBills/resources/util.rb +18 -9
- data/example_files/resources/hpxml-measures/ReportUtilityBills/tests/test_report_utility_bills.rb +1308 -0
- data/example_files/resources/hpxml-measures/docs/requirements.txt +5 -0
- data/example_files/resources/hpxml-measures/docs/source/conf.py +1 -2
- data/example_files/resources/hpxml-measures/docs/source/intro.rst +3 -20
- data/example_files/resources/hpxml-measures/docs/source/usage_instructions.rst +1 -1
- data/example_files/resources/hpxml-measures/docs/source/workflow_inputs.rst +917 -564
- data/example_files/resources/hpxml-measures/docs/source/workflow_outputs.rst +79 -42
- data/example_files/resources/hpxml-measures/tasks.rb +2305 -2055
- data/example_files/resources/hpxml-measures/workflow/hpxml_inputs.json +270 -587
- data/example_files/resources/hpxml-measures/workflow/real_homes/house001.xml +559 -557
- data/example_files/resources/hpxml-measures/workflow/real_homes/house002.xml +522 -520
- data/example_files/resources/hpxml-measures/workflow/real_homes/house003.xml +534 -532
- data/example_files/resources/hpxml-measures/workflow/real_homes/house004.xml +547 -545
- data/example_files/resources/hpxml-measures/workflow/real_homes/house005.xml +546 -544
- data/example_files/resources/hpxml-measures/workflow/real_homes/house006.xml +603 -623
- data/example_files/resources/hpxml-measures/workflow/real_homes/house007.xml +613 -633
- data/example_files/resources/hpxml-measures/workflow/real_homes/house008.xml +699 -721
- data/example_files/resources/hpxml-measures/workflow/real_homes/house009.xml +662 -661
- data/example_files/resources/hpxml-measures/workflow/real_homes/house010.xml +657 -677
- data/example_files/resources/hpxml-measures/workflow/real_homes/house011.xml +470 -467
- data/example_files/resources/hpxml-measures/workflow/real_homes/house012.xml +441 -438
- data/example_files/resources/hpxml-measures/workflow/real_homes/house013.xml +468 -465
- data/example_files/resources/hpxml-measures/workflow/real_homes/house014.xml +469 -466
- data/example_files/resources/hpxml-measures/workflow/real_homes/house015.xml +468 -465
- data/example_files/resources/hpxml-measures/workflow/real_homes/house016.xml +717 -714
- data/example_files/resources/hpxml-measures/workflow/real_homes/house017.xml +647 -645
- data/example_files/resources/hpxml-measures/workflow/real_homes/house018.xml +569 -566
- data/example_files/resources/hpxml-measures/workflow/real_homes/house019.xml +602 -599
- data/example_files/resources/hpxml-measures/workflow/real_homes/house020.xml +630 -627
- data/example_files/resources/hpxml-measures/workflow/real_homes/house021.xml +776 -774
- data/example_files/resources/hpxml-measures/workflow/real_homes/house022.xml +670 -667
- data/example_files/resources/hpxml-measures/workflow/real_homes/house023.xml +632 -629
- data/example_files/resources/hpxml-measures/workflow/real_homes/house024.xml +731 -729
- data/example_files/resources/hpxml-measures/workflow/real_homes/house025.xml +672 -669
- data/example_files/resources/hpxml-measures/workflow/real_homes/house026.xml +667 -644
- data/example_files/resources/hpxml-measures/workflow/real_homes/house027.xml +646 -644
- data/example_files/resources/hpxml-measures/workflow/real_homes/house028.xml +690 -688
- data/example_files/resources/hpxml-measures/workflow/real_homes/house029.xml +701 -699
- data/example_files/resources/hpxml-measures/workflow/real_homes/house030.xml +637 -615
- data/example_files/resources/hpxml-measures/workflow/real_homes/house031.xml +690 -688
- data/example_files/resources/hpxml-measures/workflow/real_homes/house032.xml +557 -554
- data/example_files/resources/hpxml-measures/workflow/real_homes/house033.xml +534 -531
- data/example_files/resources/hpxml-measures/workflow/real_homes/house034.xml +636 -635
- data/example_files/resources/hpxml-measures/workflow/real_homes/house035.xml +616 -613
- data/example_files/resources/hpxml-measures/workflow/real_homes/house036.xml +601 -598
- data/example_files/resources/hpxml-measures/workflow/real_homes/house037.xml +581 -578
- data/example_files/resources/hpxml-measures/workflow/real_homes/house038.xml +624 -622
- data/example_files/resources/hpxml-measures/workflow/real_homes/house039.xml +584 -582
- data/example_files/resources/hpxml-measures/workflow/real_homes/house040.xml +631 -629
- data/example_files/resources/hpxml-measures/workflow/real_homes/house041.xml +922 -921
- data/example_files/resources/hpxml-measures/workflow/real_homes/house042.xml +855 -853
- data/example_files/resources/hpxml-measures/workflow/real_homes/house043.xml +739 -737
- data/example_files/resources/hpxml-measures/workflow/real_homes/house044.xml +798 -796
- data/example_files/resources/hpxml-measures/workflow/real_homes/house045.xml +696 -694
- data/example_files/resources/hpxml-measures/workflow/real_homes/house046.xml +487 -483
- data/example_files/resources/hpxml-measures/workflow/real_homes/house047.xml +443 -440
- data/example_files/resources/hpxml-measures/workflow/real_homes/house048.xml +688 -686
- data/example_files/resources/hpxml-measures/workflow/real_homes/house049.xml +722 -720
- data/example_files/resources/hpxml-measures/workflow/real_homes/house050.xml +619 -617
- data/example_files/resources/hpxml-measures/workflow/run_simulation.rb +13 -20
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-coal.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-dehumidifier-ief-portable.xml +11 -12
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-dehumidifier-ief-whole-home.xml +11 -12
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-dehumidifier-multiple.xml +12 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-dehumidifier.xml +11 -12
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-gas.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-modified.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-none.xml +4 -4
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-oil.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-propane.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-wood.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-cathedral.xml +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-conditioned.xml +10 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-flat.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-radiant-barrier.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-unvented-insulated-roof.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-vented.xml +8 -8
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-battery-scheduled.xml +571 -569
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-battery.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-adjacent-to-multifamily-buffer-space.xml → base-bldgtype-mf-unit-adjacent-to-multifamily-buffer-space.xml} +5 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-adjacent-to-multiple.xml → base-bldgtype-mf-unit-adjacent-to-multiple.xml} +17 -17
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-adjacent-to-non-freezing-space.xml → base-bldgtype-mf-unit-adjacent-to-non-freezing-space.xml} +5 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-adjacent-to-other-heated-space.xml → base-bldgtype-mf-unit-adjacent-to-other-heated-space.xml} +5 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml → base-bldgtype-mf-unit-adjacent-to-other-housing-unit.xml} +5 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-infil-compartmentalization-test.xml → base-bldgtype-mf-unit-infil-compartmentalization-test.xml} +461 -461
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-residents-1.xml → base-bldgtype-mf-unit-residents-1.xml} +453 -453
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-chiller-baseboard.xml → base-bldgtype-mf-unit-shared-boiler-chiller-baseboard.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-chiller-fan-coil-ducted.xml → base-bldgtype-mf-unit-shared-boiler-chiller-fan-coil-ducted.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-chiller-fan-coil.xml → base-bldgtype-mf-unit-shared-boiler-chiller-fan-coil.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-chiller-water-loop-heat-pump.xml → base-bldgtype-mf-unit-shared-boiler-chiller-water-loop-heat-pump.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-cooling-tower-water-loop-heat-pump.xml → base-bldgtype-mf-unit-shared-boiler-cooling-tower-water-loop-heat-pump.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-only-baseboard.xml → base-bldgtype-mf-unit-shared-boiler-only-baseboard.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-only-fan-coil-ducted.xml → base-bldgtype-mf-unit-shared-boiler-only-fan-coil-ducted.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-only-fan-coil-eae.xml → base-bldgtype-mf-unit-shared-boiler-only-fan-coil-eae.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-mf-unit-shared-boiler-only-fan-coil-fireplace-elec.xml +433 -0
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-only-fan-coil.xml → base-bldgtype-mf-unit-shared-boiler-only-fan-coil.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-boiler-only-water-loop-heat-pump.xml → base-bldgtype-mf-unit-shared-boiler-only-water-loop-heat-pump.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-chiller-only-baseboard.xml → base-bldgtype-mf-unit-shared-chiller-only-baseboard.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-chiller-only-fan-coil-ducted.xml → base-bldgtype-mf-unit-shared-chiller-only-fan-coil-ducted.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-chiller-only-fan-coil.xml → base-bldgtype-mf-unit-shared-chiller-only-fan-coil.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-chiller-only-water-loop-heat-pump.xml → base-bldgtype-mf-unit-shared-chiller-only-water-loop-heat-pump.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-cooling-tower-only-water-loop-heat-pump.xml → base-bldgtype-mf-unit-shared-cooling-tower-only-water-loop-heat-pump.xml} +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-generator.xml → base-bldgtype-mf-unit-shared-generator.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-ground-loop-ground-to-air-heat-pump.xml → base-bldgtype-mf-unit-shared-ground-loop-ground-to-air-heat-pump.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-laundry-room-multiple-water-heaters.xml → base-bldgtype-mf-unit-shared-laundry-room-multiple-water-heaters.xml} +480 -480
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-laundry-room.xml → base-bldgtype-mf-unit-shared-laundry-room.xml} +10 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-mechvent-multiple.xml → base-bldgtype-mf-unit-shared-mechvent-multiple.xml} +15 -15
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-mechvent-preconditioning.xml → base-bldgtype-mf-unit-shared-mechvent-preconditioning.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-mechvent.xml → base-bldgtype-mf-unit-shared-mechvent.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-pv.xml → base-bldgtype-mf-unit-shared-pv.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-water-heater-recirc.xml → base-bldgtype-mf-unit-shared-water-heater-recirc.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily-shared-water-heater.xml → base-bldgtype-mf-unit-shared-water-heater.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-multifamily.xml → base-bldgtype-mf-unit.xml} +13 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-attached-2stories.xml → base-bldgtype-sfa-unit-2stories.xml} +610 -610
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-attached-atticroof-cathedral.xml → base-bldgtype-sfa-unit-atticroof-cathedral.xml} +558 -558
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-attached-infil-compartmentalization-test.xml → base-bldgtype-sfa-unit-infil-compartmentalization-test.xml} +610 -610
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-bldgtype-attached.xml → base-bldgtype-sfa-unit.xml} +610 -610
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-combi-tankless-outside.xml +8 -8
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-combi-tankless.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-2-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-gshp.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-hpwh.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-tankless.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-var-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-dwhr.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-detailed-setpoints.xml +507 -505
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-dse.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-outside.xml +8 -8
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-standbyloss.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-with-solar-fraction.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-electric.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-gas.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-hpwh.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-indirect.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-low-flow-fixtures.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-multiple.xml +14 -14
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-none.xml +5 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-demand.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-manual.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-nocontrol.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-temperature.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-timer.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-direct-evacuated-tube.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-direct-flat-plate.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-direct-ics.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-fraction.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-indirect-flat-plate.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-thermosyphon-flat-plate.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-coal.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-detailed-setpoints.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-elec-uef.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-gas-outside.xml +8 -8
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-gas-uef-fhr.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-gas-uef.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-gas.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-detailed-schedules.xml +13 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-operating-mode-heat-pump-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-outside.xml +8 -8
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-uef.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-with-solar-fraction.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-with-solar.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-model-type-stratified-detailed-occupancy-stochastic.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-model-type-stratified.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-oil.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-wood.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-detailed-setpoints.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-electric-outside.xml +8 -8
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-electric-uef.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-electric.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas-uef.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas-with-solar-fraction.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas-with-solar.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-propane.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-2stories-garage.xml +13 -14
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-2stories.xml +11 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-1.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-2.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-4.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-5.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-ceilingtypes.xml +576 -576
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-floortypes.xml +519 -519
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-garage.xml +4 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-ach-house-pressure.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-cfm-house-pressure.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-cfm50.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-ela.xml +548 -548
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-flue.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-natural-ach.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-natural-cfm.xml +551 -551
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-orientations.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-overhangs.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-rooftypes.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-skylights-physical-properties.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-skylights-shading.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-skylights-storms.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-skylights.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-split-level.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-thermal-mass.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-walltypes.xml +19 -19
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-windows-natural-ventilation-availability.xml +555 -553
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-windows-none.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-windows-physical-properties.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-windows-shading-seasons.xml +560 -558
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-windows-shading.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-windows-storms.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-ambient.xml +10 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-basement-garage.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-belly-wing-no-skirt.xml +496 -0
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-belly-wing-skirt.xml +496 -0
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-complex.xml +18 -18
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-schedules-simple-power-outage-natvent-unavailable.xml → base-foundation-conditioned-basement-slab-insulation-full.xml} +552 -564
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-conditioned-basement-slab-insulation.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-conditioned-basement-wall-insulation.xml +555 -555
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-conditioned-crawlspace.xml +8 -8
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-multiple.xml +5 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-slab.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement-above-grade.xml +4 -4
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement-assembly-r.xml +4 -4
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement-wall-insulation.xml +4 -4
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement.xml +4 -4
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unvented-crawlspace.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-vented-crawlspace-above-grade.xml +558 -0
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-vented-crawlspace.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-walkout-basement.xml +15 -15
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-1-speed-cooling-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-1-speed-heating-capacity-17f.xml +552 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-1-speed-heating-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-1-speed-lockout-temperatures.xml +562 -562
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-1-speed-seer2-hspf2.xml +557 -557
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-1-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-2-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-var-speed-backup-boiler-hvac-seasons.xml +586 -586
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-var-speed-backup-boiler-switchover-temperature.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-var-speed-backup-boiler.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-var-speed-backup-furnace.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-air-to-air-heat-pump-var-speed-sizing-methodology-acca.xml → base-hvac-air-to-air-heat-pump-var-speed-detailed-performance-other-temperatures.xml} +89 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-air-to-air-heat-pump-var-speed-sizing-methodology-hers.xml → base-hvac-air-to-air-heat-pump-var-speed-detailed-performance.xml} +107 -13
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-var-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-sizing-controls.xml +567 -565
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-coal-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-elec-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-gas-central-ac-1-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-gas-only-pilot.xml +512 -512
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-gas-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-oil-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-propane-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-wood-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-only-1-speed-seer2.xml +536 -536
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-only-1-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-only-2-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-central-ac-only-var-speed.xml → base-hvac-central-ac-only-var-speed-detailed-performance.xml} +49 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-only-var-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-plus-air-to-air-heat-pump-heating.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dse.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-1-speed-lockout-temperatures.xml +559 -559
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-1-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-2-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-var-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-mini-split-heat-pump-ducted.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ducts-area-fractions.xml +11 -12
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ducts-area-multipliers.xml +558 -558
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ducts-buried.xml +554 -554
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-furnace-gas-room-ac.xml → base-hvac-ducts-defaults.xml} +28 -14
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ducts-effective-rvalue.xml +552 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ducts-leakage-cfm50.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ducts-leakage-percent.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-elec-resistance-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-evap-cooler-furnace-gas.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-evap-cooler-only-ducted.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-evap-cooler-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-fireplace-wood-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-floor-furnace-propane-only.xml +15 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-coal-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-elec-central-ac-1-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-elec-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-central-ac-2-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-central-ac-var-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-only-detailed-setpoints.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-only-pilot.xml +541 -541
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-room-ac.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-oil-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-propane-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-wood-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-x3-dse.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ground-to-air-heat-pump-cooling-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ground-to-air-heat-pump-heating-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ground-to-air-heat-pump.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-air-to-air-heat-pump-1-speed-autosized-backup.xml → base-hvac-install-quality-air-to-air-heat-pump-var-speed-detailed-performance.xml} +650 -556
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-air-to-air-heat-pump-var-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-furnace-gas-central-ac-1-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-furnace-gas-central-ac-2-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-furnace-gas-central-ac-var-speed.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-furnace-gas-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-ground-to-air-heat-pump.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-mini-split-air-conditioner-only-ducted.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-mini-split-heat-pump-ducted.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-air-conditioner-only-ducted.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-mini-split-air-conditioner-only-ducted.xml → base-hvac-mini-split-air-conditioner-only-ductless-detailed-performance.xml} +50 -49
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-air-conditioner-only-ductless.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ducted-cooling-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-mini-split-heat-pump-ducted-sizing-methodology-maxload.xml → base-hvac-mini-split-heat-pump-ducted-detailed-performance.xml} +109 -14
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ducted-heating-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ducted.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ductless-backup-baseboard.xml +524 -524
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-dual-fuel-mini-split-heat-pump-ducted-backup-hardsized.xml → base-hvac-mini-split-heat-pump-ductless-backup-furnace-ducts-defaults.xml} +560 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ductless-backup-furnace.xml +563 -563
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ductless-backup-stove.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-autosize-dual-fuel-mini-split-heat-pump-ducted.xml → base-hvac-mini-split-heat-pump-ductless-detailed-performance.xml} +108 -60
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ductless-heating-capacity-17f.xml +505 -505
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ductless.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-multiple.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-none.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ptac-with-heating-electricity.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ptac-with-heating-natural-gas.xml +504 -504
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ptac.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-pthp-heating-capacity-17f.xml +512 -512
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-pthp.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-only-33percent.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-only-ceer.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-only-detailed-setpoints.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-with-heating.xml +504 -504
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-with-reverse-cycle.xml +517 -517
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-seasons.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-setpoints-daily-schedules.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-setpoints-daily-setbacks.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-setpoints.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-fixed-heater-gas-only.xml → base-hvac-space-heater-gas-only.xml} +10 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-stove-oil-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-stove-wood-pellets-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-undersized.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-wall-furnace-elec-only.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-ceiling-fans.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-holiday.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-kwh-per-year.xml +531 -528
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-mixed.xml +536 -536
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-none-ceiling-fans.xml +515 -515
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-none.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-AMY-2012.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-baltimore-md.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-capetown-zaf.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-dallas-tx.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-duluth-mn.xml +4 -4
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-helena-mt.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-honolulu-hi.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-miami-fl.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-phoenix-az.xml +10 -11
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-portland-or.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-balanced.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-bath-kitchen-fans.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis-airflow-fraction-zero.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis-dse.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis-evap-cooler-only-ducted.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis-supplemental-fan-exhaust.xml +576 -576
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis-supplemental-fan-supply.xml +576 -576
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-erv-atre-asre.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-erv.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-exhaust-rated-flow-rate.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-exhaust.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-hrv-asre.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-hrv.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-multiple.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-supply.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-whole-house-fan.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-additional-properties.xml +21 -19
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-bills-pv-detailed-only.xml +605 -605
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-bills-pv-mixed.xml +587 -587
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-bills-pv.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-bills.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-defaults.xml +3 -3
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-emissions.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-generators-battery-scheduled.xml +587 -585
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-generators-battery.xml +584 -584
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-generators.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-ground-conductivity.xml +555 -555
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-loads-large-uncommon.xml +26 -26
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-loads-large-uncommon2.xml +26 -26
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-loads-none.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-neighbor-shading-bldgtype-multifamily.xml +508 -508
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-neighbor-shading.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-shielding-of-home.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-schedules-simple-power-outage-natvent-available.xml → base-misc-unit-multiplier.xml} +553 -564
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-usage-multiplier.xml +26 -26
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-multiple-mf-units.xml +2755 -0
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-multiple-buildings.xml → base-multiple-sfd-buildings.xml} +31 -22
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-battery-ah.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-battery-garage.xml +4 -5
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-battery-round-trip-efficiency.xml +597 -597
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-battery-scheduled.xml +599 -597
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-battery.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-generators-battery-scheduled.xml +615 -613
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-generators-battery.xml +612 -612
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-generators.xml +596 -596
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-residents-0-runperiod-1-month.xml +559 -559
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-residents-0.xml +555 -555
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-residents-1-misc-loads-large-uncommon.xml +616 -616
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-residents-1-misc-loads-large-uncommon2.xml +616 -616
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-residents-1.xml +547 -547
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-residents-5.xml +515 -515
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-all-10-mins.xml +14 -12
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-crankcase-heater-40w.xml → base-schedules-detailed-mixed-timesteps-power-outage.xml} +565 -555
- data/example_files/resources/hpxml-measures/workflow/sample_files/{base-schedules-detailed-occupancy-stochastic-vacancy-year-round.xml → base-schedules-detailed-mixed-timesteps.xml} +554 -563
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-occupancy-stochastic-10-mins.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-occupancy-stochastic-power-outage.xml +566 -564
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-occupancy-stochastic-vacancy.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-occupancy-stochastic.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-setpoints-daily-schedules.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-setpoints-daily-setbacks.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-detailed-setpoints.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-simple-power-outage.xml +619 -619
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-simple-vacancy.xml +618 -618
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-simple.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-calendar-year-custom.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-daylight-saving-custom.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-daylight-saving-disabled.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-runperiod-1-month.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-temperature-capacitance-multiplier.xml +553 -553
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-timestep-10-mins-occupancy-stochastic-10-mins.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-timestep-10-mins-occupancy-stochastic-60-mins.xml +12 -10
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-timestep-10-mins.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-timestep-30-mins.xml +552 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base.xml +9 -9
- data/example_files/resources/hpxml-measures/workflow/template-build-and-run-hpxml-with-stochastic-occupancy.osw +2 -0
- data/example_files/resources/hpxml-measures/workflow/template-run-hpxml-with-stochastic-occupancy-subset.osw +2 -0
- data/example_files/resources/hpxml-measures/workflow/template-run-hpxml-with-stochastic-occupancy.osw +2 -0
- data/example_files/resources/hpxml-measures/workflow/template-run-hpxml.osw +4 -1
- data/example_files/resources/hpxml-measures/workflow/tests/ACCA_Examples/Long_Residence.xml +385 -385
- data/example_files/resources/hpxml-measures/workflow/tests/ACCA_Examples/Vatilo_Residence.xml +378 -380
- data/example_files/resources/hpxml-measures/workflow/tests/ACCA_Examples/Victor_Residence.xml +369 -369
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L100AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L100AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L110AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L110AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L120AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L120AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L130AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L130AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L140AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L140AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L150AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L150AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L155AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L155AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L160AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L160AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L170AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L170AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L200AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L200AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L202AC.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L202AL.xml +7 -7
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L302XC.xml +7 -8
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L304XC.xml +7 -8
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L322XC.xml +6 -6
- data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L324XC.xml +6 -6
- data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_sizing.csv +363 -0
- data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_workflow_simulations1.csv +281 -0
- data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_workflow_simulations1_bills.csv +281 -0
- data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_workflow_simulations2.csv +141 -0
- data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_workflow_simulations2_bills.csv +141 -0
- data/example_files/resources/hpxml-measures/workflow/tests/compare.py +12 -6
- data/example_files/resources/hpxml-measures/workflow/tests/util.rb +1141 -0
- data/example_files/weather/USA_CO_Denver.Intl.AP.725650_TMY3.ddy +536 -0
- data/example_files/weather/USA_CO_Denver.Intl.AP.725650_TMY3.epw +8768 -0
- data/example_files/weather/USA_CO_Denver.Intl.AP.725650_TMY3.stat +554 -0
- data/example_files/weather/USA_FL_MacDill.AFB.747880_TMY3.ddy +536 -0
- data/example_files/weather/USA_FL_MacDill.AFB.747880_TMY3.epw +8768 -0
- data/example_files/weather/USA_FL_MacDill.AFB.747880_TMY3.stat +553 -0
- data/example_files/weather/USA_GA_Atlanta-Hartsfield-Jackson.Intl.AP.722190_TMY3-cache.csv +35 -0
- data/example_files/weather/USA_GA_Atlanta-Hartsfield-Jackson.Intl.AP.722190_TMY3.ddy +536 -0
- data/example_files/weather/USA_GA_Atlanta-Hartsfield-Jackson.Intl.AP.722190_TMY3.epw +8768 -0
- data/example_files/weather/USA_GA_Atlanta-Hartsfield-Jackson.Intl.AP.722190_TMY3.stat +553 -0
- data/example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3-cache.csv +35 -0
- data/example_files/xml_building/17/README.md +4 -2
- data/example_files/xml_building/17/feature.xml +2112 -0
- data/lib/uo_cli/version.rb +1 -1
- data/lib/uo_cli.rb +110 -17
- data/uo_cli.gemspec +6 -8
- metadata +130 -177
- data/Jenkinsfile +0 -10
- data/example_files/base_workflow_res.osw +0 -276
- data/example_files/resources/hpxml-measures/ReportUtilityBills/tests/utility_bills_test.rb +0 -1226
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-oil-location-miami-fl.xml +0 -551
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-propane-location-portland-or.xml +0 -551
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-cooling-only.xml +0 -544
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-heating-only.xml +0 -550
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-sizing-methodology-acca.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-sizing-methodology-hers.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-sizing-methodology-maxload-miami-fl.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-sizing-methodology-maxload.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-2-speed-sizing-methodology-acca.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-2-speed-sizing-methodology-hers.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-2-speed-sizing-methodology-maxload.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-var-speed-backup-boiler.xml +0 -569
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-var-speed-backup-furnace.xml +0 -599
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-var-speed-sizing-methodology-maxload.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-boiler-elec-only.xml +0 -506
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-boiler-gas-central-ac-1-speed.xml +0 -560
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-boiler-gas-only.xml +0 -507
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-central-ac-only-1-speed.xml +0 -536
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-central-ac-only-2-speed.xml +0 -536
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-central-ac-plus-air-to-air-heat-pump-heating.xml +0 -565
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-dual-fuel-air-to-air-heat-pump-1-speed-sizing-methodology-acca.xml +0 -553
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-dual-fuel-air-to-air-heat-pump-1-speed-sizing-methodology-hers.xml +0 -553
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-dual-fuel-air-to-air-heat-pump-1-speed-sizing-methodology-maxload.xml +0 -553
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-elec-resistance-only.xml +0 -497
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-evap-cooler-furnace-gas.xml +0 -544
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-floor-furnace-propane-only.xml +0 -500
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-furnace-elec-only.xml +0 -536
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-furnace-gas-central-ac-2-speed.xml +0 -551
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-furnace-gas-central-ac-var-speed.xml +0 -551
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-furnace-gas-only.xml +0 -536
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ground-to-air-heat-pump-cooling-only.xml +0 -546
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ground-to-air-heat-pump-heating-only.xml +0 -552
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ground-to-air-heat-pump-sizing-methodology-acca.xml +0 -554
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ground-to-air-heat-pump-sizing-methodology-hers.xml +0 -554
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ground-to-air-heat-pump-sizing-methodology-maxload.xml +0 -554
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-heat-pump-ducted-cooling-only.xml +0 -543
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-heat-pump-ducted-heating-only.xml +0 -549
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-heat-pump-ducted-sizing-methodology-acca.xml +0 -551
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-heat-pump-ducted-sizing-methodology-hers.xml +0 -551
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-heat-pump-ductless-backup-baseboard.xml +0 -519
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-heat-pump-ductless-backup-stove.xml +0 -522
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ptac-with-heating.xml +0 -503
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ptac.xml +0 -496
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-pthp-sizing-methodology-acca.xml +0 -518
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-pthp-sizing-methodology-hers.xml +0 -518
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-pthp-sizing-methodology-maxload.xml +0 -518
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-room-ac-only.xml +0 -496
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-room-ac-with-heating.xml +0 -503
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-room-ac-with-reverse-cycle-sizing-methodology-acca.xml +0 -518
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-room-ac-with-reverse-cycle-sizing-methodology-hers.xml +0 -518
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-room-ac-with-reverse-cycle-sizing-methodology-maxload.xml +0 -518
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-stove-oil-only.xml +0 -500
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-wall-furnace-elec-only.xml +0 -500
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-floor-furnace-propane-only-pilot-light.xml +0 -506
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-portable-heater-gas-only.xml +0 -501
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-undersized-allow-increased-fixed-capacities.xml +0 -556
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-bills-none.xml +0 -548
- data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-simple-vacancy-year-round.xml +0 -619
- data/example_files/resources/hpxml-measures/workflow/tests/base_results/results.csv +0 -475
- data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_bills.csv +0 -475
- data/example_files/resources/hpxml-measures/workflow/tests/hpxml_translator_test.rb +0 -1313
- data/example_files/resources/measure-info.json +0 -26
- data/example_files/resources/meta_measure.rb +0 -301
- data/example_files/xml_building/17/unit 1.xml +0 -580
- data/example_files/xml_building/17/unit 2.xml +0 -553
- data/example_files/xml_building/17/unit 3.xml +0 -553
- data/example_files/xml_building/17/unit 4.xml +0 -580
- /data/example_files/{residential → mappers/residential/template/iecc}/clothes_dryer.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/clothes_washer.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/cooling_system.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/dishwasher.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/enclosure.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/heat_pump.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/heating_system.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/mechanical_ventilation.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/refrigerator.tsv +0 -0
- /data/example_files/{residential → mappers/residential/template/iecc}/water_heater.tsv +0 -0
- /data/example_files/resources/hpxml-measures/ReportUtilityBills/tests/{JacksonElectricMemberCorp-ResidentialSeniorCitizenLowIncomeAssistance.json → Detailed Rate.json} +0 -0
@@ -1,3 +1,8 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt (tm), Copyright (c) Alliance for Sustainable Energy, LLC.
|
3
|
+
# See also https://github.com/urbanopt/urbanopt-cli/blob/develop/LICENSE.md
|
4
|
+
# *********************************************************************************
|
5
|
+
|
1
6
|
# frozen_string_literal: true
|
2
7
|
|
3
8
|
# Require all gems up front; this is much faster than multiple resource
|
@@ -63,7 +68,7 @@ class HPXMLtoOpenStudio < OpenStudio::Measure::ModelMeasure
|
|
63
68
|
|
64
69
|
arg = OpenStudio::Measure::OSArgument.makeStringArgument('building_id', false)
|
65
70
|
arg.setDisplayName('BuildingID')
|
66
|
-
arg.setDescription(
|
71
|
+
arg.setDescription("The ID of the HPXML Building. Only required if there are multiple Building elements in the HPXML file. Use 'ALL' to run all the HPXML Buildings (dwelling units) of a multifamily building in a single model.")
|
67
72
|
args << arg
|
68
73
|
|
69
74
|
return args
|
@@ -89,6 +94,7 @@ class HPXMLtoOpenStudio < OpenStudio::Measure::ModelMeasure
|
|
89
94
|
debug = runner.getBoolArgumentValue('debug', user_arguments)
|
90
95
|
skip_validation = runner.getBoolArgumentValue('skip_validation', user_arguments)
|
91
96
|
building_id = runner.getOptionalStringArgumentValue('building_id', user_arguments)
|
97
|
+
building_id = building_id.is_initialized ? building_id.get : nil
|
92
98
|
|
93
99
|
unless (Pathname.new hpxml_path).absolute?
|
94
100
|
hpxml_path = File.expand_path(hpxml_path)
|
@@ -101,12 +107,6 @@ class HPXMLtoOpenStudio < OpenStudio::Measure::ModelMeasure
|
|
101
107
|
output_dir = File.expand_path(output_dir)
|
102
108
|
end
|
103
109
|
|
104
|
-
if building_id.is_initialized
|
105
|
-
building_id = building_id.get
|
106
|
-
else
|
107
|
-
building_id = nil
|
108
|
-
end
|
109
|
-
|
110
110
|
begin
|
111
111
|
if skip_validation
|
112
112
|
schema_validator = nil
|
@@ -117,6 +117,7 @@ class HPXMLtoOpenStudio < OpenStudio::Measure::ModelMeasure
|
|
117
117
|
schematron_path = File.join(File.dirname(__FILE__), 'resources', 'hpxml_schematron', 'EPvalidator.xml')
|
118
118
|
schematron_validator = XMLValidator.get_schematron_validator(schematron_path)
|
119
119
|
end
|
120
|
+
|
120
121
|
hpxml = HPXML.new(hpxml_path: hpxml_path, schema_validator: schema_validator, schematron_validator: schematron_validator, building_id: building_id)
|
121
122
|
hpxml.errors.each do |error|
|
122
123
|
runner.registerError(error)
|
@@ -126,16 +127,91 @@ class HPXMLtoOpenStudio < OpenStudio::Measure::ModelMeasure
|
|
126
127
|
end
|
127
128
|
return false unless hpxml.errors.empty?
|
128
129
|
|
129
|
-
|
130
|
-
|
130
|
+
eri_version = hpxml.header.eri_calculation_version # Hidden feature
|
131
|
+
eri_version = 'latest' if eri_version.nil?
|
132
|
+
eri_version = Constants.ERIVersions[-1] if eri_version == 'latest'
|
133
|
+
|
134
|
+
# Process weather once upfront
|
135
|
+
epw_path = Location.get_epw_path(hpxml.buildings[0], hpxml_path)
|
136
|
+
weather = WeatherProcess.new(epw_path: epw_path, runner: runner, hpxml: hpxml)
|
137
|
+
epw_file = OpenStudio::EpwFile.new(epw_path)
|
138
|
+
hpxml.buildings.each_with_index do |hpxml_bldg, i|
|
139
|
+
next if i == 0
|
140
|
+
next if Location.get_epw_path(hpxml_bldg, hpxml_path) == epw_path
|
141
|
+
|
142
|
+
fail 'Weather station EPW filepath has different values across dwelling units.'
|
143
|
+
end
|
144
|
+
|
145
|
+
if (building_id == 'ALL') && (hpxml.buildings.size > 1)
|
146
|
+
if hpxml.buildings.map { |hpxml_bldg| hpxml_bldg.batteries.size }.sum > 0
|
147
|
+
# FUTURE: Figure out how to allow this. If we allow it, update docs and hpxml_translator_test.rb too.
|
148
|
+
# Batteries use "TrackFacilityElectricDemandStoreExcessOnSite"; to support modeling of batteries in whole
|
149
|
+
# SFA/MF building simulations, we'd need to create custom meters with electricity usage *for each unit*
|
150
|
+
# and switch to "TrackMeterDemandStoreExcessOnSite".
|
151
|
+
# https://github.com/NREL/OpenStudio-HPXML/issues/1499
|
152
|
+
fail 'Modeling batteries for whole SFA/MF buildings is not currently supported.'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Apply HPXML defaults upfront; process schedules & emissions
|
157
|
+
hpxml_sch_map = {}
|
158
|
+
check_emissions_references(hpxml.header, hpxml_path)
|
159
|
+
hpxml.buildings.each_with_index do |hpxml_bldg, i|
|
160
|
+
check_schedule_references(hpxml_bldg.header, hpxml_path)
|
161
|
+
in_schedules_csv = 'in.schedules.csv'
|
162
|
+
in_schedules_csv = "in.schedules#{i + 1}.csv" if i > 0
|
163
|
+
schedules_file = SchedulesFile.new(runner: runner,
|
164
|
+
schedules_paths: hpxml_bldg.header.schedules_filepaths,
|
165
|
+
year: Location.get_sim_calendar_year(hpxml.header.sim_calendar_year, epw_file),
|
166
|
+
unavailable_periods: hpxml.header.unavailable_periods,
|
167
|
+
output_path: File.join(output_dir, in_schedules_csv))
|
168
|
+
HPXMLDefaults.apply(runner, hpxml, hpxml_bldg, eri_version, weather, epw_file: epw_file, schedules_file: schedules_file)
|
169
|
+
hpxml_sch_map[hpxml_bldg] = schedules_file
|
170
|
+
end
|
171
|
+
validate_emissions_files(hpxml.header)
|
172
|
+
|
173
|
+
# Write updated HPXML object (w/ defaults) to file for inspection
|
174
|
+
hpxml_defaults_path = File.join(output_dir, 'in.xml')
|
175
|
+
XMLHelper.write_file(hpxml.to_doc, hpxml_defaults_path)
|
176
|
+
|
177
|
+
# Create OpenStudio model
|
178
|
+
hpxml_osm_map = {}
|
179
|
+
hpxml.buildings.each_with_index do |hpxml_bldg, i|
|
180
|
+
schedules_file = hpxml_sch_map[hpxml_bldg]
|
181
|
+
if hpxml.buildings.size > 1
|
182
|
+
# Create the model for this single unit
|
183
|
+
unit_model = OpenStudio::Model::Model.new
|
184
|
+
create_unit_model(hpxml, hpxml_bldg, runner, unit_model, epw_path, epw_file, weather, debug, schedules_file, eri_version, i + 1)
|
185
|
+
hpxml_osm_map[hpxml_bldg] = unit_model
|
186
|
+
else
|
187
|
+
create_unit_model(hpxml, hpxml_bldg, runner, model, epw_path, epw_file, weather, debug, schedules_file, eri_version, i + 1)
|
188
|
+
hpxml_osm_map[hpxml_bldg] = model
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Merge unit models into final model
|
193
|
+
if hpxml.buildings.size > 1
|
194
|
+
add_unit_model_to_model(model, hpxml_osm_map)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Output
|
198
|
+
add_unmet_hours_output(model, hpxml_osm_map)
|
199
|
+
add_loads_output(model, add_component_loads, hpxml_osm_map)
|
200
|
+
set_output_files(model)
|
201
|
+
add_additional_properties(model, hpxml, hpxml_osm_map, hpxml_path, building_id, epw_file, hpxml_defaults_path)
|
202
|
+
# Uncomment to debug EMS
|
203
|
+
# add_ems_debug_output(model)
|
131
204
|
|
132
205
|
if debug
|
206
|
+
# Write OSM file to run dir
|
207
|
+
osm_output_path = File.join(output_dir, 'in.osm')
|
208
|
+
File.write(osm_output_path, model.to_s)
|
209
|
+
runner.registerInfo("Wrote file: #{osm_output_path}")
|
210
|
+
|
211
|
+
# Copy EPW file to run dir
|
133
212
|
epw_output_path = File.join(output_dir, 'in.epw')
|
134
213
|
FileUtils.cp(epw_path, epw_output_path)
|
135
214
|
end
|
136
|
-
|
137
|
-
OSModel.create(hpxml, runner, model, hpxml_path, epw_path, weather, output_dir,
|
138
|
-
add_component_loads, building_id, debug)
|
139
215
|
rescue Exception => e
|
140
216
|
runner.registerError("#{e.message}\n#{e.backtrace.join("\n")}")
|
141
217
|
return false
|
@@ -143,19 +219,198 @@ class HPXMLtoOpenStudio < OpenStudio::Measure::ModelMeasure
|
|
143
219
|
|
144
220
|
return true
|
145
221
|
end
|
146
|
-
end
|
147
222
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
223
|
+
def add_unit_model_to_model(model, hpxml_osm_map)
|
224
|
+
unique_objects = { 'OS:ConvergenceLimits' => 'ConvergenceLimits',
|
225
|
+
'OS:Foundation:Kiva:Settings' => 'FoundationKivaSettings',
|
226
|
+
'OS:OutputControl:Files' => 'OutputControlFiles',
|
227
|
+
'OS:Output:Diagnostics' => 'OutputDiagnostics',
|
228
|
+
'OS:Output:JSON' => 'OutputJSON',
|
229
|
+
'OS:PerformancePrecisionTradeoffs' => 'PerformancePrecisionTradeoffs',
|
230
|
+
'OS:RunPeriod' => 'RunPeriod',
|
231
|
+
'OS:RunPeriodControl:DaylightSavingTime' => 'RunPeriodControlDaylightSavingTime',
|
232
|
+
'OS:ShadowCalculation' => 'ShadowCalculation',
|
233
|
+
'OS:SimulationControl' => 'SimulationControl',
|
234
|
+
'OS:Site' => 'Site',
|
235
|
+
'OS:Site:GroundTemperature:Deep' => 'SiteGroundTemperatureDeep',
|
236
|
+
'OS:Site:GroundTemperature:Shallow' => 'SiteGroundTemperatureShallow',
|
237
|
+
'OS:Site:WaterMainsTemperature' => 'SiteWaterMainsTemperature',
|
238
|
+
'OS:SurfaceConvectionAlgorithm:Inside' => 'InsideSurfaceConvectionAlgorithm',
|
239
|
+
'OS:SurfaceConvectionAlgorithm:Outside' => 'OutsideSurfaceConvectionAlgorithm',
|
240
|
+
'OS:Timestep' => 'Timestep' }
|
241
|
+
|
242
|
+
# Handle unique objects first: Grab one from the first model we find the
|
243
|
+
# object on (may not be the first unit).
|
244
|
+
unit_model_objects = []
|
245
|
+
unique_handles_to_skip = []
|
246
|
+
uuid_regex = /\{(.*?)\}/
|
247
|
+
unique_objects.each do |idd_obj, osm_class|
|
248
|
+
first_model_object_by_type = nil
|
249
|
+
hpxml_osm_map.values.each do |unit_model|
|
250
|
+
next if unit_model.getObjectsByType(idd_obj.to_IddObjectType).empty?
|
251
|
+
|
252
|
+
model_object = unit_model.send("get#{osm_class}")
|
253
|
+
|
254
|
+
if first_model_object_by_type.nil?
|
255
|
+
# Retain object for model
|
256
|
+
unit_model_objects << model_object
|
257
|
+
first_model_object_by_type = model_object
|
258
|
+
if idd_obj == 'OS:Site:WaterMainsTemperature' # Handle referenced child object too
|
259
|
+
unit_model_objects << unit_model.getObjectsByName(model_object.temperatureSchedule.get.name.to_s)[0]
|
260
|
+
end
|
261
|
+
else
|
262
|
+
# Throw error if different values between this model_object and first_model_object_by_type
|
263
|
+
if model_object.to_s.gsub(uuid_regex, '') != first_model_object_by_type.to_s.gsub(uuid_regex, '')
|
264
|
+
fail "Unique object (#{idd_obj}) has different values across dwelling units."
|
265
|
+
end
|
266
|
+
|
267
|
+
if idd_obj == 'OS:Site:WaterMainsTemperature' # Handle referenced child object too
|
268
|
+
if model_object.temperatureSchedule.get.to_s.gsub(uuid_regex, '') != first_model_object_by_type.temperatureSchedule.get.to_s.gsub(uuid_regex, '')
|
269
|
+
fail "Unique object (#{idd_obj}) has different values across dwelling units."
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
unique_handles_to_skip << model_object.handle.to_s
|
275
|
+
if idd_obj == 'OS:Site:WaterMainsTemperature' # Handle referenced child object too
|
276
|
+
unique_handles_to_skip << model_object.temperatureSchedule.get.handle.to_s
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
hpxml_osm_map.values.each_with_index do |unit_model, unit_number|
|
282
|
+
shift_geometry(unit_model, unit_number)
|
283
|
+
prefix_all_unit_model_objects(unit_model, unit_number)
|
284
|
+
|
285
|
+
# Handle remaining (non-unique) objects now
|
286
|
+
unit_model.objects.each do |obj|
|
287
|
+
next if unit_number > 0 && obj.to_Building.is_initialized
|
288
|
+
next if unique_handles_to_skip.include? obj.handle.to_s
|
153
289
|
|
154
|
-
|
155
|
-
|
156
|
-
|
290
|
+
unit_model_objects << obj
|
291
|
+
end
|
292
|
+
end
|
157
293
|
|
158
|
-
|
294
|
+
model.addObjects(unit_model_objects, true)
|
295
|
+
end
|
296
|
+
|
297
|
+
def shift_geometry(unit_model, unit_number)
|
298
|
+
# Shift units so they aren't right on top and shade each other
|
299
|
+
y_shift = 200.0 * unit_number # meters
|
300
|
+
|
301
|
+
# shift the unit so it's not right on top of the previous one
|
302
|
+
unit_model.getSpaces.sort.each do |space|
|
303
|
+
space.setYOrigin(y_shift)
|
304
|
+
end
|
305
|
+
|
306
|
+
# shift shading surfaces
|
307
|
+
m = OpenStudio::Matrix.new(4, 4, 0)
|
308
|
+
m[0, 0] = 1
|
309
|
+
m[1, 1] = 1
|
310
|
+
m[2, 2] = 1
|
311
|
+
m[3, 3] = 1
|
312
|
+
m[1, 3] = y_shift
|
313
|
+
t = OpenStudio::Transformation.new(m)
|
314
|
+
|
315
|
+
unit_model.getShadingSurfaceGroups.each do |shading_surface_group|
|
316
|
+
next if shading_surface_group.space.is_initialized # already got shifted
|
317
|
+
|
318
|
+
shading_surface_group.shadingSurfaces.each do |shading_surface|
|
319
|
+
shading_surface.setVertices(t * shading_surface.vertices)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def prefix_all_unit_model_objects(unit_model, unit_number)
|
325
|
+
# Prefix all objects with name using unit number
|
326
|
+
# FUTURE: Create objects with unique names up front so we don't have to do this
|
327
|
+
|
328
|
+
# EMS objects
|
329
|
+
ems_map = {}
|
330
|
+
|
331
|
+
unit_model.getEnergyManagementSystemSensors.each do |sensor|
|
332
|
+
ems_map[sensor.name.to_s] = make_variable_name(sensor.name, unit_number)
|
333
|
+
sensor.setKeyName(make_variable_name(sensor.keyName, unit_number)) unless sensor.keyName.empty? || sensor.keyName.downcase == 'environment'
|
334
|
+
end
|
335
|
+
|
336
|
+
unit_model.getEnergyManagementSystemActuators.each do |actuator|
|
337
|
+
ems_map[actuator.name.to_s] = make_variable_name(actuator.name, unit_number)
|
338
|
+
end
|
339
|
+
|
340
|
+
unit_model.getEnergyManagementSystemInternalVariables.each do |internal_variable|
|
341
|
+
ems_map[internal_variable.name.to_s] = make_variable_name(internal_variable.name, unit_number)
|
342
|
+
internal_variable.setInternalDataIndexKeyName(make_variable_name(internal_variable.internalDataIndexKeyName, unit_number)) unless internal_variable.internalDataIndexKeyName.empty?
|
343
|
+
end
|
344
|
+
|
345
|
+
unit_model.getEnergyManagementSystemGlobalVariables.each do |global_variable|
|
346
|
+
ems_map[global_variable.name.to_s] = make_variable_name(global_variable.name, unit_number)
|
347
|
+
end
|
348
|
+
|
349
|
+
unit_model.getEnergyManagementSystemOutputVariables.each do |output_variable|
|
350
|
+
next if output_variable.emsVariableObject.is_initialized
|
351
|
+
|
352
|
+
new_ems_variable_name = make_variable_name(output_variable.emsVariableName, unit_number)
|
353
|
+
ems_map[output_variable.emsVariableName.to_s] = new_ems_variable_name
|
354
|
+
output_variable.setEMSVariableName(new_ems_variable_name)
|
355
|
+
end
|
356
|
+
|
357
|
+
unit_model.getEnergyManagementSystemSubroutines.each do |subroutine|
|
358
|
+
ems_map[subroutine.name.to_s] = make_variable_name(subroutine.name, unit_number)
|
359
|
+
end
|
360
|
+
|
361
|
+
# variables in program lines don't get updated automatically
|
362
|
+
lhs_characters = [' ', ',', '(', ')', '+', '-', '*', '/', ';']
|
363
|
+
rhs_characters = [''] + lhs_characters
|
364
|
+
(unit_model.getEnergyManagementSystemPrograms + unit_model.getEnergyManagementSystemSubroutines).each do |program|
|
365
|
+
new_lines = []
|
366
|
+
program.lines.each do |line|
|
367
|
+
ems_map.each do |old_name, new_name|
|
368
|
+
next unless line.include?(old_name)
|
369
|
+
|
370
|
+
# old_name between at least 1 character, with the exception of '' on left and ' ' on right
|
371
|
+
lhs_characters.each do |lhs|
|
372
|
+
next unless line.include?("#{lhs}#{old_name}")
|
373
|
+
|
374
|
+
rhs_characters.each do |rhs|
|
375
|
+
next unless line.include?("#{lhs}#{old_name}#{rhs}")
|
376
|
+
next if lhs == '' && ['', ' '].include?(rhs)
|
377
|
+
|
378
|
+
line.gsub!("#{lhs}#{old_name}#{rhs}", "#{lhs}#{new_name}#{rhs}")
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
new_lines << line
|
383
|
+
end
|
384
|
+
program.setLines(new_lines)
|
385
|
+
end
|
386
|
+
|
387
|
+
# All model objects
|
388
|
+
unit_model.objects.each do |model_object|
|
389
|
+
next if model_object.name.nil?
|
390
|
+
|
391
|
+
if unit_number == 0
|
392
|
+
# OpenStudio is unhappy if these schedules are renamed
|
393
|
+
next if model_object.name.to_s == unit_model.alwaysOnContinuousSchedule.name.to_s
|
394
|
+
next if model_object.name.to_s == unit_model.alwaysOnDiscreteSchedule.name.to_s
|
395
|
+
next if model_object.name.to_s == unit_model.alwaysOffDiscreteSchedule.name.to_s
|
396
|
+
end
|
397
|
+
|
398
|
+
model_object.setName(make_variable_name(model_object.name, unit_number))
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
def make_variable_name(obj_name, unit_number)
|
403
|
+
return "unit#{unit_number + 1}_#{obj_name}".gsub(' ', '_').gsub('-', '_')
|
404
|
+
end
|
405
|
+
|
406
|
+
def create_unit_model(hpxml, hpxml_bldg, runner, model, epw_path, epw_file, weather, debug, schedules_file, eri_version, unit_num)
|
407
|
+
@hpxml_header = hpxml.header
|
408
|
+
@hpxml_bldg = hpxml_bldg
|
409
|
+
@debug = debug
|
410
|
+
@schedules_file = schedules_file
|
411
|
+
@eri_version = eri_version
|
412
|
+
|
413
|
+
@apply_ashrae140_assumptions = @hpxml_header.apply_ashrae140_assumptions # Hidden feature
|
159
414
|
@apply_ashrae140_assumptions = false if @apply_ashrae140_assumptions.nil?
|
160
415
|
|
161
416
|
# Here we turn off OS error-checking so that any invalid values provided
|
@@ -167,21 +422,14 @@ class OSModel
|
|
167
422
|
model.setStrictnessLevel('None'.to_StrictnessLevel)
|
168
423
|
|
169
424
|
# Init
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
schedules_paths: @hpxml.header.schedules_filepaths,
|
174
|
-
year: Location.get_sim_calendar_year(@hpxml.header.sim_calendar_year, epw_file),
|
175
|
-
unavailable_periods: @hpxml.header.unavailable_periods,
|
176
|
-
output_path: File.join(output_dir, 'in.schedules.csv'))
|
177
|
-
set_defaults_and_globals(runner, output_dir, epw_file, weather, @schedules_file)
|
178
|
-
validate_emissions_files()
|
179
|
-
Location.apply(model, weather, epw_file, @hpxml)
|
425
|
+
OpenStudio::Model::WeatherFile.setWeatherFile(model, epw_file)
|
426
|
+
set_defaults_and_globals()
|
427
|
+
Location.apply(model, weather, epw_file, @hpxml_header, @hpxml_bldg)
|
180
428
|
add_simulation_params(model)
|
181
429
|
|
182
430
|
# Conditioned space/zone
|
183
431
|
spaces = {}
|
184
|
-
create_or_get_space(model, spaces, HPXML::
|
432
|
+
create_or_get_space(model, spaces, HPXML::LocationConditionedSpace)
|
185
433
|
set_foundation_and_walls_top()
|
186
434
|
set_heating_and_cooling_seasons()
|
187
435
|
add_setpoints(runner, model, weather, spaces)
|
@@ -197,16 +445,16 @@ class OSModel
|
|
197
445
|
add_skylights(model, spaces)
|
198
446
|
add_conditioned_floor_area(model, spaces)
|
199
447
|
add_thermal_mass(model, spaces)
|
200
|
-
Geometry.set_zone_volumes(spaces, @
|
201
|
-
Geometry.explode_surfaces(model, @
|
448
|
+
Geometry.set_zone_volumes(spaces, @hpxml_bldg, @apply_ashrae140_assumptions)
|
449
|
+
Geometry.explode_surfaces(model, @hpxml_bldg, @walls_top)
|
202
450
|
add_num_occupants(model, runner, spaces)
|
203
451
|
|
204
452
|
# HVAC
|
205
|
-
@hvac_unavailable_periods = Schedule.get_unavailable_periods(runner, SchedulesFile::ColumnHVAC, @
|
453
|
+
@hvac_unavailable_periods = Schedule.get_unavailable_periods(runner, SchedulesFile::ColumnHVAC, @hpxml_header.unavailable_periods)
|
206
454
|
airloop_map = {} # Map of HPXML System ID -> AirLoopHVAC (or ZoneHVACFourPipeFanCoil)
|
207
455
|
add_ideal_system(model, spaces, epw_path)
|
208
|
-
add_cooling_system(model, spaces, airloop_map)
|
209
|
-
add_heating_system(runner, model, spaces, airloop_map)
|
456
|
+
add_cooling_system(model, weather, spaces, airloop_map)
|
457
|
+
add_heating_system(runner, model, weather, spaces, airloop_map)
|
210
458
|
add_heat_pump(runner, model, weather, spaces, airloop_map)
|
211
459
|
add_dehumidifiers(runner, model, spaces)
|
212
460
|
add_ceiling_fans(runner, model, weather, spaces)
|
@@ -219,8 +467,8 @@ class OSModel
|
|
219
467
|
add_mfls(runner, model, spaces)
|
220
468
|
add_lighting(runner, model, epw_file, spaces)
|
221
469
|
|
222
|
-
# Pools &
|
223
|
-
|
470
|
+
# Pools & Permanent Spas
|
471
|
+
add_pools_and_permanent_spas(runner, model, spaces)
|
224
472
|
|
225
473
|
# Other
|
226
474
|
add_cooling_season(model, weather)
|
@@ -228,34 +476,13 @@ class OSModel
|
|
228
476
|
add_photovoltaics(model)
|
229
477
|
add_generators(model)
|
230
478
|
add_batteries(runner, model, spaces)
|
231
|
-
|
232
|
-
|
233
|
-
# Output
|
234
|
-
add_unmet_hours_output(model, spaces)
|
235
|
-
add_loads_output(model, spaces, add_component_loads)
|
236
|
-
set_output_files(model)
|
237
|
-
# Uncomment to debug EMS
|
238
|
-
# add_ems_debug_output(model)
|
239
|
-
|
240
|
-
if debug
|
241
|
-
osm_output_path = File.join(output_dir, 'in.osm')
|
242
|
-
File.write(osm_output_path, model.to_s)
|
243
|
-
runner.registerInfo("Wrote file: #{osm_output_path}")
|
244
|
-
end
|
479
|
+
add_building_unit(model, unit_num)
|
245
480
|
end
|
246
481
|
|
247
|
-
|
248
|
-
|
249
|
-
def self.check_file_references(hpxml_path)
|
482
|
+
def check_emissions_references(hpxml_header, hpxml_path)
|
250
483
|
# Check/update file references
|
251
|
-
|
252
|
-
|
253
|
-
File.dirname(hpxml_path),
|
254
|
-
'Schedules')
|
255
|
-
}
|
256
|
-
|
257
|
-
@hpxml.header.emissions_scenarios.each do |scenario|
|
258
|
-
if @hpxml.header.emissions_scenarios.select { |s| s.emissions_type == scenario.emissions_type && s.name == scenario.name }.size > 1
|
484
|
+
hpxml_header.emissions_scenarios.each do |scenario|
|
485
|
+
if hpxml_header.emissions_scenarios.select { |s| s.emissions_type == scenario.emissions_type && s.name == scenario.name }.size > 1
|
259
486
|
fail "Found multiple Emissions Scenarios with the Scenario Name=#{scenario.name} and Emissions Type=#{scenario.emissions_type}."
|
260
487
|
end
|
261
488
|
next if scenario.elec_schedule_filepath.nil?
|
@@ -266,8 +493,17 @@ class OSModel
|
|
266
493
|
end
|
267
494
|
end
|
268
495
|
|
269
|
-
def
|
270
|
-
|
496
|
+
def check_schedule_references(hpxml_bldg_header, hpxml_path)
|
497
|
+
# Check/update file references
|
498
|
+
hpxml_bldg_header.schedules_filepaths = hpxml_bldg_header.schedules_filepaths.collect { |sfp|
|
499
|
+
FilePath.check_path(sfp,
|
500
|
+
File.dirname(hpxml_path),
|
501
|
+
'Schedules')
|
502
|
+
}
|
503
|
+
end
|
504
|
+
|
505
|
+
def validate_emissions_files(hpxml_header)
|
506
|
+
hpxml_header.emissions_scenarios.each do |scenario|
|
271
507
|
next if scenario.elec_schedule_filepath.nil?
|
272
508
|
|
273
509
|
data = File.readlines(scenario.elec_schedule_filepath)
|
@@ -283,76 +519,69 @@ class OSModel
|
|
283
519
|
end
|
284
520
|
end
|
285
521
|
|
286
|
-
def
|
522
|
+
def set_defaults_and_globals()
|
287
523
|
# Initialize
|
288
524
|
@remaining_heat_load_frac = 1.0
|
289
525
|
@remaining_cool_load_frac = 1.0
|
290
526
|
|
291
527
|
# Set globals
|
292
|
-
@cfa = @
|
293
|
-
@ncfl = @
|
294
|
-
@ncfl_ag = @
|
295
|
-
@nbeds = @
|
296
|
-
@default_azimuths = HPXMLDefaults.get_default_azimuths(@
|
297
|
-
|
298
|
-
# Apply
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
#
|
306
|
-
# are zero in order to prevent potential E+ errors.
|
307
|
-
HVAC.ensure_nonzero_sizing_values(@hpxml)
|
308
|
-
|
309
|
-
# Now that we've written in.xml, make adjustments for modeling purposes.
|
310
|
-
@frac_windows_operable = @hpxml.fraction_of_windows_operable()
|
311
|
-
@hpxml.collapse_enclosure_surfaces() # Speeds up simulation
|
312
|
-
@hpxml.delete_adiabatic_subsurfaces() # EnergyPlus doesn't allow this
|
528
|
+
@cfa = @hpxml_bldg.building_construction.conditioned_floor_area
|
529
|
+
@ncfl = @hpxml_bldg.building_construction.number_of_conditioned_floors
|
530
|
+
@ncfl_ag = @hpxml_bldg.building_construction.number_of_conditioned_floors_above_grade
|
531
|
+
@nbeds = @hpxml_bldg.building_construction.number_of_bedrooms
|
532
|
+
@default_azimuths = HPXMLDefaults.get_default_azimuths(@hpxml_bldg)
|
533
|
+
|
534
|
+
# Apply unit multipliers to HVAC systems and water heaters
|
535
|
+
HVAC.apply_unit_multiplier(@hpxml_bldg)
|
536
|
+
# Ensure that no capacities/airflows are zero in order to prevent potential E+ errors.
|
537
|
+
HVAC.ensure_nonzero_sizing_values(@hpxml_bldg)
|
538
|
+
# Make adjustments for modeling purposes
|
539
|
+
@frac_windows_operable = @hpxml_bldg.fraction_of_windows_operable()
|
540
|
+
@hpxml_bldg.collapse_enclosure_surfaces() # Speeds up simulation
|
541
|
+
@hpxml_bldg.delete_adiabatic_subsurfaces() # EnergyPlus doesn't allow this
|
313
542
|
|
314
543
|
# We don't want this to be written to in.xml, because then if you ran the in.xml
|
315
544
|
# file, you would get different results (operational calculation) relative to the
|
316
545
|
# original file (asset calculation).
|
317
|
-
if @
|
318
|
-
@
|
546
|
+
if @hpxml_bldg.building_occupancy.number_of_residents.nil?
|
547
|
+
@hpxml_bldg.building_occupancy.number_of_residents = Geometry.get_occupancy_default_num(@nbeds)
|
319
548
|
end
|
320
549
|
|
321
550
|
# If zero occupants, ensure end uses of interest are zeroed out
|
322
|
-
if (@
|
323
|
-
@
|
324
|
-
begin_month: @
|
325
|
-
begin_day: @
|
551
|
+
if (@hpxml_bldg.building_occupancy.number_of_residents == 0) && (not @apply_ashrae140_assumptions)
|
552
|
+
@hpxml_header.unavailable_periods.add(column_name: 'Vacancy',
|
553
|
+
begin_month: @hpxml_header.sim_begin_month,
|
554
|
+
begin_day: @hpxml_header.sim_begin_day,
|
326
555
|
begin_hour: 0,
|
327
|
-
end_month: @
|
328
|
-
end_day: @
|
556
|
+
end_month: @hpxml_header.sim_end_month,
|
557
|
+
end_day: @hpxml_header.sim_end_day,
|
329
558
|
end_hour: 24,
|
330
559
|
natvent_availability: HPXML::ScheduleUnavailable)
|
331
560
|
end
|
332
561
|
end
|
333
562
|
|
334
|
-
def
|
335
|
-
SimControls.apply(model, @
|
563
|
+
def add_simulation_params(model)
|
564
|
+
SimControls.apply(model, @hpxml_header)
|
336
565
|
end
|
337
566
|
|
338
|
-
def
|
567
|
+
def add_num_occupants(model, runner, spaces)
|
339
568
|
# Occupants
|
340
|
-
num_occ = @
|
569
|
+
num_occ = @hpxml_bldg.building_occupancy.number_of_residents
|
341
570
|
return if num_occ <= 0
|
342
571
|
|
343
|
-
Geometry.apply_occupants(model, runner, @
|
344
|
-
@schedules_file, @
|
572
|
+
Geometry.apply_occupants(model, runner, @hpxml_bldg, num_occ, spaces[HPXML::LocationConditionedSpace],
|
573
|
+
@schedules_file, @hpxml_header.unavailable_periods)
|
345
574
|
end
|
346
575
|
|
347
|
-
def
|
576
|
+
def create_or_get_space(model, spaces, location)
|
348
577
|
if spaces[location].nil?
|
349
|
-
Geometry.create_space_and_zone(model, spaces, location)
|
578
|
+
Geometry.create_space_and_zone(model, spaces, location, @hpxml_bldg.building_construction.number_of_units)
|
350
579
|
end
|
351
580
|
return spaces[location]
|
352
581
|
end
|
353
582
|
|
354
|
-
def
|
355
|
-
@
|
583
|
+
def add_roofs(runner, model, spaces)
|
584
|
+
@hpxml_bldg.roofs.each do |roof|
|
356
585
|
next if roof.net_area < 1.0 # skip modeling net surface area for surfaces comprised entirely of subsurface area
|
357
586
|
|
358
587
|
if roof.azimuth.nil?
|
@@ -463,8 +692,8 @@ class OSModel
|
|
463
692
|
end
|
464
693
|
end
|
465
694
|
|
466
|
-
def
|
467
|
-
@
|
695
|
+
def add_walls(runner, model, spaces)
|
696
|
+
@hpxml_bldg.walls.each do |wall|
|
468
697
|
next if wall.net_area < 1.0 # skip modeling net surface area for surfaces comprised entirely of subsurface area
|
469
698
|
|
470
699
|
if wall.azimuth.nil?
|
@@ -531,8 +760,8 @@ class OSModel
|
|
531
760
|
end
|
532
761
|
end
|
533
762
|
|
534
|
-
def
|
535
|
-
@
|
763
|
+
def add_rim_joists(runner, model, spaces)
|
764
|
+
@hpxml_bldg.rim_joists.each do |rim_joist|
|
536
765
|
if rim_joist.azimuth.nil?
|
537
766
|
if rim_joist.is_exterior
|
538
767
|
azimuths = @default_azimuths # Model as four directions for average exterior incident solar
|
@@ -603,8 +832,8 @@ class OSModel
|
|
603
832
|
end
|
604
833
|
end
|
605
834
|
|
606
|
-
def
|
607
|
-
@
|
835
|
+
def add_floors(runner, model, spaces)
|
836
|
+
@hpxml_bldg.floors.each do |floor|
|
608
837
|
area = floor.area
|
609
838
|
width = Math::sqrt(area)
|
610
839
|
length = area / width
|
@@ -632,6 +861,12 @@ class OSModel
|
|
632
861
|
surface.setWindExposure('NoWind')
|
633
862
|
elsif floor.is_floor
|
634
863
|
surface.setSunExposure('NoSun')
|
864
|
+
if floor.exterior_adjacent_to == HPXML::LocationManufacturedHomeUnderBelly
|
865
|
+
foundation = @hpxml_bldg.foundations.find { |x| x.to_location == floor.exterior_adjacent_to }
|
866
|
+
if foundation.belly_wing_skirt_present
|
867
|
+
surface.setWindExposure('NoWind')
|
868
|
+
end
|
869
|
+
end
|
635
870
|
end
|
636
871
|
|
637
872
|
# Apply construction
|
@@ -660,7 +895,7 @@ class OSModel
|
|
660
895
|
else
|
661
896
|
outside_film = Material.AirFilmFloorReduced
|
662
897
|
end
|
663
|
-
if floor.interior_adjacent_to == HPXML::
|
898
|
+
if floor.interior_adjacent_to == HPXML::LocationConditionedSpace
|
664
899
|
mat_int_finish_or_covering = Material.CoveringBare
|
665
900
|
end
|
666
901
|
end
|
@@ -671,116 +906,73 @@ class OSModel
|
|
671
906
|
end
|
672
907
|
end
|
673
908
|
|
674
|
-
def
|
675
|
-
foundation_types = @
|
909
|
+
def add_foundation_walls_slabs(runner, model, weather, spaces)
|
910
|
+
foundation_types = @hpxml_bldg.slabs.map { |s| s.interior_adjacent_to }.uniq
|
676
911
|
|
677
912
|
foundation_types.each do |foundation_type|
|
678
|
-
# Get attached foundation walls
|
679
|
-
fnd_walls = []
|
913
|
+
# Get attached slabs/foundation walls
|
680
914
|
slabs = []
|
681
|
-
@
|
682
|
-
next unless foundation_wall.interior_adjacent_to == foundation_type
|
683
|
-
next if foundation_wall.net_area < 1.0 # skip modeling net surface area for surfaces comprised entirely of subsurface area
|
684
|
-
|
685
|
-
fnd_walls << foundation_wall
|
686
|
-
end
|
687
|
-
@hpxml.slabs.each do |slab|
|
915
|
+
@hpxml_bldg.slabs.each do |slab|
|
688
916
|
next unless slab.interior_adjacent_to == foundation_type
|
689
917
|
|
690
918
|
slabs << slab
|
691
919
|
slab.exposed_perimeter = [slab.exposed_perimeter, 1.0].max # minimum value to prevent error if no exposed slab
|
692
920
|
end
|
693
921
|
|
694
|
-
# Calculate combinations of slabs/walls for each Kiva instance
|
695
|
-
kiva_instances = get_kiva_instances(fnd_walls, slabs)
|
696
|
-
|
697
|
-
# Obtain some wall/slab information
|
698
|
-
fnd_wall_lengths = {}
|
699
|
-
fnd_walls.each do |foundation_wall|
|
700
|
-
next unless foundation_wall.is_exterior
|
701
|
-
|
702
|
-
fnd_wall_lengths[foundation_wall] = foundation_wall.area / foundation_wall.height
|
703
|
-
end
|
704
|
-
slab_exp_perims = {}
|
705
|
-
slab_areas = {}
|
706
922
|
slabs.each do |slab|
|
707
|
-
|
708
|
-
|
709
|
-
end
|
710
|
-
total_slab_exp_perim = slab_exp_perims.values.sum(0.0)
|
711
|
-
total_slab_area = slab_areas.values.sum(0.0)
|
712
|
-
total_fnd_wall_length = fnd_wall_lengths.values.sum(0.0)
|
923
|
+
slab_frac = slab.exposed_perimeter / slabs.map { |s| s.exposed_perimeter }.sum
|
924
|
+
ext_fnd_walls = slab.connected_foundation_walls.select { |fw| fw.net_area >= 1.0 && fw.is_exterior }
|
713
925
|
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
# Apportion referenced walls/slabs for this Kiva instance
|
718
|
-
slab_frac = slab_exp_perims[slab] / total_slab_exp_perim
|
719
|
-
if total_fnd_wall_length > 0
|
720
|
-
fnd_wall_frac = fnd_wall_lengths[foundation_wall] / total_fnd_wall_length
|
926
|
+
if ext_fnd_walls.empty?
|
927
|
+
# Slab w/o foundation walls
|
928
|
+
add_foundation_slab(model, weather, spaces, slab, -1 * slab.depth_below_grade.to_f, slab.exposed_perimeter, nil)
|
721
929
|
else
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
#
|
728
|
-
|
729
|
-
|
730
|
-
|
930
|
+
# Slab w/ foundation walls
|
931
|
+
ext_fnd_walls_length = ext_fnd_walls.map { |fw| fw.area / fw.height }.sum
|
932
|
+
remaining_exposed_length = slab.exposed_perimeter
|
933
|
+
|
934
|
+
# Since we don't know which FoundationWalls are adjacent to which Slabs, we apportion
|
935
|
+
# each FoundationWall to each slab.
|
936
|
+
ext_fnd_walls.each do |fnd_wall|
|
937
|
+
# Both the foundation wall and slab must have same exposed length to prevent Kiva errors.
|
938
|
+
# For the foundation wall, we are effectively modeling the net *exposed* area.
|
939
|
+
fnd_wall_length = fnd_wall.area / fnd_wall.height
|
940
|
+
apportioned_exposed_length = fnd_wall_length / ext_fnd_walls_length * slab.exposed_perimeter # Slab exposed perimeter apportioned to this foundation wall
|
941
|
+
apportioned_total_length = fnd_wall_length * slab_frac # Foundation wall length apportioned to this slab
|
942
|
+
exposed_length = [apportioned_exposed_length, apportioned_total_length].min
|
943
|
+
remaining_exposed_length -= exposed_length
|
944
|
+
|
945
|
+
kiva_foundation = add_foundation_wall(runner, model, spaces, fnd_wall, exposed_length, fnd_wall_length)
|
946
|
+
add_foundation_slab(model, weather, spaces, slab, -1 * fnd_wall.depth_below_grade, exposed_length, kiva_foundation)
|
947
|
+
end
|
731
948
|
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
no_wall_slab_exp_perim[slab] += (slab_exp_perim - fnd_wall_lengths[foundation_wall] * slab_frac)
|
739
|
-
|
740
|
-
# Reduce this slab's exposed perimeter so that EnergyPlus does not automatically
|
741
|
-
# create a second no-wall Kiva instance for each of our Kiva instances.
|
742
|
-
# Instead, we will later create our own Kiva instance to account for it.
|
743
|
-
# This reduces the number of Kiva instances we end up with.
|
744
|
-
exp_perim_frac = (fnd_wall_lengths[foundation_wall] * slab_frac) / slab_exp_perim
|
745
|
-
slab_exp_perim *= exp_perim_frac
|
746
|
-
slab_area *= exp_perim_frac
|
747
|
-
end
|
748
|
-
if not foundation_wall.nil?
|
749
|
-
z_origin = -1 * foundation_wall.depth_below_grade # Position based on adjacent foundation walls
|
750
|
-
else
|
751
|
-
z_origin = -1 * slab.depth_below_grade
|
949
|
+
if remaining_exposed_length > 1 # Skip if a small length (e.g., due to rounding)
|
950
|
+
# The slab's exposed perimeter exceeds the sum of attached exterior foundation wall lengths.
|
951
|
+
# This may legitimately occur for a walkout basement, where a portion of the slab has no
|
952
|
+
# adjacent foundation wall.
|
953
|
+
add_foundation_slab(model, weather, spaces, slab, 0, remaining_exposed_length, nil)
|
954
|
+
end
|
752
955
|
end
|
753
|
-
add_foundation_slab(model, weather, spaces, slab, slab_exp_perim,
|
754
|
-
slab_area, z_origin, kiva_foundation)
|
755
|
-
end
|
756
|
-
|
757
|
-
# For each slab, create a no-wall Kiva slab instance if needed.
|
758
|
-
slabs.each do |slab|
|
759
|
-
next unless no_wall_slab_exp_perim[slab] > 1.0
|
760
|
-
|
761
|
-
z_origin = 0
|
762
|
-
slab_area = total_slab_area * no_wall_slab_exp_perim[slab] / total_slab_exp_perim
|
763
|
-
add_foundation_slab(model, weather, spaces, slab, no_wall_slab_exp_perim[slab],
|
764
|
-
slab_area, z_origin, nil)
|
765
956
|
end
|
766
957
|
|
767
958
|
# Interzonal foundation wall surfaces
|
768
959
|
# The above-grade portion of these walls are modeled as EnergyPlus surfaces with standard adjacency.
|
769
960
|
# The below-grade portion of these walls (in contact with ground) are not modeled, as Kiva does not
|
770
961
|
# calculate heat flow between two zones through the ground.
|
771
|
-
|
772
|
-
|
962
|
+
int_fnd_walls = @hpxml_bldg.foundation_walls.select { |fw| fw.is_interior && fw.interior_adjacent_to == foundation_type }
|
963
|
+
int_fnd_walls.each do |fnd_wall|
|
964
|
+
next unless fnd_wall.is_interior
|
773
965
|
|
774
|
-
ag_height =
|
775
|
-
ag_net_area =
|
966
|
+
ag_height = fnd_wall.height - fnd_wall.depth_below_grade
|
967
|
+
ag_net_area = fnd_wall.net_area * ag_height / fnd_wall.height
|
776
968
|
next if ag_net_area < 1.0
|
777
969
|
|
778
970
|
length = ag_net_area / ag_height
|
779
971
|
z_origin = -1 * ag_height
|
780
|
-
if
|
972
|
+
if fnd_wall.azimuth.nil?
|
781
973
|
azimuth = @default_azimuths[0] # Arbitrary direction, doesn't receive exterior incident solar
|
782
974
|
else
|
783
|
-
azimuth =
|
975
|
+
azimuth = fnd_wall.azimuth
|
784
976
|
end
|
785
977
|
|
786
978
|
vertices = Geometry.create_wall_vertices(length, ag_height, z_origin, azimuth)
|
@@ -789,10 +981,10 @@ class OSModel
|
|
789
981
|
surface.additionalProperties.setFeature('Azimuth', azimuth)
|
790
982
|
surface.additionalProperties.setFeature('Tilt', 90.0)
|
791
983
|
surface.additionalProperties.setFeature('SurfaceType', 'FoundationWall')
|
792
|
-
surface.setName(
|
984
|
+
surface.setName(fnd_wall.id)
|
793
985
|
surface.setSurfaceType('Wall')
|
794
|
-
set_surface_interior(model, spaces, surface,
|
795
|
-
set_surface_exterior(model, spaces, surface,
|
986
|
+
set_surface_interior(model, spaces, surface, fnd_wall)
|
987
|
+
set_surface_exterior(model, spaces, surface, fnd_wall)
|
796
988
|
surface.setSunExposure('NoSun')
|
797
989
|
surface.setWindExposure('NoWind')
|
798
990
|
|
@@ -801,57 +993,50 @@ class OSModel
|
|
801
993
|
wall_type = HPXML::WallTypeConcrete
|
802
994
|
inside_film = Material.AirFilmVertical
|
803
995
|
outside_film = Material.AirFilmVertical
|
804
|
-
assembly_r =
|
805
|
-
mat_int_finish = Material.InteriorFinishMaterial(
|
996
|
+
assembly_r = fnd_wall.insulation_assembly_r_value
|
997
|
+
mat_int_finish = Material.InteriorFinishMaterial(fnd_wall.interior_finish_type, fnd_wall.interior_finish_thickness)
|
806
998
|
if assembly_r.nil?
|
807
|
-
concrete_thick_in =
|
808
|
-
int_r =
|
809
|
-
ext_r =
|
999
|
+
concrete_thick_in = fnd_wall.thickness
|
1000
|
+
int_r = fnd_wall.insulation_interior_r_value
|
1001
|
+
ext_r = fnd_wall.insulation_exterior_r_value
|
810
1002
|
mat_concrete = Material.Concrete(concrete_thick_in)
|
811
1003
|
mat_int_finish_rvalue = mat_int_finish.nil? ? 0.0 : mat_int_finish.rvalue
|
812
1004
|
assembly_r = int_r + ext_r + mat_concrete.rvalue + mat_int_finish_rvalue + inside_film.rvalue + outside_film.rvalue
|
813
1005
|
end
|
814
1006
|
mat_ext_finish = nil
|
815
1007
|
|
816
|
-
Constructions.apply_wall_construction(runner, model, [surface],
|
1008
|
+
Constructions.apply_wall_construction(runner, model, [surface], fnd_wall.id, wall_type, assembly_r,
|
817
1009
|
mat_int_finish, inside_film, outside_film, mat_ext_finish, nil, nil)
|
818
1010
|
end
|
819
1011
|
end
|
820
1012
|
end
|
821
1013
|
|
822
|
-
def
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
gross_area = foundation_wall.area * slab_frac
|
1014
|
+
def add_foundation_wall(runner, model, spaces, foundation_wall, exposed_length, fnd_wall_length)
|
1015
|
+
exposed_fraction = exposed_length / fnd_wall_length
|
1016
|
+
net_exposed_area = foundation_wall.net_area * exposed_fraction
|
1017
|
+
gross_exposed_area = foundation_wall.area * exposed_fraction
|
827
1018
|
height = foundation_wall.height
|
828
1019
|
height_ag = height - foundation_wall.depth_below_grade
|
829
1020
|
z_origin = -1 * foundation_wall.depth_below_grade
|
830
|
-
length = gross_area / height
|
831
1021
|
if foundation_wall.azimuth.nil?
|
832
1022
|
azimuth = @default_azimuths[0] # Arbitrary; solar incidence in Kiva is applied as an orientation average (to the above grade portion of the wall)
|
833
1023
|
else
|
834
1024
|
azimuth = foundation_wall.azimuth
|
835
1025
|
end
|
836
1026
|
|
837
|
-
if
|
838
|
-
# Calculate exposed section of wall based on slab's total exposed perimeter.
|
839
|
-
length *= total_slab_exp_perim / total_fnd_wall_length
|
840
|
-
end
|
1027
|
+
return if exposed_length < 0.1 # Avoid Kiva error if exposed wall length is too small
|
841
1028
|
|
842
|
-
|
843
|
-
|
844
|
-
if gross_area > net_area
|
1029
|
+
if gross_exposed_area > net_exposed_area
|
845
1030
|
# Create a "notch" in the wall to account for the subsurfaces. This ensures that
|
846
1031
|
# we preserve the appropriate wall height, length, and area for Kiva.
|
847
|
-
subsurface_area =
|
1032
|
+
subsurface_area = gross_exposed_area - net_exposed_area
|
848
1033
|
else
|
849
1034
|
subsurface_area = 0
|
850
1035
|
end
|
851
1036
|
|
852
|
-
vertices = Geometry.create_wall_vertices(
|
1037
|
+
vertices = Geometry.create_wall_vertices(exposed_length, height, z_origin, azimuth, subsurface_area: subsurface_area)
|
853
1038
|
surface = OpenStudio::Model::Surface.new(vertices, model)
|
854
|
-
surface.additionalProperties.setFeature('Length',
|
1039
|
+
surface.additionalProperties.setFeature('Length', exposed_length)
|
855
1040
|
surface.additionalProperties.setFeature('Azimuth', azimuth)
|
856
1041
|
surface.additionalProperties.setFeature('Tilt', 90.0)
|
857
1042
|
surface.additionalProperties.setFeature('SurfaceType', 'FoundationWall')
|
@@ -893,7 +1078,7 @@ class OSModel
|
|
893
1078
|
int_rigid_r = foundation_wall.insulation_interior_r_value
|
894
1079
|
end
|
895
1080
|
|
896
|
-
soil_k_in = UnitConversions.convert(@
|
1081
|
+
soil_k_in = UnitConversions.convert(@hpxml_bldg.site.ground_conductivity, 'ft', 'in')
|
897
1082
|
|
898
1083
|
Constructions.apply_foundation_wall(model, [surface], "#{foundation_wall.id} construction",
|
899
1084
|
ext_rigid_offset, int_rigid_offset, ext_rigid_height, int_rigid_height,
|
@@ -907,10 +1092,10 @@ class OSModel
|
|
907
1092
|
return surface.adjacentFoundation.get
|
908
1093
|
end
|
909
1094
|
|
910
|
-
def
|
911
|
-
|
912
|
-
|
913
|
-
|
1095
|
+
def add_foundation_slab(model, weather, spaces, slab, z_origin, exposed_length, kiva_foundation)
|
1096
|
+
exposed_fraction = exposed_length / slab.exposed_perimeter
|
1097
|
+
slab_tot_perim = exposed_length
|
1098
|
+
slab_area = slab.area * exposed_fraction
|
914
1099
|
if slab_tot_perim**2 - 16.0 * slab_area <= 0
|
915
1100
|
# Cannot construct rectangle with this perimeter/area. Some of the
|
916
1101
|
# perimeter is presumably not exposed, so bump up perimeter value.
|
@@ -961,18 +1146,18 @@ class OSModel
|
|
961
1146
|
mat_carpet = Material.CoveringBare(slab.carpet_fraction,
|
962
1147
|
slab.carpet_r_value)
|
963
1148
|
end
|
964
|
-
soil_k_in = UnitConversions.convert(@
|
1149
|
+
soil_k_in = UnitConversions.convert(@hpxml_bldg.site.ground_conductivity, 'ft', 'in')
|
965
1150
|
|
966
1151
|
Constructions.apply_foundation_slab(model, surface, "#{slab.id} construction",
|
967
1152
|
slab_under_r, slab_under_width, slab_gap_r, slab_perim_r,
|
968
1153
|
slab_perim_depth, slab_whole_r, slab.thickness,
|
969
|
-
|
1154
|
+
exposed_length, mat_carpet, soil_k_in, kiva_foundation)
|
970
1155
|
|
971
1156
|
kiva_foundation = surface.adjacentFoundation.get
|
972
1157
|
|
973
1158
|
foundation_walls_insulated = false
|
974
1159
|
foundation_ceiling_insulated = false
|
975
|
-
@
|
1160
|
+
@hpxml_bldg.foundation_walls.each do |fnd_wall|
|
976
1161
|
next unless fnd_wall.interior_adjacent_to == slab.interior_adjacent_to
|
977
1162
|
next unless fnd_wall.exterior_adjacent_to == HPXML::LocationGround
|
978
1163
|
|
@@ -982,8 +1167,8 @@ class OSModel
|
|
982
1167
|
foundation_walls_insulated = true
|
983
1168
|
end
|
984
1169
|
end
|
985
|
-
@
|
986
|
-
next unless floor.interior_adjacent_to == HPXML::
|
1170
|
+
@hpxml_bldg.floors.each do |floor|
|
1171
|
+
next unless floor.interior_adjacent_to == HPXML::LocationConditionedSpace
|
987
1172
|
next unless floor.exterior_adjacent_to == slab.interior_adjacent_to
|
988
1173
|
|
989
1174
|
if floor.insulation_assembly_r_value > 5
|
@@ -992,29 +1177,29 @@ class OSModel
|
|
992
1177
|
end
|
993
1178
|
|
994
1179
|
Constructions.apply_kiva_initial_temp(kiva_foundation, slab, weather,
|
995
|
-
spaces[HPXML::
|
996
|
-
@
|
997
|
-
@
|
1180
|
+
spaces[HPXML::LocationConditionedSpace].thermalZone.get,
|
1181
|
+
@hpxml_header.sim_begin_month, @hpxml_header.sim_begin_day,
|
1182
|
+
@hpxml_header.sim_calendar_year, @schedules_file,
|
998
1183
|
foundation_walls_insulated, foundation_ceiling_insulated)
|
999
1184
|
|
1000
1185
|
return kiva_foundation
|
1001
1186
|
end
|
1002
1187
|
|
1003
|
-
def
|
1188
|
+
def add_conditioned_floor_area(model, spaces)
|
1004
1189
|
# Check if we need to add floors between conditioned spaces (e.g., between first
|
1005
1190
|
# and second story or conditioned basement ceiling).
|
1006
1191
|
# This ensures that the E+ reported Conditioned Floor Area is correct.
|
1007
1192
|
|
1008
1193
|
sum_cfa = 0.0
|
1009
|
-
@
|
1194
|
+
@hpxml_bldg.floors.each do |floor|
|
1010
1195
|
next unless floor.is_floor
|
1011
|
-
next unless [HPXML::
|
1012
|
-
[HPXML::
|
1196
|
+
next unless [HPXML::LocationConditionedSpace, HPXML::LocationBasementConditioned].include?(floor.interior_adjacent_to) ||
|
1197
|
+
[HPXML::LocationConditionedSpace, HPXML::LocationBasementConditioned].include?(floor.exterior_adjacent_to)
|
1013
1198
|
|
1014
1199
|
sum_cfa += floor.area
|
1015
1200
|
end
|
1016
|
-
@
|
1017
|
-
next unless [HPXML::
|
1201
|
+
@hpxml_bldg.slabs.each do |slab|
|
1202
|
+
next unless [HPXML::LocationConditionedSpace, HPXML::LocationBasementConditioned].include? slab.interior_adjacent_to
|
1018
1203
|
|
1019
1204
|
sum_cfa += slab.area
|
1020
1205
|
end
|
@@ -1037,7 +1222,7 @@ class OSModel
|
|
1037
1222
|
floor_surface.setWindExposure('NoWind')
|
1038
1223
|
floor_surface.setName('inferred conditioned floor')
|
1039
1224
|
floor_surface.setSurfaceType('Floor')
|
1040
|
-
floor_surface.setSpace(create_or_get_space(model, spaces, HPXML::
|
1225
|
+
floor_surface.setSpace(create_or_get_space(model, spaces, HPXML::LocationConditionedSpace))
|
1041
1226
|
floor_surface.setOutsideBoundaryCondition('Adiabatic')
|
1042
1227
|
floor_surface.additionalProperties.setFeature('SurfaceType', 'InferredFloor')
|
1043
1228
|
floor_surface.additionalProperties.setFeature('Tilt', 0.0)
|
@@ -1050,7 +1235,7 @@ class OSModel
|
|
1050
1235
|
ceiling_surface.setWindExposure('NoWind')
|
1051
1236
|
ceiling_surface.setName('inferred conditioned ceiling')
|
1052
1237
|
ceiling_surface.setSurfaceType('RoofCeiling')
|
1053
|
-
ceiling_surface.setSpace(create_or_get_space(model, spaces, HPXML::
|
1238
|
+
ceiling_surface.setSpace(create_or_get_space(model, spaces, HPXML::LocationConditionedSpace))
|
1054
1239
|
ceiling_surface.setOutsideBoundaryCondition('Adiabatic')
|
1055
1240
|
ceiling_surface.additionalProperties.setFeature('SurfaceType', 'InferredCeiling')
|
1056
1241
|
ceiling_surface.additionalProperties.setFeature('Tilt', 0.0)
|
@@ -1059,22 +1244,22 @@ class OSModel
|
|
1059
1244
|
apply_adiabatic_construction(model, [floor_surface, ceiling_surface], 'floor')
|
1060
1245
|
end
|
1061
1246
|
|
1062
|
-
def
|
1247
|
+
def add_thermal_mass(model, spaces)
|
1063
1248
|
if @apply_ashrae140_assumptions
|
1064
1249
|
# 1024 ft2 of interior partition wall mass, no furniture mass
|
1065
1250
|
mat_int_finish = Material.InteriorFinishMaterial(HPXML::InteriorFinishGypsumBoard, 0.5)
|
1066
1251
|
partition_wall_area = 1024.0 * 2 # Exposed partition wall area (both sides)
|
1067
1252
|
Constructions.apply_partition_walls(model, 'PartitionWallConstruction', mat_int_finish, partition_wall_area, spaces)
|
1068
1253
|
else
|
1069
|
-
mat_int_finish = Material.InteriorFinishMaterial(@
|
1070
|
-
partition_wall_area = @
|
1254
|
+
mat_int_finish = Material.InteriorFinishMaterial(@hpxml_bldg.partition_wall_mass.interior_finish_type, @hpxml_bldg.partition_wall_mass.interior_finish_thickness)
|
1255
|
+
partition_wall_area = @hpxml_bldg.partition_wall_mass.area_fraction * @cfa # Exposed partition wall area (both sides)
|
1071
1256
|
Constructions.apply_partition_walls(model, 'PartitionWallConstruction', mat_int_finish, partition_wall_area, spaces)
|
1072
1257
|
|
1073
|
-
Constructions.apply_furniture(model, @
|
1258
|
+
Constructions.apply_furniture(model, @hpxml_bldg.furniture_mass, spaces)
|
1074
1259
|
end
|
1075
1260
|
end
|
1076
1261
|
|
1077
|
-
def
|
1262
|
+
def add_cooling_season(model, weather)
|
1078
1263
|
# Create cooling season schedule
|
1079
1264
|
# Applies to natural ventilation and calculation of component loads, not HVAC equipment
|
1080
1265
|
# Uses BAHSP cooling season, not user-specified cooling season (which may be, e.g., year-round)
|
@@ -1086,22 +1271,20 @@ class OSModel
|
|
1086
1271
|
@clg_ssn_sensor.setKeyName(clg_season_sch.schedule.name.to_s)
|
1087
1272
|
end
|
1088
1273
|
|
1089
|
-
def
|
1274
|
+
def add_windows(model, spaces)
|
1090
1275
|
# We already stored @fraction_of_windows_operable, so lets remove the
|
1091
1276
|
# fraction_operable properties from windows and re-collapse the enclosure
|
1092
1277
|
# so as to prevent potentially modeling multiple identical windows in E+,
|
1093
1278
|
# which can increase simulation runtime.
|
1094
|
-
@
|
1279
|
+
@hpxml_bldg.windows.each do |window|
|
1095
1280
|
window.fraction_operable = nil
|
1096
1281
|
end
|
1097
|
-
@
|
1282
|
+
@hpxml_bldg.collapse_enclosure_surfaces()
|
1098
1283
|
|
1099
|
-
shading_group = nil
|
1100
1284
|
shading_schedules = {}
|
1101
|
-
shading_ems = { sensors: {}, program: nil }
|
1102
1285
|
|
1103
1286
|
surfaces = []
|
1104
|
-
@
|
1287
|
+
@hpxml_bldg.windows.each do |window|
|
1105
1288
|
window_height = 4.0 # ft, default
|
1106
1289
|
|
1107
1290
|
overhang_depth = nil
|
@@ -1142,16 +1325,14 @@ class OSModel
|
|
1142
1325
|
|
1143
1326
|
if not overhang_depth.nil?
|
1144
1327
|
overhang = sub_surface.addOverhang(UnitConversions.convert(overhang_depth, 'ft', 'm'), UnitConversions.convert(overhang_distance_to_top, 'ft', 'm'))
|
1145
|
-
overhang.get.setName("#{sub_surface.name}
|
1328
|
+
overhang.get.setName("#{sub_surface.name} overhangs")
|
1146
1329
|
end
|
1147
1330
|
|
1148
1331
|
# Apply construction
|
1149
1332
|
Constructions.apply_window(model, sub_surface, 'WindowConstruction', ufactor, shgc)
|
1150
1333
|
|
1151
1334
|
# Apply interior/exterior shading (as needed)
|
1152
|
-
|
1153
|
-
shading_group = Constructions.apply_window_skylight_shading(model, window, i, shading_vertices, surface, sub_surface, shading_group,
|
1154
|
-
shading_schedules, shading_ems, Constants.ObjectNameWindowShade, @hpxml)
|
1335
|
+
Constructions.apply_window_skylight_shading(model, window, sub_surface, shading_schedules, @hpxml_header, @hpxml_bldg)
|
1155
1336
|
else
|
1156
1337
|
# Window is on an interior surface, which E+ does not allow. Model
|
1157
1338
|
# as a door instead so that we can get the appropriate conduction
|
@@ -1188,14 +1369,11 @@ class OSModel
|
|
1188
1369
|
apply_adiabatic_construction(model, surfaces, 'wall')
|
1189
1370
|
end
|
1190
1371
|
|
1191
|
-
def
|
1372
|
+
def add_skylights(model, spaces)
|
1192
1373
|
surfaces = []
|
1193
|
-
|
1194
|
-
shading_group = nil
|
1195
1374
|
shading_schedules = {}
|
1196
|
-
shading_ems = { sensors: {}, program: nil }
|
1197
1375
|
|
1198
|
-
@
|
1376
|
+
@hpxml_bldg.skylights.each do |skylight|
|
1199
1377
|
tilt = skylight.roof.pitch / 12.0
|
1200
1378
|
width = Math::sqrt(skylight.area)
|
1201
1379
|
length = skylight.area / width
|
@@ -1213,7 +1391,7 @@ class OSModel
|
|
1213
1391
|
surface.additionalProperties.setFeature('SurfaceType', 'Skylight')
|
1214
1392
|
surface.setName("surface #{skylight.id}")
|
1215
1393
|
surface.setSurfaceType('RoofCeiling')
|
1216
|
-
surface.setSpace(create_or_get_space(model, spaces, HPXML::
|
1394
|
+
surface.setSpace(create_or_get_space(model, spaces, HPXML::LocationConditionedSpace)) # Ensures it is included in Manual J sizing
|
1217
1395
|
surface.setOutsideBoundaryCondition('Outdoors') # cannot be adiabatic because subsurfaces won't be created
|
1218
1396
|
surfaces << surface
|
1219
1397
|
|
@@ -1227,17 +1405,15 @@ class OSModel
|
|
1227
1405
|
Constructions.apply_skylight(model, sub_surface, 'SkylightConstruction', ufactor, shgc)
|
1228
1406
|
|
1229
1407
|
# Apply interior/exterior shading (as needed)
|
1230
|
-
|
1231
|
-
shading_group = Constructions.apply_window_skylight_shading(model, skylight, i, shading_vertices, surface, sub_surface, shading_group,
|
1232
|
-
shading_schedules, shading_ems, Constants.ObjectNameSkylightShade, @hpxml)
|
1408
|
+
Constructions.apply_window_skylight_shading(model, skylight, sub_surface, shading_schedules, @hpxml_header, @hpxml_bldg)
|
1233
1409
|
end
|
1234
1410
|
|
1235
1411
|
apply_adiabatic_construction(model, surfaces, 'roof')
|
1236
1412
|
end
|
1237
1413
|
|
1238
|
-
def
|
1414
|
+
def add_doors(model, spaces)
|
1239
1415
|
surfaces = []
|
1240
|
-
@
|
1416
|
+
@hpxml_bldg.doors.each do |door|
|
1241
1417
|
door_height = 6.67 # ft
|
1242
1418
|
door_length = door.area / door_height
|
1243
1419
|
z_origin = @foundation_top
|
@@ -1277,7 +1453,7 @@ class OSModel
|
|
1277
1453
|
apply_adiabatic_construction(model, surfaces, 'wall')
|
1278
1454
|
end
|
1279
1455
|
|
1280
|
-
def
|
1456
|
+
def apply_adiabatic_construction(model, surfaces, type)
|
1281
1457
|
# Arbitrary construction for heat capacitance.
|
1282
1458
|
# Only applies to surfaces where outside boundary conditioned is
|
1283
1459
|
# adiabatic or surface net area is near zero.
|
@@ -1302,80 +1478,81 @@ class OSModel
|
|
1302
1478
|
end
|
1303
1479
|
end
|
1304
1480
|
|
1305
|
-
def
|
1481
|
+
def add_hot_water_and_appliances(runner, model, weather, spaces)
|
1306
1482
|
# Assign spaces
|
1307
|
-
@
|
1483
|
+
@hpxml_bldg.clothes_washers.each do |clothes_washer|
|
1308
1484
|
clothes_washer.additional_properties.space = get_space_from_location(clothes_washer.location, spaces)
|
1309
1485
|
end
|
1310
|
-
@
|
1486
|
+
@hpxml_bldg.clothes_dryers.each do |clothes_dryer|
|
1311
1487
|
clothes_dryer.additional_properties.space = get_space_from_location(clothes_dryer.location, spaces)
|
1312
1488
|
end
|
1313
|
-
@
|
1489
|
+
@hpxml_bldg.dishwashers.each do |dishwasher|
|
1314
1490
|
dishwasher.additional_properties.space = get_space_from_location(dishwasher.location, spaces)
|
1315
1491
|
end
|
1316
|
-
@
|
1492
|
+
@hpxml_bldg.refrigerators.each do |refrigerator|
|
1317
1493
|
refrigerator.additional_properties.space = get_space_from_location(refrigerator.location, spaces)
|
1318
1494
|
end
|
1319
|
-
@
|
1495
|
+
@hpxml_bldg.freezers.each do |freezer|
|
1320
1496
|
freezer.additional_properties.space = get_space_from_location(freezer.location, spaces)
|
1321
1497
|
end
|
1322
|
-
@
|
1498
|
+
@hpxml_bldg.cooking_ranges.each do |cooking_range|
|
1323
1499
|
cooking_range.additional_properties.space = get_space_from_location(cooking_range.location, spaces)
|
1324
1500
|
end
|
1325
1501
|
|
1326
1502
|
# Distribution
|
1327
|
-
if @
|
1328
|
-
hot_water_distribution = @
|
1503
|
+
if @hpxml_bldg.water_heating_systems.size > 0
|
1504
|
+
hot_water_distribution = @hpxml_bldg.hot_water_distributions[0]
|
1329
1505
|
end
|
1330
1506
|
|
1331
1507
|
# Solar thermal system
|
1332
1508
|
solar_thermal_system = nil
|
1333
|
-
if @
|
1334
|
-
solar_thermal_system = @
|
1509
|
+
if @hpxml_bldg.solar_thermal_systems.size > 0
|
1510
|
+
solar_thermal_system = @hpxml_bldg.solar_thermal_systems[0]
|
1335
1511
|
end
|
1336
1512
|
|
1337
1513
|
# Water Heater
|
1338
|
-
unavailable_periods = Schedule.get_unavailable_periods(runner, SchedulesFile::ColumnWaterHeater, @
|
1339
|
-
|
1514
|
+
unavailable_periods = Schedule.get_unavailable_periods(runner, SchedulesFile::ColumnWaterHeater, @hpxml_header.unavailable_periods)
|
1515
|
+
unit_multiplier = @hpxml_bldg.building_construction.number_of_units
|
1516
|
+
has_uncond_bsmnt = @hpxml_bldg.has_location(HPXML::LocationBasementUnconditioned)
|
1340
1517
|
plantloop_map = {}
|
1341
|
-
@
|
1518
|
+
@hpxml_bldg.water_heating_systems.each do |water_heating_system|
|
1342
1519
|
loc_space, loc_schedule = get_space_or_schedule_from_location(water_heating_system.location, model, spaces)
|
1343
1520
|
|
1344
1521
|
ec_adj = HotWaterAndAppliances.get_dist_energy_consumption_adjustment(has_uncond_bsmnt, @cfa, @ncfl, water_heating_system, hot_water_distribution)
|
1345
1522
|
|
1346
1523
|
sys_id = water_heating_system.id
|
1347
1524
|
if water_heating_system.water_heater_type == HPXML::WaterHeaterTypeStorage
|
1348
|
-
plantloop_map[sys_id] = Waterheater.apply_tank(model, runner, loc_space, loc_schedule, water_heating_system, ec_adj, solar_thermal_system, @eri_version, @schedules_file, unavailable_periods)
|
1525
|
+
plantloop_map[sys_id] = Waterheater.apply_tank(model, runner, loc_space, loc_schedule, water_heating_system, ec_adj, solar_thermal_system, @eri_version, @schedules_file, unavailable_periods, unit_multiplier)
|
1349
1526
|
elsif water_heating_system.water_heater_type == HPXML::WaterHeaterTypeTankless
|
1350
|
-
plantloop_map[sys_id] = Waterheater.apply_tankless(model, runner, loc_space, loc_schedule, water_heating_system, ec_adj, solar_thermal_system, @eri_version, @schedules_file, unavailable_periods)
|
1527
|
+
plantloop_map[sys_id] = Waterheater.apply_tankless(model, runner, loc_space, loc_schedule, water_heating_system, ec_adj, solar_thermal_system, @eri_version, @schedules_file, unavailable_periods, unit_multiplier)
|
1351
1528
|
elsif water_heating_system.water_heater_type == HPXML::WaterHeaterTypeHeatPump
|
1352
|
-
|
1353
|
-
plantloop_map[sys_id] = Waterheater.apply_heatpump(model, runner, loc_space, loc_schedule, weather, water_heating_system, ec_adj, solar_thermal_system,
|
1529
|
+
conditioned_zone = spaces[HPXML::LocationConditionedSpace].thermalZone.get
|
1530
|
+
plantloop_map[sys_id] = Waterheater.apply_heatpump(model, runner, loc_space, loc_schedule, weather, water_heating_system, ec_adj, solar_thermal_system, conditioned_zone, @eri_version, @schedules_file, unavailable_periods, unit_multiplier)
|
1354
1531
|
elsif [HPXML::WaterHeaterTypeCombiStorage, HPXML::WaterHeaterTypeCombiTankless].include? water_heating_system.water_heater_type
|
1355
|
-
plantloop_map[sys_id] = Waterheater.apply_combi(model, runner, loc_space, loc_schedule, water_heating_system, ec_adj, solar_thermal_system, @eri_version, @schedules_file, unavailable_periods)
|
1532
|
+
plantloop_map[sys_id] = Waterheater.apply_combi(model, runner, loc_space, loc_schedule, water_heating_system, ec_adj, solar_thermal_system, @eri_version, @schedules_file, unavailable_periods, unit_multiplier)
|
1356
1533
|
else
|
1357
1534
|
fail "Unhandled water heater (#{water_heating_system.water_heater_type})."
|
1358
1535
|
end
|
1359
1536
|
end
|
1360
1537
|
|
1361
1538
|
# Hot water fixtures and appliances
|
1362
|
-
HotWaterAndAppliances.apply(model, runner, @
|
1539
|
+
HotWaterAndAppliances.apply(model, runner, @hpxml_header, @hpxml_bldg, weather, spaces, hot_water_distribution,
|
1363
1540
|
solar_thermal_system, @eri_version, @schedules_file, plantloop_map,
|
1364
|
-
@
|
1541
|
+
@hpxml_header.unavailable_periods, @hpxml_bldg.building_construction.number_of_units)
|
1365
1542
|
|
1366
1543
|
if (not solar_thermal_system.nil?) && (not solar_thermal_system.collector_area.nil?) # Detailed solar water heater
|
1367
1544
|
loc_space, loc_schedule = get_space_or_schedule_from_location(solar_thermal_system.water_heating_system.location, model, spaces)
|
1368
|
-
Waterheater.apply_solar_thermal(model, loc_space, loc_schedule, solar_thermal_system, plantloop_map)
|
1545
|
+
Waterheater.apply_solar_thermal(model, loc_space, loc_schedule, solar_thermal_system, plantloop_map, unit_multiplier)
|
1369
1546
|
end
|
1370
1547
|
|
1371
1548
|
# Add combi-system EMS program with water use equipment information
|
1372
|
-
Waterheater.apply_combi_system_EMS(model, @
|
1549
|
+
Waterheater.apply_combi_system_EMS(model, @hpxml_bldg.water_heating_systems, plantloop_map)
|
1373
1550
|
end
|
1374
1551
|
|
1375
|
-
def
|
1376
|
-
|
1552
|
+
def add_cooling_system(model, weather, spaces, airloop_map)
|
1553
|
+
conditioned_zone = spaces[HPXML::LocationConditionedSpace].thermalZone.get
|
1377
1554
|
|
1378
|
-
HVAC.get_hpxml_hvac_systems(@
|
1555
|
+
HVAC.get_hpxml_hvac_systems(@hpxml_bldg).each do |hvac_system|
|
1379
1556
|
next if hvac_system[:cooling].nil?
|
1380
1557
|
next unless hvac_system[:cooling].is_a? HPXML::CoolingSystem
|
1381
1558
|
|
@@ -1405,22 +1582,23 @@ class OSModel
|
|
1405
1582
|
HPXML::HVACTypeMiniSplitAirConditioner,
|
1406
1583
|
HPXML::HVACTypePTAC].include? cooling_system.cooling_system_type
|
1407
1584
|
|
1408
|
-
airloop_map[sys_id] = HVAC.apply_air_source_hvac_systems(model, cooling_system, heating_system,
|
1409
|
-
|
1410
|
-
|
1585
|
+
airloop_map[sys_id] = HVAC.apply_air_source_hvac_systems(model, cooling_system, heating_system, sequential_cool_load_fracs, sequential_heat_load_fracs,
|
1586
|
+
weather.data.AnnualMaxDrybulb, weather.data.AnnualMinDrybulb,
|
1587
|
+
conditioned_zone, @hvac_unavailable_periods)
|
1411
1588
|
|
1412
1589
|
elsif [HPXML::HVACTypeEvaporativeCooler].include? cooling_system.cooling_system_type
|
1413
1590
|
|
1414
|
-
airloop_map[sys_id] = HVAC.apply_evaporative_cooler(model, cooling_system,
|
1415
|
-
|
1591
|
+
airloop_map[sys_id] = HVAC.apply_evaporative_cooler(model, cooling_system, sequential_cool_load_fracs,
|
1592
|
+
conditioned_zone, @hvac_unavailable_periods,
|
1593
|
+
@hpxml_bldg.building_construction.number_of_units)
|
1416
1594
|
end
|
1417
1595
|
end
|
1418
1596
|
end
|
1419
1597
|
|
1420
|
-
def
|
1421
|
-
|
1598
|
+
def add_heating_system(runner, model, weather, spaces, airloop_map)
|
1599
|
+
conditioned_zone = spaces[HPXML::LocationConditionedSpace].thermalZone.get
|
1422
1600
|
|
1423
|
-
HVAC.get_hpxml_hvac_systems(@
|
1601
|
+
HVAC.get_hpxml_hvac_systems(@hpxml_bldg).each do |hvac_system|
|
1424
1602
|
next if hvac_system[:heating].nil?
|
1425
1603
|
next unless hvac_system[:heating].is_a? HPXML::HeatingSystem
|
1426
1604
|
|
@@ -1449,43 +1627,42 @@ class OSModel
|
|
1449
1627
|
sys_id = heating_system.id
|
1450
1628
|
if [HPXML::HVACTypeFurnace].include? heating_system.heating_system_type
|
1451
1629
|
|
1452
|
-
airloop_map[sys_id] = HVAC.apply_air_source_hvac_systems(model, nil, heating_system,
|
1453
|
-
|
1454
|
-
|
1630
|
+
airloop_map[sys_id] = HVAC.apply_air_source_hvac_systems(model, nil, heating_system, [0], sequential_heat_load_fracs,
|
1631
|
+
weather.data.AnnualMaxDrybulb, weather.data.AnnualMinDrybulb,
|
1632
|
+
conditioned_zone, @hvac_unavailable_periods)
|
1455
1633
|
|
1456
1634
|
elsif [HPXML::HVACTypeBoiler].include? heating_system.heating_system_type
|
1457
1635
|
|
1458
|
-
airloop_map[sys_id] = HVAC.apply_boiler(model, runner, heating_system,
|
1459
|
-
|
1636
|
+
airloop_map[sys_id] = HVAC.apply_boiler(model, runner, heating_system, sequential_heat_load_fracs, conditioned_zone,
|
1637
|
+
@hvac_unavailable_periods)
|
1460
1638
|
|
1461
1639
|
elsif [HPXML::HVACTypeElectricResistance].include? heating_system.heating_system_type
|
1462
1640
|
|
1463
1641
|
HVAC.apply_electric_baseboard(model, heating_system,
|
1464
|
-
sequential_heat_load_fracs,
|
1642
|
+
sequential_heat_load_fracs, conditioned_zone, @hvac_unavailable_periods)
|
1465
1643
|
|
1466
1644
|
elsif [HPXML::HVACTypeStove,
|
1467
|
-
HPXML::
|
1468
|
-
HPXML::HVACTypeFixedHeater,
|
1645
|
+
HPXML::HVACTypeSpaceHeater,
|
1469
1646
|
HPXML::HVACTypeWallFurnace,
|
1470
1647
|
HPXML::HVACTypeFloorFurnace,
|
1471
1648
|
HPXML::HVACTypeFireplace].include? heating_system.heating_system_type
|
1472
1649
|
|
1473
1650
|
HVAC.apply_unit_heater(model, heating_system,
|
1474
|
-
sequential_heat_load_fracs,
|
1651
|
+
sequential_heat_load_fracs, conditioned_zone, @hvac_unavailable_periods)
|
1475
1652
|
end
|
1476
1653
|
|
1477
1654
|
next unless heating_system.is_heat_pump_backup_system
|
1478
1655
|
|
1479
1656
|
# Store OS object for later use
|
1480
|
-
equipment_list = model.getZoneHVACEquipmentLists.find { |el| el.thermalZone ==
|
1657
|
+
equipment_list = model.getZoneHVACEquipmentLists.find { |el| el.thermalZone == conditioned_zone }
|
1481
1658
|
@heat_pump_backup_system_object = equipment_list.equipment[-1]
|
1482
1659
|
end
|
1483
1660
|
end
|
1484
1661
|
|
1485
|
-
def
|
1486
|
-
|
1662
|
+
def add_heat_pump(runner, model, weather, spaces, airloop_map)
|
1663
|
+
conditioned_zone = spaces[HPXML::LocationConditionedSpace].thermalZone.get
|
1487
1664
|
|
1488
|
-
HVAC.get_hpxml_hvac_systems(@
|
1665
|
+
HVAC.get_hpxml_hvac_systems(@hpxml_bldg).each do |hvac_system|
|
1489
1666
|
next if hvac_system[:cooling].nil?
|
1490
1667
|
next unless hvac_system[:cooling].is_a? HPXML::HeatPump
|
1491
1668
|
|
@@ -1506,26 +1683,27 @@ class OSModel
|
|
1506
1683
|
|
1507
1684
|
airloop_map[sys_id] = HVAC.apply_water_loop_to_air_heat_pump(model, heat_pump,
|
1508
1685
|
sequential_heat_load_fracs, sequential_cool_load_fracs,
|
1509
|
-
|
1686
|
+
conditioned_zone, @hvac_unavailable_periods)
|
1510
1687
|
|
1511
1688
|
elsif [HPXML::HVACTypeHeatPumpAirToAir,
|
1512
1689
|
HPXML::HVACTypeHeatPumpMiniSplit,
|
1513
1690
|
HPXML::HVACTypeHeatPumpPTHP,
|
1514
1691
|
HPXML::HVACTypeHeatPumpRoom].include? heat_pump.heat_pump_type
|
1515
|
-
airloop_map[sys_id] = HVAC.apply_air_source_hvac_systems(model, heat_pump, heat_pump,
|
1516
|
-
|
1517
|
-
|
1692
|
+
airloop_map[sys_id] = HVAC.apply_air_source_hvac_systems(model, heat_pump, heat_pump, sequential_cool_load_fracs, sequential_heat_load_fracs,
|
1693
|
+
weather.data.AnnualMaxDrybulb, weather.data.AnnualMinDrybulb,
|
1694
|
+
conditioned_zone, @hvac_unavailable_periods)
|
1518
1695
|
elsif [HPXML::HVACTypeHeatPumpGroundToAir].include? heat_pump.heat_pump_type
|
1519
1696
|
|
1520
1697
|
airloop_map[sys_id] = HVAC.apply_ground_to_air_heat_pump(model, runner, weather, heat_pump,
|
1521
1698
|
sequential_heat_load_fracs, sequential_cool_load_fracs,
|
1522
|
-
|
1699
|
+
conditioned_zone, @hpxml_bldg.site.ground_conductivity, @hvac_unavailable_periods,
|
1700
|
+
@hpxml_bldg.building_construction.number_of_units)
|
1523
1701
|
|
1524
1702
|
end
|
1525
1703
|
|
1526
|
-
next
|
1704
|
+
next if heat_pump.backup_system.nil?
|
1527
1705
|
|
1528
|
-
equipment_list = model.getZoneHVACEquipmentLists.find { |el| el.thermalZone ==
|
1706
|
+
equipment_list = model.getZoneHVACEquipmentLists.find { |el| el.thermalZone == conditioned_zone }
|
1529
1707
|
|
1530
1708
|
# Set priority to be last (i.e., after the heat pump that it is backup for)
|
1531
1709
|
equipment_list.setHeatingPriority(@heat_pump_backup_system_object, 99)
|
@@ -1533,14 +1711,13 @@ class OSModel
|
|
1533
1711
|
end
|
1534
1712
|
end
|
1535
1713
|
|
1536
|
-
def
|
1714
|
+
def add_ideal_system(model, spaces, epw_path)
|
1537
1715
|
# Adds an ideal air system as needed to meet the load under certain circumstances:
|
1538
1716
|
# 1. the sum of fractions load served is less than 1, or
|
1539
1717
|
# 2. we're using an ideal air system for e.g. ASHRAE 140 loads calculation.
|
1540
|
-
|
1541
|
-
obj_name = Constants.ObjectNameIdealAirSystem
|
1718
|
+
conditioned_zone = spaces[HPXML::LocationConditionedSpace].thermalZone.get
|
1542
1719
|
|
1543
|
-
if @apply_ashrae140_assumptions && (@
|
1720
|
+
if @apply_ashrae140_assumptions && (@hpxml_bldg.total_fraction_heat_load_served + @hpxml_bldg.total_fraction_heat_load_served == 0.0)
|
1544
1721
|
cooling_load_frac = 1.0
|
1545
1722
|
heating_load_frac = 1.0
|
1546
1723
|
if @apply_ashrae140_assumptions
|
@@ -1552,56 +1729,57 @@ class OSModel
|
|
1552
1729
|
fail 'Unexpected weather file for ASHRAE 140 run.'
|
1553
1730
|
end
|
1554
1731
|
end
|
1555
|
-
HVAC.apply_ideal_air_loads(model,
|
1556
|
-
|
1732
|
+
HVAC.apply_ideal_air_loads(model, [cooling_load_frac], [heating_load_frac],
|
1733
|
+
conditioned_zone, @hvac_unavailable_periods)
|
1557
1734
|
return
|
1558
1735
|
end
|
1559
1736
|
|
1560
|
-
if (@
|
1561
|
-
sequential_heat_load_fracs = HVAC.calc_sequential_load_fractions(@remaining_heat_load_frac - @
|
1562
|
-
@remaining_heat_load_frac -= (1.0 - @
|
1737
|
+
if (@hpxml_bldg.total_fraction_heat_load_served < 1.0) && (@hpxml_bldg.total_fraction_heat_load_served > 0.0)
|
1738
|
+
sequential_heat_load_fracs = HVAC.calc_sequential_load_fractions(@remaining_heat_load_frac - @hpxml_bldg.total_fraction_heat_load_served, @remaining_heat_load_frac, @heating_days)
|
1739
|
+
@remaining_heat_load_frac -= (1.0 - @hpxml_bldg.total_fraction_heat_load_served)
|
1563
1740
|
else
|
1564
1741
|
sequential_heat_load_fracs = [0.0]
|
1565
1742
|
end
|
1566
1743
|
|
1567
|
-
if (@
|
1568
|
-
sequential_cool_load_fracs = HVAC.calc_sequential_load_fractions(@remaining_cool_load_frac - @
|
1569
|
-
@remaining_cool_load_frac -= (1.0 - @
|
1744
|
+
if (@hpxml_bldg.total_fraction_cool_load_served < 1.0) && (@hpxml_bldg.total_fraction_cool_load_served > 0.0)
|
1745
|
+
sequential_cool_load_fracs = HVAC.calc_sequential_load_fractions(@remaining_cool_load_frac - @hpxml_bldg.total_fraction_cool_load_served, @remaining_cool_load_frac, @cooling_days)
|
1746
|
+
@remaining_cool_load_frac -= (1.0 - @hpxml_bldg.total_fraction_cool_load_served)
|
1570
1747
|
else
|
1571
1748
|
sequential_cool_load_fracs = [0.0]
|
1572
1749
|
end
|
1573
1750
|
|
1574
1751
|
if (sequential_heat_load_fracs.sum > 0.0) || (sequential_cool_load_fracs.sum > 0.0)
|
1575
|
-
HVAC.apply_ideal_air_loads(model,
|
1576
|
-
|
1752
|
+
HVAC.apply_ideal_air_loads(model, sequential_cool_load_fracs, sequential_heat_load_fracs,
|
1753
|
+
conditioned_zone, @hvac_unavailable_periods)
|
1577
1754
|
end
|
1578
1755
|
end
|
1579
1756
|
|
1580
|
-
def
|
1581
|
-
return if @
|
1757
|
+
def add_setpoints(runner, model, weather, spaces)
|
1758
|
+
return if @hpxml_bldg.hvac_controls.size == 0
|
1582
1759
|
|
1583
|
-
hvac_control = @
|
1584
|
-
|
1585
|
-
has_ceiling_fan = (@
|
1760
|
+
hvac_control = @hpxml_bldg.hvac_controls[0]
|
1761
|
+
conditioned_zone = spaces[HPXML::LocationConditionedSpace].thermalZone.get
|
1762
|
+
has_ceiling_fan = (@hpxml_bldg.ceiling_fans.size > 0)
|
1586
1763
|
|
1587
|
-
HVAC.apply_setpoints(model, runner, weather, hvac_control,
|
1764
|
+
HVAC.apply_setpoints(model, runner, weather, hvac_control, conditioned_zone, has_ceiling_fan, @heating_days, @cooling_days, @hpxml_header.sim_calendar_year, @schedules_file)
|
1588
1765
|
end
|
1589
1766
|
|
1590
|
-
def
|
1591
|
-
return if @
|
1767
|
+
def add_ceiling_fans(runner, model, weather, spaces)
|
1768
|
+
return if @hpxml_bldg.ceiling_fans.size == 0
|
1592
1769
|
|
1593
|
-
ceiling_fan = @
|
1594
|
-
HVAC.apply_ceiling_fans(model, runner, weather, ceiling_fan, spaces[HPXML::
|
1595
|
-
@schedules_file, @
|
1770
|
+
ceiling_fan = @hpxml_bldg.ceiling_fans[0]
|
1771
|
+
HVAC.apply_ceiling_fans(model, runner, weather, ceiling_fan, spaces[HPXML::LocationConditionedSpace],
|
1772
|
+
@schedules_file, @hpxml_header.unavailable_periods)
|
1596
1773
|
end
|
1597
1774
|
|
1598
|
-
def
|
1599
|
-
return if @
|
1775
|
+
def add_dehumidifiers(runner, model, spaces)
|
1776
|
+
return if @hpxml_bldg.dehumidifiers.size == 0
|
1600
1777
|
|
1601
|
-
HVAC.apply_dehumidifiers(runner, model, @
|
1778
|
+
HVAC.apply_dehumidifiers(runner, model, @hpxml_bldg.dehumidifiers, spaces[HPXML::LocationConditionedSpace], @hpxml_header.unavailable_periods,
|
1779
|
+
@hpxml_bldg.building_construction.number_of_units)
|
1602
1780
|
end
|
1603
1781
|
|
1604
|
-
def
|
1782
|
+
def check_distribution_system(hvac_distribution, system_type)
|
1605
1783
|
return if hvac_distribution.nil?
|
1606
1784
|
|
1607
1785
|
hvac_distribution_type_map = { HPXML::HVACTypeFurnace => [HPXML::HVACDistributionTypeAir, HPXML::HVACDistributionTypeDSE],
|
@@ -1619,9 +1797,9 @@ class OSModel
|
|
1619
1797
|
end
|
1620
1798
|
end
|
1621
1799
|
|
1622
|
-
def
|
1800
|
+
def add_mels(runner, model, spaces)
|
1623
1801
|
# Misc
|
1624
|
-
@
|
1802
|
+
@hpxml_bldg.plug_loads.each do |plug_load|
|
1625
1803
|
if plug_load.plug_load_type == HPXML::PlugLoadTypeOther
|
1626
1804
|
obj_name = Constants.ObjectNameMiscPlugLoads
|
1627
1805
|
elsif plug_load.plug_load_type == HPXML::PlugLoadTypeTelevision
|
@@ -1636,14 +1814,14 @@ class OSModel
|
|
1636
1814
|
next
|
1637
1815
|
end
|
1638
1816
|
|
1639
|
-
MiscLoads.apply_plug(model, runner, plug_load, obj_name, spaces[HPXML::
|
1640
|
-
@schedules_file, @
|
1817
|
+
MiscLoads.apply_plug(model, runner, plug_load, obj_name, spaces[HPXML::LocationConditionedSpace], @apply_ashrae140_assumptions,
|
1818
|
+
@schedules_file, @hpxml_header.unavailable_periods)
|
1641
1819
|
end
|
1642
1820
|
end
|
1643
1821
|
|
1644
|
-
def
|
1822
|
+
def add_mfls(runner, model, spaces)
|
1645
1823
|
# Misc
|
1646
|
-
@
|
1824
|
+
@hpxml_bldg.fuel_loads.each do |fuel_load|
|
1647
1825
|
if fuel_load.fuel_load_type == HPXML::FuelLoadTypeGrill
|
1648
1826
|
obj_name = Constants.ObjectNameMiscGrill
|
1649
1827
|
elsif fuel_load.fuel_load_type == HPXML::FuelLoadTypeLighting
|
@@ -1656,44 +1834,33 @@ class OSModel
|
|
1656
1834
|
next
|
1657
1835
|
end
|
1658
1836
|
|
1659
|
-
MiscLoads.apply_fuel(model, runner, fuel_load, obj_name, spaces[HPXML::
|
1660
|
-
@schedules_file, @
|
1837
|
+
MiscLoads.apply_fuel(model, runner, fuel_load, obj_name, spaces[HPXML::LocationConditionedSpace],
|
1838
|
+
@schedules_file, @hpxml_header.unavailable_periods)
|
1661
1839
|
end
|
1662
1840
|
end
|
1663
1841
|
|
1664
|
-
def
|
1665
|
-
Lighting.apply(runner, model, epw_file, spaces, @
|
1666
|
-
@schedules_file, @cfa, @
|
1842
|
+
def add_lighting(runner, model, epw_file, spaces)
|
1843
|
+
Lighting.apply(runner, model, epw_file, spaces, @hpxml_bldg.lighting_groups, @hpxml_bldg.lighting, @eri_version,
|
1844
|
+
@schedules_file, @cfa, @hpxml_header.unavailable_periods, @hpxml_bldg.building_construction.number_of_units)
|
1667
1845
|
end
|
1668
1846
|
|
1669
|
-
def
|
1670
|
-
@
|
1671
|
-
next if
|
1847
|
+
def add_pools_and_permanent_spas(runner, model, spaces)
|
1848
|
+
(@hpxml_bldg.pools + @hpxml_bldg.permanent_spas).each do |pool_or_spa|
|
1849
|
+
next if pool_or_spa.type == HPXML::TypeNone
|
1672
1850
|
|
1673
|
-
MiscLoads.
|
1674
|
-
|
1675
|
-
next if
|
1851
|
+
MiscLoads.apply_pool_or_permanent_spa_heater(runner, model, pool_or_spa, spaces[HPXML::LocationConditionedSpace],
|
1852
|
+
@schedules_file, @hpxml_header.unavailable_periods)
|
1853
|
+
next if pool_or_spa.pump_type == HPXML::TypeNone
|
1676
1854
|
|
1677
|
-
MiscLoads.
|
1678
|
-
|
1679
|
-
end
|
1680
|
-
|
1681
|
-
@hpxml.hot_tubs.each do |hot_tub|
|
1682
|
-
next if hot_tub.type == HPXML::TypeNone
|
1683
|
-
|
1684
|
-
MiscLoads.apply_pool_or_hot_tub_heater(runner, model, hot_tub, Constants.ObjectNameMiscHotTubHeater, spaces[HPXML::LocationLivingSpace],
|
1685
|
-
@schedules_file, @hpxml.header.unavailable_periods)
|
1686
|
-
next if hot_tub.pump_type == HPXML::TypeNone
|
1687
|
-
|
1688
|
-
MiscLoads.apply_pool_or_hot_tub_pump(runner, model, hot_tub, Constants.ObjectNameMiscHotTubPump, spaces[HPXML::LocationLivingSpace],
|
1689
|
-
@schedules_file, @hpxml.header.unavailable_periods)
|
1855
|
+
MiscLoads.apply_pool_or_permanent_spa_pump(runner, model, pool_or_spa, spaces[HPXML::LocationConditionedSpace],
|
1856
|
+
@schedules_file, @hpxml_header.unavailable_periods)
|
1690
1857
|
end
|
1691
1858
|
end
|
1692
1859
|
|
1693
|
-
def
|
1860
|
+
def add_airflow(runner, model, weather, spaces, airloop_map)
|
1694
1861
|
# Ducts
|
1695
1862
|
duct_systems = {}
|
1696
|
-
@
|
1863
|
+
@hpxml_bldg.hvac_distributions.each do |hvac_distribution|
|
1697
1864
|
next unless hvac_distribution.distribution_system_type == HPXML::HVACDistributionTypeAir
|
1698
1865
|
|
1699
1866
|
air_ducts = create_ducts(model, hvac_distribution, spaces)
|
@@ -1721,24 +1888,50 @@ class OSModel
|
|
1721
1888
|
end
|
1722
1889
|
end
|
1723
1890
|
|
1891
|
+
# Duct leakage to outside warnings?
|
1892
|
+
# Need to check here instead of in schematron in case duct locations are defaulted
|
1893
|
+
@hpxml_bldg.hvac_distributions.each do |hvac_distribution|
|
1894
|
+
next unless hvac_distribution.distribution_system_type == HPXML::HVACDistributionTypeAir
|
1895
|
+
next if hvac_distribution.duct_leakage_measurements.empty?
|
1896
|
+
|
1897
|
+
# Skip if there's a duct outside conditioned space
|
1898
|
+
next if hvac_distribution.ducts.select { |d| !HPXML::conditioned_locations_this_unit.include?(d.duct_location) }.size > 0
|
1899
|
+
|
1900
|
+
# Issue warning if duct leakage to outside above a certain threshold and ducts completely in conditioned space
|
1901
|
+
issue_warning = false
|
1902
|
+
units = hvac_distribution.duct_leakage_measurements[0].duct_leakage_units
|
1903
|
+
lto_measurements = hvac_distribution.duct_leakage_measurements.select { |dlm| dlm.duct_leakage_total_or_to_outside == HPXML::DuctLeakageToOutside }
|
1904
|
+
sum_lto = lto_measurements.map { |dlm| dlm.duct_leakage_value }.sum(0.0)
|
1905
|
+
if units == HPXML::UnitsCFM25
|
1906
|
+
issue_warning = true if sum_lto > 0.04 * @cfa
|
1907
|
+
elsif units == HPXML::UnitsCFM50
|
1908
|
+
issue_warning = true if sum_lto > 0.06 * @cfa
|
1909
|
+
elsif units == HPXML::UnitsPercent
|
1910
|
+
issue_warning = true if sum_lto > 0.05
|
1911
|
+
end
|
1912
|
+
next unless issue_warning
|
1913
|
+
|
1914
|
+
runner.registerWarning('Ducts are entirely within conditioned space but there is moderate leakage to the outside. Leakage to the outside is typically zero or near-zero in these situations, consider revising leakage values. Leakage will be modeled as heat lost to the ambient environment.')
|
1915
|
+
end
|
1916
|
+
|
1724
1917
|
# Create HVAC availability sensor
|
1725
|
-
|
1918
|
+
hvac_availability_sensor = nil
|
1726
1919
|
if not @hvac_unavailable_periods.empty?
|
1727
1920
|
avail_sch = ScheduleConstant.new(model, SchedulesFile::ColumnHVAC, 1.0, Constants.ScheduleTypeLimitsFraction, unavailable_periods: @hvac_unavailable_periods)
|
1728
|
-
avail_sch = avail_sch.schedule
|
1729
1921
|
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1922
|
+
hvac_availability_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
|
1923
|
+
hvac_availability_sensor.setName('hvac availability s')
|
1924
|
+
hvac_availability_sensor.setKeyName(avail_sch.schedule.name.to_s)
|
1925
|
+
hvac_availability_sensor.additionalProperties.setFeature('ObjectType', Constants.ObjectNameHVACAvailabilitySensor)
|
1733
1926
|
end
|
1734
1927
|
|
1735
|
-
Airflow.apply(model, runner, weather, spaces, @
|
1928
|
+
Airflow.apply(model, runner, weather, spaces, @hpxml_header, @hpxml_bldg, @cfa, @nbeds,
|
1736
1929
|
@ncfl_ag, duct_systems, airloop_map, @clg_ssn_sensor, @eri_version,
|
1737
1930
|
@frac_windows_operable, @apply_ashrae140_assumptions, @schedules_file,
|
1738
|
-
@
|
1931
|
+
@hpxml_header.unavailable_periods, hvac_availability_sensor)
|
1739
1932
|
end
|
1740
1933
|
|
1741
|
-
def
|
1934
|
+
def create_ducts(model, hvac_distribution, spaces)
|
1742
1935
|
air_ducts = []
|
1743
1936
|
|
1744
1937
|
# Duct leakage (supply/return => [value, units])
|
@@ -1817,96 +2010,131 @@ class OSModel
|
|
1817
2010
|
return air_ducts
|
1818
2011
|
end
|
1819
2012
|
|
1820
|
-
def
|
1821
|
-
@
|
1822
|
-
next if pv_system.inverter.inverter_efficiency == @
|
2013
|
+
def add_photovoltaics(model)
|
2014
|
+
@hpxml_bldg.pv_systems.each do |pv_system|
|
2015
|
+
next if pv_system.inverter.inverter_efficiency == @hpxml_bldg.pv_systems[0].inverter.inverter_efficiency
|
1823
2016
|
|
1824
2017
|
fail 'Expected all InverterEfficiency values to be equal.'
|
1825
2018
|
end
|
1826
|
-
@
|
1827
|
-
PV.apply(model, @nbeds, pv_system)
|
2019
|
+
@hpxml_bldg.pv_systems.each do |pv_system|
|
2020
|
+
PV.apply(model, @nbeds, pv_system, @hpxml_bldg.building_construction.number_of_units)
|
1828
2021
|
end
|
1829
2022
|
end
|
1830
2023
|
|
1831
|
-
def
|
1832
|
-
@
|
1833
|
-
Generator.apply(model, @nbeds, generator)
|
2024
|
+
def add_generators(model)
|
2025
|
+
@hpxml_bldg.generators.each do |generator|
|
2026
|
+
Generator.apply(model, @nbeds, generator, @hpxml_bldg.building_construction.number_of_units)
|
1834
2027
|
end
|
1835
2028
|
end
|
1836
2029
|
|
1837
|
-
def
|
1838
|
-
@
|
2030
|
+
def add_batteries(runner, model, spaces)
|
2031
|
+
@hpxml_bldg.batteries.each do |battery|
|
1839
2032
|
# Assign space
|
1840
2033
|
battery.additional_properties.space = get_space_from_location(battery.location, spaces)
|
1841
|
-
Battery.apply(runner, model, @
|
2034
|
+
Battery.apply(runner, model, @hpxml_bldg.pv_systems, battery, @schedules_file, @hpxml_bldg.building_construction.number_of_units)
|
1842
2035
|
end
|
1843
2036
|
end
|
1844
2037
|
|
1845
|
-
def
|
2038
|
+
def add_building_unit(model, unit_num)
|
2039
|
+
return if unit_num.nil?
|
2040
|
+
|
2041
|
+
unit = OpenStudio::Model::BuildingUnit.new(model)
|
2042
|
+
unit.additionalProperties.setFeature('unit_num', unit_num)
|
2043
|
+
model.getSpaces.each do |s|
|
2044
|
+
s.setBuildingUnit(unit)
|
2045
|
+
end
|
2046
|
+
end
|
2047
|
+
|
2048
|
+
def add_additional_properties(model, hpxml, hpxml_osm_map, hpxml_path, building_id, epw_file, hpxml_defaults_path)
|
1846
2049
|
# Store some data for use in reporting measure
|
1847
2050
|
additionalProperties = model.getBuilding.additionalProperties
|
1848
2051
|
additionalProperties.setFeature('hpxml_path', hpxml_path)
|
1849
|
-
additionalProperties.setFeature('hpxml_defaults_path',
|
2052
|
+
additionalProperties.setFeature('hpxml_defaults_path', hpxml_defaults_path)
|
1850
2053
|
additionalProperties.setFeature('building_id', building_id.to_s)
|
1851
|
-
emissions_scenario_names
|
1852
|
-
additionalProperties.setFeature('
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
1856
|
-
|
2054
|
+
additionalProperties.setFeature('emissions_scenario_names', hpxml.header.emissions_scenarios.map { |s| s.name }.to_s)
|
2055
|
+
additionalProperties.setFeature('emissions_scenario_types', hpxml.header.emissions_scenarios.map { |s| s.emissions_type }.to_s)
|
2056
|
+
heated_zones, cooled_zones = [], []
|
2057
|
+
hpxml_osm_map.each do |hpxml_bldg, unit_model|
|
2058
|
+
conditioned_zone_name = unit_model.getThermalZones.find { |z| z.additionalProperties.getFeatureAsString('ObjectType').to_s == HPXML::LocationConditionedSpace }.name.to_s
|
2059
|
+
|
2060
|
+
heated_zones << conditioned_zone_name if hpxml_bldg.total_fraction_heat_load_served > 0
|
2061
|
+
cooled_zones << conditioned_zone_name if hpxml_bldg.total_fraction_cool_load_served > 0
|
2062
|
+
end
|
2063
|
+
additionalProperties.setFeature('heated_zones', heated_zones.to_s)
|
2064
|
+
additionalProperties.setFeature('cooled_zones', cooled_zones.to_s)
|
1857
2065
|
additionalProperties.setFeature('is_southern_hemisphere', epw_file.latitude < 0)
|
1858
2066
|
end
|
1859
2067
|
|
1860
|
-
def
|
2068
|
+
def add_unmet_hours_output(model, hpxml_osm_map)
|
1861
2069
|
# We do our own unmet hours calculation via EMS so that we can incorporate,
|
1862
|
-
# e.g., heating/cooling seasons into the logic.
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
2070
|
+
# e.g., heating/cooling seasons into the logic. The calculation layers on top
|
2071
|
+
# of the built-in EnergyPlus unmet hours output.
|
2072
|
+
|
2073
|
+
# Create sensors and gather data
|
2074
|
+
htg_sensors, clg_sensors = {}, {}
|
2075
|
+
total_heat_load_serveds, total_cool_load_serveds = {}, {}
|
2076
|
+
htg_start_days, htg_end_days, clg_start_days, clg_end_days = {}, {}, {}, {}
|
2077
|
+
hpxml_osm_map.each_with_index do |(hpxml_bldg, unit_model), unit|
|
2078
|
+
conditioned_zone_name = unit_model.getThermalZones.find { |z| z.additionalProperties.getFeatureAsString('ObjectType').to_s == HPXML::LocationConditionedSpace }.name.to_s
|
2079
|
+
|
2080
|
+
# EMS sensors
|
2081
|
+
htg_sensors[unit] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Heating Setpoint Not Met Time')
|
2082
|
+
htg_sensors[unit].setName('zone htg unmet s')
|
2083
|
+
htg_sensors[unit].setKeyName(conditioned_zone_name)
|
1871
2084
|
|
1872
|
-
|
2085
|
+
clg_sensors[unit] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Cooling Setpoint Not Met Time')
|
2086
|
+
clg_sensors[unit].setName('zone clg unmet s')
|
2087
|
+
clg_sensors[unit].setKeyName(conditioned_zone_name)
|
1873
2088
|
|
1874
|
-
|
1875
|
-
|
1876
|
-
htg_sensor.setName('zone htg unmet s')
|
1877
|
-
htg_sensor.setKeyName(living_zone.name.to_s)
|
2089
|
+
total_heat_load_serveds[unit] = hpxml_bldg.total_fraction_heat_load_served
|
2090
|
+
total_cool_load_serveds[unit] = hpxml_bldg.total_fraction_cool_load_served
|
1878
2091
|
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
2092
|
+
hvac_control = hpxml_bldg.hvac_controls[0]
|
2093
|
+
next unless not hvac_control.nil?
|
2094
|
+
|
2095
|
+
sim_year = @hpxml_header.sim_calendar_year
|
2096
|
+
htg_start_days[unit] = Schedule.get_day_num_from_month_day(sim_year, hvac_control.seasons_heating_begin_month, hvac_control.seasons_heating_begin_day)
|
2097
|
+
htg_end_days[unit] = Schedule.get_day_num_from_month_day(sim_year, hvac_control.seasons_heating_end_month, hvac_control.seasons_heating_end_day)
|
2098
|
+
clg_start_days[unit] = Schedule.get_day_num_from_month_day(sim_year, hvac_control.seasons_cooling_begin_month, hvac_control.seasons_cooling_begin_day)
|
2099
|
+
clg_end_days[unit] = Schedule.get_day_num_from_month_day(sim_year, hvac_control.seasons_cooling_end_month, hvac_control.seasons_cooling_end_day)
|
2100
|
+
end
|
2101
|
+
|
2102
|
+
hvac_availability_sensor = model.getEnergyManagementSystemSensors.find { |s| s.additionalProperties.getFeatureAsString('ObjectType').to_s == Constants.ObjectNameHVACAvailabilitySensor }
|
1882
2103
|
|
1883
2104
|
# EMS program
|
1884
2105
|
clg_hrs = 'clg_unmet_hours'
|
1885
2106
|
htg_hrs = 'htg_unmet_hours'
|
1886
2107
|
program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
|
1887
|
-
program.setName(
|
2108
|
+
program.setName('unmet hours program')
|
2109
|
+
program.additionalProperties.setFeature('ObjectType', Constants.ObjectNameUnmetHoursProgram)
|
1888
2110
|
program.addLine("Set #{htg_hrs} = 0")
|
1889
2111
|
program.addLine("Set #{clg_hrs} = 0")
|
1890
|
-
|
1891
|
-
if
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
2112
|
+
for unit in 0..hpxml_osm_map.size - 1
|
2113
|
+
if total_heat_load_serveds[unit] > 0
|
2114
|
+
if htg_end_days[unit] >= htg_start_days[unit]
|
2115
|
+
line = "If ((DayOfYear >= #{htg_start_days[unit]}) && (DayOfYear <= #{htg_end_days[unit]}))"
|
2116
|
+
else
|
2117
|
+
line = "If ((DayOfYear >= #{htg_start_days[unit]}) || (DayOfYear <= #{htg_end_days[unit]}))"
|
2118
|
+
end
|
2119
|
+
line += " && (#{hvac_availability_sensor.name} == 1)" if not hvac_availability_sensor.nil?
|
2120
|
+
program.addLine(line)
|
2121
|
+
program.addLine(" If #{htg_sensors[unit].name} > #{htg_hrs}") # Use max hourly value across all units
|
2122
|
+
program.addLine(" Set #{htg_hrs} = #{htg_sensors[unit].name}")
|
2123
|
+
program.addLine(' EndIf')
|
2124
|
+
program.addLine('EndIf')
|
1895
2125
|
end
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
|
1900
|
-
end
|
1901
|
-
if @hpxml.total_fraction_cool_load_served > 0
|
1902
|
-
if clg_end_day >= clg_start_day
|
1903
|
-
line = "If ((DayOfYear >= #{clg_start_day}) && (DayOfYear <= #{clg_end_day}))"
|
2126
|
+
next unless total_cool_load_serveds[unit] > 0
|
2127
|
+
|
2128
|
+
if clg_end_days[unit] >= clg_start_days[unit]
|
2129
|
+
line = "If ((DayOfYear >= #{clg_start_days[unit]}) && (DayOfYear <= #{clg_end_days[unit]}))"
|
1904
2130
|
else
|
1905
|
-
line = "If ((DayOfYear >= #{
|
2131
|
+
line = "If ((DayOfYear >= #{clg_start_days[unit]}) || (DayOfYear <= #{clg_end_days[unit]}))"
|
1906
2132
|
end
|
1907
|
-
line += " && (#{
|
2133
|
+
line += " && (#{hvac_availability_sensor.name} == 1)" if not hvac_availability_sensor.nil?
|
1908
2134
|
program.addLine(line)
|
1909
|
-
program.addLine("
|
2135
|
+
program.addLine(" If #{clg_sensors[unit].name} > #{clg_hrs}") # Use max hourly value across all units
|
2136
|
+
program.addLine(" Set #{clg_hrs} = #{clg_sensors[unit].name}")
|
2137
|
+
program.addLine(' EndIf')
|
1910
2138
|
program.addLine('EndIf')
|
1911
2139
|
end
|
1912
2140
|
|
@@ -1917,68 +2145,88 @@ class OSModel
|
|
1917
2145
|
program_calling_manager.addProgram(program)
|
1918
2146
|
end
|
1919
2147
|
|
1920
|
-
def
|
1921
|
-
|
1922
|
-
|
1923
|
-
if @apply_ashrae140_assumptions
|
1924
|
-
total_heat_load_served = 1.0
|
1925
|
-
total_cool_load_served = 1.0
|
1926
|
-
else
|
1927
|
-
total_heat_load_served = @hpxml.total_fraction_heat_load_served
|
1928
|
-
total_cool_load_served = @hpxml.total_fraction_cool_load_served
|
1929
|
-
end
|
1930
|
-
|
1931
|
-
liv_load_sensors, intgain_dehumidifier = add_total_loads_output(model, living_zone, total_heat_load_served, total_cool_load_served)
|
2148
|
+
def add_loads_output(model, add_component_loads, hpxml_osm_map)
|
2149
|
+
loads_data = add_total_loads_output(model, hpxml_osm_map)
|
1932
2150
|
return unless add_component_loads
|
1933
2151
|
|
1934
|
-
add_component_loads_output(model,
|
2152
|
+
add_component_loads_output(model, hpxml_osm_map, loads_data)
|
1935
2153
|
end
|
1936
2154
|
|
1937
|
-
def
|
1938
|
-
#
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
|
2155
|
+
def add_total_loads_output(model, hpxml_osm_map)
|
2156
|
+
# Create sensors and gather data
|
2157
|
+
htg_cond_load_sensors, clg_cond_load_sensors = {}, {}
|
2158
|
+
htg_duct_load_sensors, clg_duct_load_sensors = {}, {}
|
2159
|
+
total_heat_load_serveds, total_cool_load_serveds = {}, {}
|
2160
|
+
dehumidifier_sensors = {}
|
2161
|
+
|
2162
|
+
hpxml_osm_map.each_with_index do |(hpxml_bldg, unit_model), unit|
|
2163
|
+
# Retrieve objects
|
2164
|
+
conditioned_zone_name = unit_model.getThermalZones.find { |z| z.additionalProperties.getFeatureAsString('ObjectType').to_s == HPXML::LocationConditionedSpace }.name.to_s
|
2165
|
+
duct_zone_names = unit_model.getThermalZones.select { |z| z.isPlenum }.map { |z| z.name.to_s }
|
2166
|
+
dehumidifier = unit_model.getZoneHVACDehumidifierDXs
|
2167
|
+
dehumidifier_name = dehumidifier[0].name.to_s unless dehumidifier.empty?
|
2168
|
+
|
2169
|
+
# Fraction heat/cool load served
|
2170
|
+
if @hpxml_header.apply_ashrae140_assumptions
|
2171
|
+
total_heat_load_serveds[unit] = 1.0
|
2172
|
+
total_cool_load_serveds[unit] = 1.0
|
2173
|
+
else
|
2174
|
+
total_heat_load_serveds[unit] = hpxml_bldg.total_fraction_heat_load_served
|
2175
|
+
total_cool_load_serveds[unit] = hpxml_bldg.total_fraction_cool_load_served
|
2176
|
+
end
|
1951
2177
|
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
2178
|
+
# Energy transferred in conditioned zone, used for determining heating (winter) vs cooling (summer)
|
2179
|
+
htg_cond_load_sensors[unit] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Heating:EnergyTransfer:Zone:#{conditioned_zone_name.upcase}")
|
2180
|
+
htg_cond_load_sensors[unit].setName('htg_load_cond')
|
2181
|
+
clg_cond_load_sensors[unit] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Cooling:EnergyTransfer:Zone:#{conditioned_zone_name.upcase}")
|
2182
|
+
clg_cond_load_sensors[unit].setName('clg_load_cond')
|
1956
2183
|
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
2184
|
+
# Energy transferred in duct zone(s)
|
2185
|
+
htg_duct_load_sensors[unit] = []
|
2186
|
+
clg_duct_load_sensors[unit] = []
|
2187
|
+
duct_zone_names.each do |duct_zone_name|
|
2188
|
+
htg_duct_load_sensors[unit] << OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Heating:EnergyTransfer:Zone:#{duct_zone_name.upcase}")
|
2189
|
+
htg_duct_load_sensors[unit][-1].setName('htg_load_duct')
|
2190
|
+
clg_duct_load_sensors[unit] << OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Cooling:EnergyTransfer:Zone:#{duct_zone_name.upcase}")
|
2191
|
+
clg_duct_load_sensors[unit][-1].setName('clg_load_duct')
|
1961
2192
|
end
|
2193
|
+
|
2194
|
+
# Need to adjusted E+ EnergyTransfer meters for dehumidifier internal gains
|
2195
|
+
next if dehumidifier_name.nil?
|
2196
|
+
|
2197
|
+
dehumidifier_sensors[unit] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Dehumidifier Sensible Heating Energy')
|
2198
|
+
dehumidifier_sensors[unit].setName('ig_dehumidifier')
|
2199
|
+
dehumidifier_sensors[unit].setKeyName(dehumidifier_name)
|
1962
2200
|
end
|
1963
2201
|
|
1964
2202
|
# EMS program
|
1965
2203
|
program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
|
1966
|
-
program.setName(
|
2204
|
+
program.setName('total loads program')
|
2205
|
+
program.additionalProperties.setFeature('ObjectType', Constants.ObjectNameTotalLoadsProgram)
|
1967
2206
|
program.addLine('Set loads_htg_tot = 0')
|
1968
2207
|
program.addLine('Set loads_clg_tot = 0')
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
2208
|
+
for unit in 0..hpxml_osm_map.size - 1
|
2209
|
+
program.addLine("If #{htg_cond_load_sensors[unit].name} > 0")
|
2210
|
+
program.addLine(" Set loads_htg_tot = loads_htg_tot + (#{htg_cond_load_sensors[unit].name} - #{clg_cond_load_sensors[unit].name}) * #{total_heat_load_serveds[unit]}")
|
2211
|
+
for i in 0..htg_duct_load_sensors[unit].size - 1
|
2212
|
+
program.addLine(" Set loads_htg_tot = loads_htg_tot + (#{htg_duct_load_sensors[unit][i].name} - #{clg_duct_load_sensors[unit][i].name}) * #{total_heat_load_serveds[unit]}")
|
2213
|
+
end
|
2214
|
+
if not dehumidifier_sensors[unit].nil?
|
2215
|
+
program.addLine(" Set loads_htg_tot = loads_htg_tot - #{dehumidifier_sensors[unit].name}")
|
2216
|
+
end
|
2217
|
+
program.addLine('EndIf')
|
1973
2218
|
end
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
2219
|
+
for unit in 0..hpxml_osm_map.size - 1
|
2220
|
+
program.addLine("If #{clg_cond_load_sensors[unit].name} > 0")
|
2221
|
+
program.addLine(" Set loads_clg_tot = loads_clg_tot + (#{clg_cond_load_sensors[unit].name} - #{htg_cond_load_sensors[unit].name}) * #{total_cool_load_serveds[unit]}")
|
2222
|
+
for i in 0..clg_duct_load_sensors[unit].size - 1
|
2223
|
+
program.addLine(" Set loads_clg_tot = loads_clg_tot + (#{clg_duct_load_sensors[unit][i].name} - #{htg_duct_load_sensors[unit][i].name}) * #{total_cool_load_serveds[unit]}")
|
2224
|
+
end
|
2225
|
+
if not dehumidifier_sensors[unit].nil?
|
2226
|
+
program.addLine(" Set loads_clg_tot = loads_clg_tot + #{dehumidifier_sensors[unit].name}")
|
2227
|
+
end
|
2228
|
+
program.addLine('EndIf')
|
1979
2229
|
end
|
1980
|
-
program.addLine(s)
|
1981
|
-
program.addLine('EndIf')
|
1982
2230
|
|
1983
2231
|
# EMS calling manager
|
1984
2232
|
program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
|
@@ -1986,27 +2234,11 @@ class OSModel
|
|
1986
2234
|
program_calling_manager.setCallingPoint('EndOfZoneTimestepAfterZoneReporting')
|
1987
2235
|
program_calling_manager.addProgram(program)
|
1988
2236
|
|
1989
|
-
return
|
2237
|
+
return htg_cond_load_sensors, clg_cond_load_sensors, total_heat_load_serveds, total_cool_load_serveds, dehumidifier_sensors
|
1990
2238
|
end
|
1991
2239
|
|
1992
|
-
def
|
1993
|
-
|
1994
|
-
objects_already_processed = []
|
1995
|
-
|
1996
|
-
# EMS Sensors: Surfaces, SubSurfaces, InternalMass
|
1997
|
-
surfaces_sensors = { walls: [],
|
1998
|
-
rim_joists: [],
|
1999
|
-
foundation_walls: [],
|
2000
|
-
floors: [],
|
2001
|
-
slabs: [],
|
2002
|
-
ceilings: [],
|
2003
|
-
roofs: [],
|
2004
|
-
windows_conduction: [],
|
2005
|
-
windows_solar: [],
|
2006
|
-
doors: [],
|
2007
|
-
skylights_conduction: [],
|
2008
|
-
skylights_solar: [],
|
2009
|
-
internal_mass: [] }
|
2240
|
+
def add_component_loads_output(model, hpxml_osm_map, loads_data)
|
2241
|
+
htg_cond_load_sensors, clg_cond_load_sensors, total_heat_load_serveds, total_cool_load_serveds, dehumidifier_sensors = loads_data
|
2010
2242
|
|
2011
2243
|
# Output diagnostics needed for some output variables used below
|
2012
2244
|
output_diagnostics = model.getOutputDiagnostics
|
@@ -2014,397 +2246,376 @@ class OSModel
|
|
2014
2246
|
|
2015
2247
|
area_tolerance = UnitConversions.convert(1.0, 'ft^2', 'm^2')
|
2016
2248
|
|
2017
|
-
|
2018
|
-
|
2249
|
+
nonsurf_names = ['intgains', 'lighting', 'infil', 'mechvent', 'natvent', 'whf', 'ducts']
|
2250
|
+
surf_names = ['walls', 'rim_joists', 'foundation_walls', 'floors', 'slabs', 'ceilings',
|
2251
|
+
'roofs', 'windows_conduction', 'windows_solar', 'doors', 'skylights_conduction',
|
2252
|
+
'skylights_solar', 'internal_mass']
|
2253
|
+
|
2254
|
+
# EMS program
|
2255
|
+
program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
|
2256
|
+
program.setName('component loads program')
|
2257
|
+
program.additionalProperties.setFeature('ObjectType', Constants.ObjectNameComponentLoadsProgram)
|
2019
2258
|
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2259
|
+
# Initialize
|
2260
|
+
[:htg, :clg].each do |mode|
|
2261
|
+
surf_names.each do |surf_name|
|
2262
|
+
program.addLine("Set loads_#{mode}_#{surf_name} = 0")
|
2263
|
+
end
|
2264
|
+
nonsurf_names.each do |nonsurf_name|
|
2265
|
+
program.addLine("Set loads_#{mode}_#{nonsurf_name} = 0")
|
2023
2266
|
end
|
2267
|
+
end
|
2024
2268
|
|
2025
|
-
|
2269
|
+
hpxml_osm_map.values.each_with_index do |unit_model, unit|
|
2270
|
+
conditioned_zone = unit_model.getThermalZones.find { |z| z.additionalProperties.getFeatureAsString('ObjectType').to_s == HPXML::LocationConditionedSpace }
|
2026
2271
|
|
2027
|
-
|
2028
|
-
|
2029
|
-
key = { 'Window' => :windows_conduction,
|
2030
|
-
'Door' => :doors,
|
2031
|
-
'Skylight' => :skylights_conduction }[surface_type]
|
2032
|
-
fail "Unexpected subsurface for component loads: '#{ss.name}'." if key.nil?
|
2272
|
+
# Prevent certain objects (e.g., OtherEquipment) from being counted towards both, e.g., ducts and internal gains
|
2273
|
+
objects_already_processed = []
|
2033
2274
|
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2275
|
+
# EMS Sensors: Surfaces, SubSurfaces, InternalMass
|
2276
|
+
surfaces_sensors = {}
|
2277
|
+
surf_names.each do |surf_name|
|
2278
|
+
surfaces_sensors[surf_name.to_sym] = []
|
2279
|
+
end
|
2280
|
+
|
2281
|
+
unit_model.getSurfaces.sort.each do |s|
|
2282
|
+
next unless s.space.get.thermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2283
|
+
|
2284
|
+
surface_type = s.additionalProperties.getFeatureAsString('SurfaceType')
|
2285
|
+
if not surface_type.is_initialized
|
2286
|
+
fail "Could not identify surface type for surface: '#{s.name}'."
|
2044
2287
|
end
|
2045
2288
|
|
2046
|
-
|
2289
|
+
surface_type = surface_type.get
|
2290
|
+
|
2291
|
+
s.subSurfaces.each do |ss|
|
2292
|
+
# Conduction (windows, skylights, doors)
|
2293
|
+
key = { 'Window' => :windows_conduction,
|
2294
|
+
'Door' => :doors,
|
2295
|
+
'Skylight' => :skylights_conduction }[surface_type]
|
2296
|
+
fail "Unexpected subsurface for component loads: '#{ss.name}'." if key.nil?
|
2297
|
+
|
2298
|
+
if (surface_type == 'Window') || (surface_type == 'Skylight')
|
2299
|
+
vars = { 'Surface Inside Face Convection Heat Gain Energy' => 'ss_conv',
|
2300
|
+
'Surface Inside Face Internal Gains Radiation Heat Gain Energy' => 'ss_ig',
|
2301
|
+
'Surface Inside Face Net Surface Thermal Radiation Heat Gain Energy' => 'ss_surf' }
|
2302
|
+
else
|
2303
|
+
vars = { 'Surface Inside Face Solar Radiation Heat Gain Energy' => 'ss_sol',
|
2304
|
+
'Surface Inside Face Lights Radiation Heat Gain Energy' => 'ss_lgt',
|
2305
|
+
'Surface Inside Face Convection Heat Gain Energy' => 'ss_conv',
|
2306
|
+
'Surface Inside Face Internal Gains Radiation Heat Gain Energy' => 'ss_ig',
|
2307
|
+
'Surface Inside Face Net Surface Thermal Radiation Heat Gain Energy' => 'ss_surf' }
|
2308
|
+
end
|
2309
|
+
|
2310
|
+
vars.each do |var, name|
|
2311
|
+
surfaces_sensors[key] << []
|
2312
|
+
sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2313
|
+
sensor.setName(name)
|
2314
|
+
sensor.setKeyName(ss.name.to_s)
|
2315
|
+
surfaces_sensors[key][-1] << sensor
|
2316
|
+
end
|
2317
|
+
|
2318
|
+
# Solar (windows, skylights)
|
2319
|
+
next unless (surface_type == 'Window') || (surface_type == 'Skylight')
|
2320
|
+
|
2321
|
+
key = { 'Window' => :windows_solar,
|
2322
|
+
'Skylight' => :skylights_solar }[surface_type]
|
2323
|
+
vars = { 'Surface Window Transmitted Solar Radiation Energy' => 'ss_trans_in',
|
2324
|
+
'Surface Window Shortwave from Zone Back Out Window Heat Transfer Rate' => 'ss_back_out',
|
2325
|
+
'Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate' => 'ss_sw_abs',
|
2326
|
+
'Surface Window Total Glazing Layers Absorbed Solar Radiation Energy' => 'ss_sol_abs',
|
2327
|
+
'Surface Inside Face Initial Transmitted Diffuse Transmitted Out Window Solar Radiation Rate' => 'ss_trans_out' }
|
2328
|
+
|
2047
2329
|
surfaces_sensors[key] << []
|
2048
|
-
|
2049
|
-
|
2050
|
-
|
2051
|
-
|
2330
|
+
vars.each do |var, name|
|
2331
|
+
sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2332
|
+
sensor.setName(name)
|
2333
|
+
sensor.setKeyName(ss.name.to_s)
|
2334
|
+
surfaces_sensors[key][-1] << sensor
|
2335
|
+
end
|
2052
2336
|
end
|
2053
2337
|
|
2054
|
-
#
|
2055
|
-
next unless (surface_type == 'Window') || (surface_type == 'Skylight')
|
2338
|
+
next if s.netArea < area_tolerance # Skip parent surfaces (of subsurfaces) that have near zero net area
|
2056
2339
|
|
2057
|
-
key = { '
|
2058
|
-
'
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2340
|
+
key = { 'FoundationWall' => :foundation_walls,
|
2341
|
+
'RimJoist' => :rim_joists,
|
2342
|
+
'Wall' => :walls,
|
2343
|
+
'Slab' => :slabs,
|
2344
|
+
'Floor' => :floors,
|
2345
|
+
'Ceiling' => :ceilings,
|
2346
|
+
'Roof' => :roofs,
|
2347
|
+
'InferredCeiling' => :internal_mass,
|
2348
|
+
'InferredFloor' => :internal_mass }[surface_type]
|
2349
|
+
fail "Unexpected surface for component loads: '#{s.name}'." if key.nil?
|
2064
2350
|
|
2065
2351
|
surfaces_sensors[key] << []
|
2066
|
-
|
2352
|
+
{ 'Surface Inside Face Convection Heat Gain Energy' => 's_conv',
|
2353
|
+
'Surface Inside Face Internal Gains Radiation Heat Gain Energy' => 's_ig',
|
2354
|
+
'Surface Inside Face Solar Radiation Heat Gain Energy' => 's_sol',
|
2355
|
+
'Surface Inside Face Lights Radiation Heat Gain Energy' => 's_lgt',
|
2356
|
+
'Surface Inside Face Net Surface Thermal Radiation Heat Gain Energy' => 's_surf' }.each do |var, name|
|
2067
2357
|
sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2068
2358
|
sensor.setName(name)
|
2069
|
-
sensor.setKeyName(
|
2359
|
+
sensor.setKeyName(s.name.to_s)
|
2070
2360
|
surfaces_sensors[key][-1] << sensor
|
2071
2361
|
end
|
2072
2362
|
end
|
2073
2363
|
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
model.getInternalMasss.sort.each do |m|
|
2101
|
-
next unless m.space.get.thermalZone.get.name.to_s == living_zone.name.to_s
|
2102
|
-
|
2103
|
-
surfaces_sensors[:internal_mass] << []
|
2104
|
-
{ 'Surface Inside Face Convection Heat Gain Energy' => 'im_conv',
|
2105
|
-
'Surface Inside Face Internal Gains Radiation Heat Gain Energy' => 'im_ig',
|
2106
|
-
'Surface Inside Face Solar Radiation Heat Gain Energy' => 'im_sol',
|
2107
|
-
'Surface Inside Face Lights Radiation Heat Gain Energy' => 'im_lgt',
|
2108
|
-
'Surface Inside Face Net Surface Thermal Radiation Heat Gain Energy' => 'im_surf' }.each do |var, name|
|
2109
|
-
sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2110
|
-
sensor.setName(name)
|
2111
|
-
sensor.setKeyName(m.name.to_s)
|
2112
|
-
surfaces_sensors[:internal_mass][-1] << sensor
|
2113
|
-
end
|
2114
|
-
end
|
2115
|
-
|
2116
|
-
# EMS Sensors: Infiltration, Mechanical Ventilation, Natural Ventilation, Whole House Fan
|
2117
|
-
infil_sensors = []
|
2118
|
-
natvent_sensors = []
|
2119
|
-
whf_sensors = []
|
2120
|
-
{ Constants.ObjectNameInfiltration => infil_sensors,
|
2121
|
-
Constants.ObjectNameNaturalVentilation => natvent_sensors,
|
2122
|
-
Constants.ObjectNameWholeHouseFan => whf_sensors }.each do |prefix, array|
|
2123
|
-
model.getSpaceInfiltrationDesignFlowRates.sort.each do |i|
|
2124
|
-
next unless i.name.to_s.start_with? prefix
|
2125
|
-
next unless i.space.get.thermalZone.get.name.to_s == living_zone.name.to_s
|
2126
|
-
|
2127
|
-
{ 'Infiltration Sensible Heat Gain Energy' => prefix.gsub(' ', '_') + '_' + 'gain',
|
2128
|
-
'Infiltration Sensible Heat Loss Energy' => prefix.gsub(' ', '_') + '_' + 'loss' }.each do |var, name|
|
2364
|
+
unit_model.getInternalMasss.sort.each do |m|
|
2365
|
+
next unless m.space.get.thermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2366
|
+
|
2367
|
+
surfaces_sensors[:internal_mass] << []
|
2368
|
+
{ 'Surface Inside Face Convection Heat Gain Energy' => 'im_conv',
|
2369
|
+
'Surface Inside Face Internal Gains Radiation Heat Gain Energy' => 'im_ig',
|
2370
|
+
'Surface Inside Face Solar Radiation Heat Gain Energy' => 'im_sol',
|
2371
|
+
'Surface Inside Face Lights Radiation Heat Gain Energy' => 'im_lgt',
|
2372
|
+
'Surface Inside Face Net Surface Thermal Radiation Heat Gain Energy' => 'im_surf' }.each do |var, name|
|
2373
|
+
sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2374
|
+
sensor.setName(name)
|
2375
|
+
sensor.setKeyName(m.name.to_s)
|
2376
|
+
surfaces_sensors[:internal_mass][-1] << sensor
|
2377
|
+
end
|
2378
|
+
end
|
2379
|
+
|
2380
|
+
# EMS Sensors: Infiltration, Natural Ventilation, Whole House Fan
|
2381
|
+
infil_sensors, natvent_sensors, whf_sensors = [], [], []
|
2382
|
+
unit_model.getSpaceInfiltrationDesignFlowRates.sort.each do |i|
|
2383
|
+
next unless i.space.get.thermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2384
|
+
|
2385
|
+
object_type = i.additionalProperties.getFeatureAsString('ObjectType').get
|
2386
|
+
|
2387
|
+
{ 'Infiltration Sensible Heat Gain Energy' => 'airflow_gain',
|
2388
|
+
'Infiltration Sensible Heat Loss Energy' => 'airflow_loss' }.each do |var, name|
|
2129
2389
|
airflow_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2130
2390
|
airflow_sensor.setName(name)
|
2131
2391
|
airflow_sensor.setKeyName(i.name.to_s)
|
2132
|
-
|
2392
|
+
if object_type == Constants.ObjectNameInfiltration
|
2393
|
+
infil_sensors << airflow_sensor
|
2394
|
+
elsif object_type == Constants.ObjectNameNaturalVentilation
|
2395
|
+
natvent_sensors << airflow_sensor
|
2396
|
+
elsif object_type == Constants.ObjectNameWholeHouseFan
|
2397
|
+
whf_sensors << airflow_sensor
|
2398
|
+
end
|
2133
2399
|
end
|
2134
2400
|
end
|
2135
|
-
end
|
2136
2401
|
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2402
|
+
# EMS Sensors: Mechanical Ventilation
|
2403
|
+
mechvents_sensors = []
|
2404
|
+
unit_model.getElectricEquipments.sort.each do |o|
|
2405
|
+
next unless o.endUseSubcategory == Constants.ObjectNameMechanicalVentilation
|
2140
2406
|
|
2141
|
-
mechvents_sensors << []
|
2142
|
-
{ 'Electric Equipment Convective Heating Energy' => 'mv_conv',
|
2143
|
-
'Electric Equipment Radiant Heating Energy' => 'mv_rad' }.each do |var, name|
|
2144
|
-
mechvent_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2145
|
-
mechvent_sensor.setName(name)
|
2146
|
-
mechvent_sensor.setKeyName(o.name.to_s)
|
2147
|
-
mechvents_sensors[-1] << mechvent_sensor
|
2148
2407
|
objects_already_processed << o
|
2408
|
+
{ 'Electric Equipment Convective Heating Energy' => 'mv_conv',
|
2409
|
+
'Electric Equipment Radiant Heating Energy' => 'mv_rad' }.each do |var, name|
|
2410
|
+
mechvent_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2411
|
+
mechvent_sensor.setName(name)
|
2412
|
+
mechvent_sensor.setKeyName(o.name.to_s)
|
2413
|
+
mechvents_sensors << mechvent_sensor
|
2414
|
+
end
|
2149
2415
|
end
|
2150
|
-
|
2151
|
-
|
2152
|
-
next unless o.name.to_s.start_with? Constants.ObjectNameMechanicalVentilationHouseFan
|
2416
|
+
unit_model.getOtherEquipments.sort.each do |o|
|
2417
|
+
next unless o.endUseSubcategory == Constants.ObjectNameMechanicalVentilationHouseFan
|
2153
2418
|
|
2154
|
-
mechvents_sensors << []
|
2155
|
-
{ 'Other Equipment Convective Heating Energy' => 'mv_conv',
|
2156
|
-
'Other Equipment Radiant Heating Energy' => 'mv_rad' }.each do |var, name|
|
2157
|
-
mechvent_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2158
|
-
mechvent_sensor.setName(name)
|
2159
|
-
mechvent_sensor.setKeyName(o.name.to_s)
|
2160
|
-
mechvents_sensors[-1] << mechvent_sensor
|
2161
2419
|
objects_already_processed << o
|
2420
|
+
{ 'Other Equipment Convective Heating Energy' => 'mv_conv',
|
2421
|
+
'Other Equipment Radiant Heating Energy' => 'mv_rad' }.each do |var, name|
|
2422
|
+
mechvent_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2423
|
+
mechvent_sensor.setName(name)
|
2424
|
+
mechvent_sensor.setKeyName(o.name.to_s)
|
2425
|
+
mechvents_sensors << mechvent_sensor
|
2426
|
+
end
|
2162
2427
|
end
|
2163
|
-
end
|
2164
2428
|
|
2165
|
-
|
2166
|
-
|
2167
|
-
|
2168
|
-
|
2429
|
+
# EMS Sensors: Ducts
|
2430
|
+
ducts_sensors = []
|
2431
|
+
ducts_mix_gain_sensor = nil
|
2432
|
+
ducts_mix_loss_sensor = nil
|
2433
|
+
conditioned_zone.zoneMixing.each do |zone_mix|
|
2434
|
+
object_type = zone_mix.additionalProperties.getFeatureAsString('ObjectType').to_s
|
2435
|
+
next unless object_type == Constants.ObjectNameDuctLoad
|
2169
2436
|
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2173
|
-
next unless zone_mix.name.to_s.start_with? airloop.name.to_s.gsub(' ', '_')
|
2437
|
+
ducts_mix_gain_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Mixing Sensible Heat Gain Energy')
|
2438
|
+
ducts_mix_gain_sensor.setName('duct_mix_gain')
|
2439
|
+
ducts_mix_gain_sensor.setKeyName(conditioned_zone.name.to_s)
|
2174
2440
|
|
2175
|
-
|
2441
|
+
ducts_mix_loss_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Mixing Sensible Heat Loss Energy')
|
2442
|
+
ducts_mix_loss_sensor.setName('duct_mix_loss')
|
2443
|
+
ducts_mix_loss_sensor.setKeyName(conditioned_zone.name.to_s)
|
2176
2444
|
end
|
2177
|
-
|
2178
|
-
|
2179
|
-
|
2180
|
-
ducts_mix_gain_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Mixing Sensible Heat Gain Energy')
|
2181
|
-
ducts_mix_gain_sensor.setName('duct_mix_gain')
|
2182
|
-
ducts_mix_gain_sensor.setKeyName(living_zone.name.to_s)
|
2183
|
-
|
2184
|
-
ducts_mix_loss_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Mixing Sensible Heat Loss Energy')
|
2185
|
-
ducts_mix_loss_sensor.setName('duct_mix_loss')
|
2186
|
-
ducts_mix_loss_sensor.setKeyName(living_zone.name.to_s)
|
2187
|
-
end
|
2188
|
-
|
2189
|
-
# Duct losses
|
2190
|
-
model.getOtherEquipments.sort.each do |o|
|
2191
|
-
next if objects_already_processed.include? o
|
2445
|
+
unit_model.getOtherEquipments.sort.each do |o|
|
2446
|
+
next if objects_already_processed.include? o
|
2447
|
+
next unless o.endUseSubcategory == Constants.ObjectNameDuctLoad
|
2192
2448
|
|
2193
|
-
|
2194
|
-
|
2449
|
+
objects_already_processed << o
|
2450
|
+
{ 'Other Equipment Convective Heating Energy' => 'ducts_conv',
|
2451
|
+
'Other Equipment Radiant Heating Energy' => 'ducts_rad' }.each do |var, name|
|
2452
|
+
ducts_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2453
|
+
ducts_sensor.setName(name)
|
2454
|
+
ducts_sensor.setKeyName(o.name.to_s)
|
2455
|
+
ducts_sensors << ducts_sensor
|
2456
|
+
end
|
2457
|
+
end
|
2195
2458
|
|
2196
|
-
|
2197
|
-
|
2459
|
+
# EMS Sensors: Lighting
|
2460
|
+
lightings_sensors = []
|
2461
|
+
unit_model.getLightss.sort.each do |e|
|
2462
|
+
next unless e.space.get.thermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2198
2463
|
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2203
|
-
|
2204
|
-
|
2205
|
-
|
2464
|
+
{ 'Lights Convective Heating Energy' => 'ig_lgt_conv',
|
2465
|
+
'Lights Radiant Heating Energy' => 'ig_lgt_rad',
|
2466
|
+
'Lights Visible Radiation Heating Energy' => 'ig_lgt_vis' }.each do |var, name|
|
2467
|
+
intgains_lights_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2468
|
+
intgains_lights_sensor.setName(name)
|
2469
|
+
intgains_lights_sensor.setKeyName(e.name.to_s)
|
2470
|
+
lightings_sensors << intgains_lights_sensor
|
2471
|
+
end
|
2206
2472
|
end
|
2207
|
-
end
|
2208
2473
|
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2474
|
+
# EMS Sensors: Internal Gains
|
2475
|
+
intgains_sensors = []
|
2476
|
+
unit_model.getElectricEquipments.sort.each do |o|
|
2477
|
+
next if objects_already_processed.include? o
|
2478
|
+
next unless o.space.get.thermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2214
2479
|
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
lightings_sensors[-1] << intgains_lights_sensor
|
2480
|
+
{ 'Electric Equipment Convective Heating Energy' => 'ig_ee_conv',
|
2481
|
+
'Electric Equipment Radiant Heating Energy' => 'ig_ee_rad' }.each do |var, name|
|
2482
|
+
intgains_elec_equip_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2483
|
+
intgains_elec_equip_sensor.setName(name)
|
2484
|
+
intgains_elec_equip_sensor.setKeyName(o.name.to_s)
|
2485
|
+
intgains_sensors << intgains_elec_equip_sensor
|
2486
|
+
end
|
2223
2487
|
end
|
2224
|
-
end
|
2225
2488
|
|
2226
|
-
|
2227
|
-
|
2489
|
+
unit_model.getOtherEquipments.sort.each do |o|
|
2490
|
+
next if objects_already_processed.include? o
|
2491
|
+
next unless o.space.get.thermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2228
2492
|
|
2229
|
-
|
2230
|
-
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2236
|
-
intgains_elec_equip_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2237
|
-
intgains_elec_equip_sensor.setName(name)
|
2238
|
-
intgains_elec_equip_sensor.setKeyName(o.name.to_s)
|
2239
|
-
intgains_sensors[-1] << intgains_elec_equip_sensor
|
2493
|
+
{ 'Other Equipment Convective Heating Energy' => 'ig_oe_conv',
|
2494
|
+
'Other Equipment Radiant Heating Energy' => 'ig_oe_rad' }.each do |var, name|
|
2495
|
+
intgains_other_equip_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2496
|
+
intgains_other_equip_sensor.setName(name)
|
2497
|
+
intgains_other_equip_sensor.setKeyName(o.name.to_s)
|
2498
|
+
intgains_sensors << intgains_other_equip_sensor
|
2499
|
+
end
|
2240
2500
|
end
|
2241
|
-
end
|
2242
2501
|
|
2243
|
-
|
2244
|
-
|
2245
|
-
next if objects_already_processed.include? o
|
2502
|
+
unit_model.getPeoples.sort.each do |e|
|
2503
|
+
next unless e.space.get.thermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2246
2504
|
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2505
|
+
{ 'People Convective Heating Energy' => 'ig_ppl_conv',
|
2506
|
+
'People Radiant Heating Energy' => 'ig_ppl_rad' }.each do |var, name|
|
2507
|
+
intgains_people = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2508
|
+
intgains_people.setName(name)
|
2509
|
+
intgains_people.setKeyName(e.name.to_s)
|
2510
|
+
intgains_sensors << intgains_people
|
2511
|
+
end
|
2254
2512
|
end
|
2255
|
-
end
|
2256
2513
|
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
intgains_sensors << []
|
2261
|
-
{ 'People Convective Heating Energy' => 'ig_ppl_conv',
|
2262
|
-
'People Radiant Heating Energy' => 'ig_ppl_rad' }.each do |var, name|
|
2263
|
-
intgains_people = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
|
2264
|
-
intgains_people.setName(name)
|
2265
|
-
intgains_people.setKeyName(e.name.to_s)
|
2266
|
-
intgains_sensors[-1] << intgains_people
|
2514
|
+
if not dehumidifier_sensors[unit].nil?
|
2515
|
+
intgains_sensors << dehumidifier_sensors[unit]
|
2267
2516
|
end
|
2268
|
-
end
|
2269
2517
|
|
2270
|
-
|
2271
|
-
intgains_sensors[-1] << intgain_dehumidifier
|
2272
|
-
end
|
2518
|
+
intgains_dhw_sensors = {}
|
2273
2519
|
|
2274
|
-
|
2520
|
+
(unit_model.getWaterHeaterMixeds + unit_model.getWaterHeaterStratifieds).sort.each do |wh|
|
2521
|
+
next unless wh.ambientTemperatureThermalZone.is_initialized
|
2522
|
+
next unless wh.ambientTemperatureThermalZone.get.name.to_s == conditioned_zone.name.to_s
|
2275
2523
|
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2524
|
+
dhw_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Water Heater Heat Loss Energy')
|
2525
|
+
dhw_sensor.setName('dhw_loss')
|
2526
|
+
dhw_sensor.setKeyName(wh.name.to_s)
|
2279
2527
|
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2528
|
+
if wh.is_a? OpenStudio::Model::WaterHeaterMixed
|
2529
|
+
oncycle_loss = wh.onCycleLossFractiontoThermalZone
|
2530
|
+
offcycle_loss = wh.offCycleLossFractiontoThermalZone
|
2531
|
+
else
|
2532
|
+
oncycle_loss = wh.skinLossFractiontoZone
|
2533
|
+
offcycle_loss = wh.offCycleFlueLossFractiontoZone
|
2534
|
+
end
|
2283
2535
|
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2536
|
+
dhw_rtf_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Water Heater Runtime Fraction')
|
2537
|
+
dhw_rtf_sensor.setName('dhw_rtf')
|
2538
|
+
dhw_rtf_sensor.setKeyName(wh.name.to_s)
|
2539
|
+
|
2540
|
+
intgains_dhw_sensors[dhw_sensor] = [offcycle_loss, oncycle_loss, dhw_rtf_sensor]
|
2541
|
+
end
|
2542
|
+
|
2543
|
+
# EMS program: Surfaces
|
2544
|
+
surfaces_sensors.each do |k, surface_sensors|
|
2545
|
+
program.addLine("Set hr_#{k} = 0")
|
2546
|
+
surface_sensors.each do |sensors|
|
2547
|
+
s = "Set hr_#{k} = hr_#{k}"
|
2548
|
+
sensors.each do |sensor|
|
2549
|
+
# remove ss_net if switch
|
2550
|
+
if sensor.name.to_s.start_with?('ss_net', 'ss_sol_abs', 'ss_trans_in')
|
2551
|
+
s += " - #{sensor.name}"
|
2552
|
+
elsif sensor.name.to_s.start_with?('ss_sw_abs', 'ss_trans_out', 'ss_back_out')
|
2553
|
+
s += " + #{sensor.name} * ZoneTimestep * 3600"
|
2554
|
+
else
|
2555
|
+
s += " + #{sensor.name}"
|
2556
|
+
end
|
2557
|
+
end
|
2558
|
+
program.addLine(s) if sensors.size > 0
|
2559
|
+
end
|
2290
2560
|
end
|
2291
2561
|
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2562
|
+
# EMS program: Internal Gains, Lighting, Infiltration, Natural Ventilation, Mechanical Ventilation, Ducts
|
2563
|
+
{ 'intgains' => intgains_sensors,
|
2564
|
+
'lighting' => lightings_sensors,
|
2565
|
+
'infil' => infil_sensors,
|
2566
|
+
'natvent' => natvent_sensors,
|
2567
|
+
'whf' => whf_sensors,
|
2568
|
+
'mechvent' => mechvents_sensors,
|
2569
|
+
'ducts' => ducts_sensors }.each do |loadtype, sensors|
|
2570
|
+
program.addLine("Set hr_#{loadtype} = 0")
|
2571
|
+
next if sensors.empty?
|
2295
2572
|
|
2296
|
-
|
2297
|
-
end
|
2298
|
-
|
2299
|
-
nonsurf_names = ['intgains', 'lighting', 'infil', 'mechvent', 'natvent', 'whf', 'ducts']
|
2300
|
-
|
2301
|
-
# EMS program
|
2302
|
-
program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
|
2303
|
-
program.setName(Constants.ObjectNameComponentLoadsProgram)
|
2304
|
-
|
2305
|
-
# EMS program: Surfaces
|
2306
|
-
surfaces_sensors.each do |k, surface_sensors|
|
2307
|
-
program.addLine("Set hr_#{k} = 0")
|
2308
|
-
surface_sensors.each do |sensors|
|
2309
|
-
s = "Set hr_#{k} = hr_#{k}"
|
2573
|
+
s = "Set hr_#{loadtype} = hr_#{loadtype}"
|
2310
2574
|
sensors.each do |sensor|
|
2311
|
-
|
2312
|
-
if sensor.name.to_s.start_with?('ss_net', 'ss_sol_abs', 'ss_trans_in')
|
2575
|
+
if ['intgains', 'lighting', 'mechvent', 'ducts'].include? loadtype
|
2313
2576
|
s += " - #{sensor.name}"
|
2314
|
-
elsif sensor.name.to_s.
|
2315
|
-
s += "
|
2316
|
-
|
2577
|
+
elsif sensor.name.to_s.include? 'gain'
|
2578
|
+
s += " - #{sensor.name}"
|
2579
|
+
elsif sensor.name.to_s.include? 'loss'
|
2317
2580
|
s += " + #{sensor.name}"
|
2318
2581
|
end
|
2319
2582
|
end
|
2320
|
-
program.addLine(s)
|
2321
|
-
end
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2329
|
-
|
2330
|
-
|
2331
|
-
program.addLine(
|
2332
|
-
|
2333
|
-
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
program.addLine(
|
2342
|
-
end
|
2343
|
-
intgains_dhw_sensors.each do |sensor, vals|
|
2344
|
-
off_loss, on_loss, rtf_sensor = vals
|
2345
|
-
program.addLine("Set hr_intgains = hr_intgains + #{sensor.name} * (#{off_loss}*(1-#{rtf_sensor.name}) + #{on_loss}*#{rtf_sensor.name})") # Water heater tank losses to zone
|
2346
|
-
end
|
2583
|
+
program.addLine(s)
|
2584
|
+
end
|
2585
|
+
intgains_dhw_sensors.each do |sensor, vals|
|
2586
|
+
off_loss, on_loss, rtf_sensor = vals
|
2587
|
+
program.addLine("Set hr_intgains = hr_intgains + #{sensor.name} * (#{off_loss}*(1-#{rtf_sensor.name}) + #{on_loss}*#{rtf_sensor.name})") # Water heater tank losses to zone
|
2588
|
+
end
|
2589
|
+
if (not ducts_mix_loss_sensor.nil?) && (not ducts_mix_gain_sensor.nil?)
|
2590
|
+
program.addLine("Set hr_ducts = hr_ducts + (#{ducts_mix_loss_sensor.name} - #{ducts_mix_gain_sensor.name})")
|
2591
|
+
end
|
2592
|
+
|
2593
|
+
# EMS program: Heating vs Cooling logic
|
2594
|
+
program.addLine('Set htg_mode = 0')
|
2595
|
+
program.addLine('Set clg_mode = 0')
|
2596
|
+
program.addLine("If (#{htg_cond_load_sensors[unit].name} > 0)") # Assign hour to heating if heating load
|
2597
|
+
program.addLine(" Set htg_mode = #{total_heat_load_serveds[unit]}")
|
2598
|
+
program.addLine("ElseIf (#{clg_cond_load_sensors[unit].name} > 0)") # Assign hour to cooling if cooling load
|
2599
|
+
program.addLine(" Set clg_mode = #{total_cool_load_serveds[unit]}")
|
2600
|
+
program.addLine("ElseIf (#{@clg_ssn_sensor.name} > 0)") # No load, assign hour to cooling if in cooling season definition (Note: natural ventilation & whole house fan only operate during the cooling season)
|
2601
|
+
program.addLine(" Set clg_mode = #{total_cool_load_serveds[unit]}")
|
2602
|
+
program.addLine('Else') # No load, assign hour to heating if not in cooling season definition
|
2603
|
+
program.addLine(" Set htg_mode = #{total_heat_load_serveds[unit]}")
|
2604
|
+
program.addLine('EndIf')
|
2347
2605
|
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
sensors.each do |sensor|
|
2355
|
-
if sensor.name.to_s.include? 'gain'
|
2356
|
-
# FIXME: Workaround for https://github.com/NREL/EnergyPlus/issues/9934
|
2357
|
-
# Remove when the issue is resolved
|
2358
|
-
if loadtype == 'infil'
|
2359
|
-
s += " - (#{sensor.name} * 3600)"
|
2360
|
-
else
|
2361
|
-
s += " - #{sensor.name}"
|
2362
|
-
end
|
2363
|
-
elsif sensor.name.to_s.include? 'loss'
|
2364
|
-
s += " + #{sensor.name}"
|
2606
|
+
unit_multiplier = @hpxml_bldg.building_construction.number_of_units
|
2607
|
+
[:htg, :clg].each do |mode|
|
2608
|
+
if mode == :htg
|
2609
|
+
sign = ''
|
2610
|
+
else
|
2611
|
+
sign = '-'
|
2365
2612
|
end
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
program.addLine("Set hr_#{loadtype} = 0")
|
2372
|
-
all_sensors.each do |sensors|
|
2373
|
-
s = "Set hr_#{loadtype} = hr_#{loadtype}"
|
2374
|
-
sensors.each do |sensor|
|
2375
|
-
s += " - #{sensor.name}"
|
2613
|
+
surf_names.each do |surf_name|
|
2614
|
+
program.addLine("Set loads_#{mode}_#{surf_name} = loads_#{mode}_#{surf_name} + (#{sign}hr_#{surf_name} * #{mode}_mode * #{unit_multiplier})")
|
2615
|
+
end
|
2616
|
+
nonsurf_names.each do |nonsurf_name|
|
2617
|
+
program.addLine("Set loads_#{mode}_#{nonsurf_name} = loads_#{mode}_#{nonsurf_name} + (#{sign}hr_#{nonsurf_name} * #{mode}_mode * #{unit_multiplier})")
|
2376
2618
|
end
|
2377
|
-
program.addLine(s) if sensors.size > 0
|
2378
|
-
end
|
2379
|
-
end
|
2380
|
-
if (not ducts_mix_loss_sensor.nil?) && (not ducts_mix_gain_sensor.nil?)
|
2381
|
-
program.addLine("Set hr_ducts = hr_ducts + (#{ducts_mix_loss_sensor.name} - #{ducts_mix_gain_sensor.name})")
|
2382
|
-
end
|
2383
|
-
|
2384
|
-
# EMS program: Heating vs Cooling logic
|
2385
|
-
program.addLine('Set htg_mode = 0')
|
2386
|
-
program.addLine('Set clg_mode = 0')
|
2387
|
-
program.addLine("If (#{liv_load_sensors[:htg].name} > 0)") # Assign hour to heating if heating load
|
2388
|
-
program.addLine(" Set htg_mode = #{total_heat_load_served}")
|
2389
|
-
program.addLine("ElseIf (#{liv_load_sensors[:clg].name} > 0)") # Assign hour to cooling if cooling load
|
2390
|
-
program.addLine(" Set clg_mode = #{total_cool_load_served}")
|
2391
|
-
program.addLine("ElseIf (#{@clg_ssn_sensor.name} > 0)") # No load, assign hour to cooling if in cooling season definition (Note: natural ventilation & whole house fan only operate during the cooling season)
|
2392
|
-
program.addLine(" Set clg_mode = #{total_cool_load_served}")
|
2393
|
-
program.addLine('Else') # No load, assign hour to heating if not in cooling season definition
|
2394
|
-
program.addLine(" Set htg_mode = #{total_heat_load_served}")
|
2395
|
-
program.addLine('EndIf')
|
2396
|
-
|
2397
|
-
[:htg, :clg].each do |mode|
|
2398
|
-
if mode == :htg
|
2399
|
-
sign = ''
|
2400
|
-
else
|
2401
|
-
sign = '-'
|
2402
|
-
end
|
2403
|
-
surfaces_sensors.keys.each do |k|
|
2404
|
-
program.addLine("Set loads_#{mode}_#{k} = #{sign}hr_#{k} * #{mode}_mode")
|
2405
|
-
end
|
2406
|
-
nonsurf_names.each do |nonsurf_name|
|
2407
|
-
program.addLine("Set loads_#{mode}_#{nonsurf_name} = #{sign}hr_#{nonsurf_name} * #{mode}_mode")
|
2408
2619
|
end
|
2409
2620
|
end
|
2410
2621
|
|
@@ -2415,7 +2626,7 @@ class OSModel
|
|
2415
2626
|
program_calling_manager.addProgram(program)
|
2416
2627
|
end
|
2417
2628
|
|
2418
|
-
def
|
2629
|
+
def set_output_files(model)
|
2419
2630
|
oj = model.getOutputJSON
|
2420
2631
|
oj.setOptionType('TimeSeriesAndTabular')
|
2421
2632
|
oj.setOutputJSON(false)
|
@@ -2423,6 +2634,7 @@ class OSModel
|
|
2423
2634
|
|
2424
2635
|
ocf = model.getOutputControlFiles
|
2425
2636
|
ocf.setOutputAUDIT(@debug)
|
2637
|
+
ocf.setOutputCSV(@debug)
|
2426
2638
|
ocf.setOutputBND(@debug)
|
2427
2639
|
ocf.setOutputEIO(@debug)
|
2428
2640
|
ocf.setOutputESO(@debug)
|
@@ -2431,30 +2643,31 @@ class OSModel
|
|
2431
2643
|
ocf.setOutputMTR(@debug)
|
2432
2644
|
ocf.setOutputRDD(@debug)
|
2433
2645
|
ocf.setOutputSHD(@debug)
|
2646
|
+
ocf.setOutputCSV(@debug)
|
2434
2647
|
ocf.setOutputSQLite(@debug)
|
2435
2648
|
ocf.setOutputPerfLog(@debug)
|
2436
2649
|
end
|
2437
2650
|
|
2438
|
-
def
|
2651
|
+
def add_ems_debug_output(model)
|
2439
2652
|
oems = model.getOutputEnergyManagementSystem
|
2440
2653
|
oems.setActuatorAvailabilityDictionaryReporting('Verbose')
|
2441
2654
|
oems.setInternalVariableAvailabilityDictionaryReporting('Verbose')
|
2442
2655
|
oems.setEMSRuntimeLanguageDebugOutputLevel('Verbose')
|
2443
2656
|
end
|
2444
2657
|
|
2445
|
-
def
|
2658
|
+
def set_surface_interior(model, spaces, surface, hpxml_surface)
|
2446
2659
|
interior_adjacent_to = hpxml_surface.interior_adjacent_to
|
2447
2660
|
if HPXML::conditioned_below_grade_locations.include? interior_adjacent_to
|
2448
|
-
surface.setSpace(create_or_get_space(model, spaces, HPXML::
|
2661
|
+
surface.setSpace(create_or_get_space(model, spaces, HPXML::LocationConditionedSpace))
|
2449
2662
|
else
|
2450
2663
|
surface.setSpace(create_or_get_space(model, spaces, interior_adjacent_to))
|
2451
2664
|
end
|
2452
2665
|
end
|
2453
2666
|
|
2454
|
-
def
|
2667
|
+
def set_surface_exterior(model, spaces, surface, hpxml_surface)
|
2455
2668
|
exterior_adjacent_to = hpxml_surface.exterior_adjacent_to
|
2456
2669
|
is_adiabatic = hpxml_surface.is_adiabatic
|
2457
|
-
if
|
2670
|
+
if [HPXML::LocationOutside, HPXML::LocationManufacturedHomeUnderBelly].include? exterior_adjacent_to
|
2458
2671
|
surface.setOutsideBoundaryCondition('Outdoors')
|
2459
2672
|
elsif exterior_adjacent_to == HPXML::LocationGround
|
2460
2673
|
surface.setOutsideBoundaryCondition('Foundation')
|
@@ -2464,7 +2677,7 @@ class OSModel
|
|
2464
2677
|
HPXML::LocationOtherNonFreezingSpace, HPXML::LocationOtherHousingUnit].include? exterior_adjacent_to
|
2465
2678
|
set_surface_otherside_coefficients(surface, exterior_adjacent_to, model, spaces)
|
2466
2679
|
elsif HPXML::conditioned_below_grade_locations.include? exterior_adjacent_to
|
2467
|
-
adjacent_surface = surface.createAdjacentSurface(create_or_get_space(model, spaces, HPXML::
|
2680
|
+
adjacent_surface = surface.createAdjacentSurface(create_or_get_space(model, spaces, HPXML::LocationConditionedSpace)).get
|
2468
2681
|
adjacent_surface.additionalProperties.setFeature('SurfaceType', surface.additionalProperties.getFeatureAsString('SurfaceType').get)
|
2469
2682
|
else
|
2470
2683
|
adjacent_surface = surface.createAdjacentSurface(create_or_get_space(model, spaces, exterior_adjacent_to)).get
|
@@ -2472,7 +2685,7 @@ class OSModel
|
|
2472
2685
|
end
|
2473
2686
|
end
|
2474
2687
|
|
2475
|
-
def
|
2688
|
+
def set_surface_otherside_coefficients(surface, exterior_adjacent_to, model, spaces)
|
2476
2689
|
otherside_coeffs = nil
|
2477
2690
|
model.getSurfacePropertyOtherSideCoefficientss.each do |c|
|
2478
2691
|
next unless c.name.to_s == exterior_adjacent_to
|
@@ -2493,7 +2706,7 @@ class OSModel
|
|
2493
2706
|
surface.setWindExposure('NoWind')
|
2494
2707
|
end
|
2495
2708
|
|
2496
|
-
def
|
2709
|
+
def get_space_temperature_schedule(model, location, spaces)
|
2497
2710
|
# Create outside boundary schedules to be actuated by EMS,
|
2498
2711
|
# can be shared by any surface, duct adjacent to / located in those spaces
|
2499
2712
|
|
@@ -2506,12 +2719,13 @@ class OSModel
|
|
2506
2719
|
|
2507
2720
|
sch = OpenStudio::Model::ScheduleConstant.new(model)
|
2508
2721
|
sch.setName(location)
|
2722
|
+
sch.additionalProperties.setFeature('ObjectType', location)
|
2509
2723
|
|
2510
2724
|
space_values = Geometry.get_temperature_scheduled_space_values(location)
|
2511
2725
|
|
2512
2726
|
if location == HPXML::LocationOtherHeatedSpace
|
2513
2727
|
# Create a sensor to get dynamic heating setpoint
|
2514
|
-
htg_sch = spaces[HPXML::
|
2728
|
+
htg_sch = spaces[HPXML::LocationConditionedSpace].thermalZone.get.thermostatSetpointDualSetpoint.get.heatingSetpointTemperatureSchedule.get
|
2515
2729
|
sensor_htg_spt = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Schedule Value')
|
2516
2730
|
sensor_htg_spt.setName('htg_spt')
|
2517
2731
|
sensor_htg_spt.setKeyName(htg_sch.name.to_s)
|
@@ -2527,7 +2741,7 @@ class OSModel
|
|
2527
2741
|
if space_values[:indoor_weight] > 0
|
2528
2742
|
sensor_ia = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Air Temperature')
|
2529
2743
|
sensor_ia.setName('cond_zone_temp')
|
2530
|
-
sensor_ia.setKeyName(spaces[HPXML::
|
2744
|
+
sensor_ia.setKeyName(spaces[HPXML::LocationConditionedSpace].thermalZone.get.name.to_s)
|
2531
2745
|
end
|
2532
2746
|
|
2533
2747
|
if space_values[:outdoor_weight] > 0
|
@@ -2578,7 +2792,7 @@ class OSModel
|
|
2578
2792
|
# Returns an OS:Space, or temperature OS:Schedule for a MF space, or nil if outside
|
2579
2793
|
# Should be called when the object's energy use is sensitive to ambient temperature
|
2580
2794
|
# (e.g., water heaters and ducts).
|
2581
|
-
def
|
2795
|
+
def get_space_or_schedule_from_location(location, model, spaces)
|
2582
2796
|
return if [HPXML::LocationOtherExterior,
|
2583
2797
|
HPXML::LocationOutside,
|
2584
2798
|
HPXML::LocationRoofDeck].include? location
|
@@ -2603,7 +2817,7 @@ class OSModel
|
|
2603
2817
|
# Returns an OS:Space, or nil if a MF space or outside
|
2604
2818
|
# Should be called when the object's energy use is NOT sensitive to ambient temperature
|
2605
2819
|
# (e.g., appliances).
|
2606
|
-
def
|
2820
|
+
def get_space_from_location(location, spaces)
|
2607
2821
|
return if [HPXML::LocationOutside,
|
2608
2822
|
HPXML::LocationOtherHeatedSpace,
|
2609
2823
|
HPXML::LocationOtherHousingUnit,
|
@@ -2611,13 +2825,13 @@ class OSModel
|
|
2611
2825
|
HPXML::LocationOtherNonFreezingSpace].include? location
|
2612
2826
|
|
2613
2827
|
if HPXML::conditioned_locations.include? location
|
2614
|
-
location = HPXML::
|
2828
|
+
location = HPXML::LocationConditionedSpace
|
2615
2829
|
end
|
2616
2830
|
|
2617
2831
|
return spaces[location]
|
2618
2832
|
end
|
2619
2833
|
|
2620
|
-
def
|
2834
|
+
def set_subsurface_exterior(surface, spaces, model, hpxml_surface)
|
2621
2835
|
# Set its parent surface outside boundary condition, which will be also applied to subsurfaces through OS
|
2622
2836
|
# The parent surface is entirely comprised of the subsurface.
|
2623
2837
|
|
@@ -2629,36 +2843,25 @@ class OSModel
|
|
2629
2843
|
end
|
2630
2844
|
end
|
2631
2845
|
|
2632
|
-
def
|
2633
|
-
# Identify unique Kiva foundations that are required.
|
2634
|
-
kiva_fnd_walls = []
|
2635
|
-
fnd_walls.each do |foundation_wall|
|
2636
|
-
next unless foundation_wall.is_exterior
|
2637
|
-
|
2638
|
-
kiva_fnd_walls << foundation_wall
|
2639
|
-
end
|
2640
|
-
if kiva_fnd_walls.empty? # Handle slab foundation type
|
2641
|
-
kiva_fnd_walls << nil
|
2642
|
-
end
|
2643
|
-
|
2644
|
-
kiva_slabs = slabs
|
2645
|
-
|
2646
|
-
return kiva_fnd_walls.product(kiva_slabs)
|
2647
|
-
end
|
2648
|
-
|
2649
|
-
def self.set_foundation_and_walls_top()
|
2846
|
+
def set_foundation_and_walls_top()
|
2650
2847
|
@foundation_top = 0
|
2651
|
-
@
|
2848
|
+
@hpxml_bldg.floors.each do |floor|
|
2849
|
+
# Keeping the floor at ground level for ASHRAE 140 tests yields the expected results
|
2850
|
+
if floor.is_floor && floor.is_exterior && !@apply_ashrae140_assumptions
|
2851
|
+
@foundation_top = 2.0
|
2852
|
+
end
|
2853
|
+
end
|
2854
|
+
@hpxml_bldg.foundation_walls.each do |foundation_wall|
|
2652
2855
|
top = -1 * foundation_wall.depth_below_grade + foundation_wall.height
|
2653
2856
|
@foundation_top = top if top > @foundation_top
|
2654
2857
|
end
|
2655
|
-
@walls_top = @foundation_top +
|
2858
|
+
@walls_top = @foundation_top + @hpxml_bldg.building_construction.average_ceiling_height * @ncfl_ag
|
2656
2859
|
end
|
2657
2860
|
|
2658
|
-
def
|
2659
|
-
return if @
|
2861
|
+
def set_heating_and_cooling_seasons()
|
2862
|
+
return if @hpxml_bldg.hvac_controls.size == 0
|
2660
2863
|
|
2661
|
-
hvac_control = @
|
2864
|
+
hvac_control = @hpxml_bldg.hvac_controls[0]
|
2662
2865
|
|
2663
2866
|
htg_start_month = hvac_control.seasons_heating_begin_month
|
2664
2867
|
htg_start_day = hvac_control.seasons_heating_begin_day
|
@@ -2669,8 +2872,8 @@ class OSModel
|
|
2669
2872
|
clg_end_month = hvac_control.seasons_cooling_end_month
|
2670
2873
|
clg_end_day = hvac_control.seasons_cooling_end_day
|
2671
2874
|
|
2672
|
-
@heating_days = Schedule.get_daily_season(@
|
2673
|
-
@cooling_days = Schedule.get_daily_season(@
|
2875
|
+
@heating_days = Schedule.get_daily_season(@hpxml_header.sim_calendar_year, htg_start_month, htg_start_day, htg_end_month, htg_end_day)
|
2876
|
+
@cooling_days = Schedule.get_daily_season(@hpxml_header.sim_calendar_year, clg_start_month, clg_start_day, clg_end_month, clg_end_day)
|
2674
2877
|
end
|
2675
2878
|
end
|
2676
2879
|
|