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,8 +1,20 @@
|
|
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
|
class HVAC
|
9
|
+
AirSourceHeatRatedODB = 47.0 # degF, Rated outdoor drybulb for air-source systems, heating
|
10
|
+
AirSourceHeatRatedIDB = 70.0 # degF, Rated indoor drybulb for air-source systems, heating
|
11
|
+
AirSourceCoolRatedODB = 95.0 # degF, Rated outdoor drybulb for air-source systems, cooling
|
12
|
+
AirSourceCoolRatedIWB = 67.0 # degF, Rated indoor wetbulb for air-source systems, cooling
|
13
|
+
CrankcaseHeaterTemp = 50.0 # degF
|
14
|
+
|
4
15
|
def self.apply_air_source_hvac_systems(model, cooling_system, heating_system,
|
5
16
|
sequential_cool_load_fracs, sequential_heat_load_fracs,
|
17
|
+
weather_max_drybulb, weather_min_drybulb,
|
6
18
|
control_zone, hvac_unavailable_periods)
|
7
19
|
is_heatpump = false
|
8
20
|
if not cooling_system.nil?
|
@@ -45,19 +57,43 @@ class HVAC
|
|
45
57
|
fail "Unexpected cooling system type: #{cooling_system.cooling_system_type}."
|
46
58
|
end
|
47
59
|
end
|
48
|
-
clg_ap = cooling_system.additional_properties
|
49
|
-
num_speeds = clg_ap.num_speeds
|
50
60
|
elsif (heating_system.is_a? HPXML::HeatingSystem) && (heating_system.heating_system_type == HPXML::HVACTypeFurnace)
|
51
61
|
obj_name = Constants.ObjectNameFurnace
|
52
|
-
num_speeds = 1
|
53
62
|
else
|
54
63
|
fail "Unexpected heating system type: #{heating_system.heating_system_type}, expect central air source hvac systems."
|
55
64
|
end
|
56
65
|
|
66
|
+
# Calculate max rated cfm
|
67
|
+
max_rated_fan_cfm = -9999
|
68
|
+
if not cooling_system.nil?
|
69
|
+
clg_ap = cooling_system.additional_properties
|
70
|
+
if not cooling_system.cooling_detailed_performance_data.empty?
|
71
|
+
cooling_system.cooling_detailed_performance_data.select { |dp| dp.capacity_description == HPXML::CapacityDescriptionMaximum }.each do |dp|
|
72
|
+
rated_fan_cfm = UnitConversions.convert(dp.capacity, 'Btu/hr', 'ton') * clg_ap.cool_rated_cfm_per_ton[-1]
|
73
|
+
max_rated_fan_cfm = rated_fan_cfm if rated_fan_cfm > max_rated_fan_cfm
|
74
|
+
end
|
75
|
+
else
|
76
|
+
rated_fan_cfm = UnitConversions.convert(cooling_system.cooling_capacity * clg_ap.cool_capacity_ratios[-1], 'Btu/hr', 'ton') * clg_ap.cool_rated_cfm_per_ton[-1]
|
77
|
+
max_rated_fan_cfm = rated_fan_cfm if rated_fan_cfm > max_rated_fan_cfm
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if not heating_system.nil?
|
81
|
+
htg_ap = heating_system.additional_properties
|
82
|
+
if not heating_system.heating_detailed_performance_data.empty?
|
83
|
+
heating_system.heating_detailed_performance_data.select { |dp| dp.capacity_description == HPXML::CapacityDescriptionMaximum }.each do |dp|
|
84
|
+
rated_fan_cfm = UnitConversions.convert(dp.capacity, 'Btu/hr', 'ton') * htg_ap.heat_rated_cfm_per_ton[-1]
|
85
|
+
max_rated_fan_cfm = rated_fan_cfm if rated_fan_cfm > max_rated_fan_cfm
|
86
|
+
end
|
87
|
+
elsif is_heatpump
|
88
|
+
rated_fan_cfm = UnitConversions.convert(heating_system.heating_capacity * htg_ap.heat_capacity_ratios[-1], 'Btu/hr', 'ton') * htg_ap.heat_rated_cfm_per_ton[-1]
|
89
|
+
max_rated_fan_cfm = rated_fan_cfm if rated_fan_cfm > max_rated_fan_cfm
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
57
93
|
fan_cfms = []
|
58
94
|
if not cooling_system.nil?
|
59
95
|
# Cooling Coil
|
60
|
-
clg_coil = create_dx_cooling_coil(model, obj_name, cooling_system)
|
96
|
+
clg_coil = create_dx_cooling_coil(model, obj_name, cooling_system, max_rated_fan_cfm, weather_max_drybulb)
|
61
97
|
|
62
98
|
clg_cfm = cooling_system.cooling_airflow_cfm
|
63
99
|
clg_ap.cool_fan_speed_ratios.each do |r|
|
@@ -70,8 +106,8 @@ class HVAC
|
|
70
106
|
else
|
71
107
|
htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
72
108
|
htg_coil.setGasBurnerEfficiency(cooling_system.integrated_heating_system_efficiency_percent)
|
73
|
-
htg_coil.
|
74
|
-
htg_coil.
|
109
|
+
htg_coil.setOnCycleParasiticElectricLoad(0)
|
110
|
+
htg_coil.setOffCycleParasiticGasLoad(0)
|
75
111
|
htg_coil.setFuelType(EPlus.fuel_type(cooling_system.integrated_heating_system_fuel))
|
76
112
|
end
|
77
113
|
htg_coil.setNominalCapacity(UnitConversions.convert(cooling_system.integrated_heating_system_capacity, 'Btu/hr', 'W'))
|
@@ -83,13 +119,12 @@ class HVAC
|
|
83
119
|
end
|
84
120
|
|
85
121
|
if not heating_system.nil?
|
86
|
-
htg_ap = heating_system.additional_properties
|
87
122
|
htg_cfm = heating_system.heating_airflow_cfm
|
88
123
|
if is_heatpump
|
89
124
|
supp_max_temp = htg_ap.supp_max_temp
|
90
125
|
|
91
126
|
# Heating Coil
|
92
|
-
htg_coil = create_dx_heating_coil(model, obj_name, heating_system)
|
127
|
+
htg_coil = create_dx_heating_coil(model, obj_name, heating_system, max_rated_fan_cfm, weather_min_drybulb)
|
93
128
|
|
94
129
|
# Supplemental Heating Coil
|
95
130
|
htg_supp_coil = create_supp_heating_coil(model, obj_name, heating_system)
|
@@ -104,8 +139,8 @@ class HVAC
|
|
104
139
|
else
|
105
140
|
htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
106
141
|
htg_coil.setGasBurnerEfficiency(heating_system.heating_efficiency_afue)
|
107
|
-
htg_coil.
|
108
|
-
htg_coil.
|
142
|
+
htg_coil.setOnCycleParasiticElectricLoad(0)
|
143
|
+
htg_coil.setOffCycleParasiticGasLoad(UnitConversions.convert(heating_system.pilot_light_btuh.to_f, 'Btu/hr', 'W'))
|
109
144
|
htg_coil.setFuelType(EPlus.fuel_type(heating_system.heating_system_fuel))
|
110
145
|
end
|
111
146
|
htg_coil.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
|
@@ -152,10 +187,10 @@ class HVAC
|
|
152
187
|
air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, clg_cfm, supp_max_temp)
|
153
188
|
|
154
189
|
# Unitary System Performance
|
155
|
-
if
|
190
|
+
if (not clg_ap.nil?) && (clg_ap.cool_fan_speed_ratios.size > 1)
|
156
191
|
perf = OpenStudio::Model::UnitarySystemPerformanceMultispeed.new(model)
|
157
192
|
perf.setSingleModeOperation(false)
|
158
|
-
for speed in 1..
|
193
|
+
for speed in 1..clg_ap.cool_fan_speed_ratios.size
|
159
194
|
if is_heatpump
|
160
195
|
f = OpenStudio::Model::SupplyAirflowRatioField.new(htg_ap.heat_fan_speed_ratios[speed - 1], clg_ap.cool_fan_speed_ratios[speed - 1])
|
161
196
|
else
|
@@ -175,7 +210,7 @@ class HVAC
|
|
175
210
|
end
|
176
211
|
|
177
212
|
def self.apply_evaporative_cooler(model, cooling_system, sequential_cool_load_fracs, control_zone,
|
178
|
-
hvac_unavailable_periods)
|
213
|
+
hvac_unavailable_periods, unit_multiplier)
|
179
214
|
|
180
215
|
obj_name = Constants.ObjectNameEvaporativeCooler
|
181
216
|
|
@@ -196,7 +231,7 @@ class HVAC
|
|
196
231
|
air_loop = create_air_loop(model, obj_name, evap_cooler, control_zone, [0], sequential_cool_load_fracs, clg_cfm, nil, hvac_unavailable_periods)
|
197
232
|
|
198
233
|
# Fan
|
199
|
-
fan_watts_per_cfm = [2.79 * clg_cfm**-0.29, 0.6].min # W/cfm; fit of efficacy to air flow from the CEC listed equipment
|
234
|
+
fan_watts_per_cfm = [2.79 * (clg_cfm / unit_multiplier)**-0.29, 0.6].min # W/cfm; fit of efficacy to air flow from the CEC listed equipment
|
200
235
|
fan = create_supply_fan(model, obj_name, fan_watts_per_cfm, [clg_cfm])
|
201
236
|
fan.addToNode(air_loop.supplyInletNode)
|
202
237
|
disaggregate_fan_or_pump(model, fan, nil, evap_cooler, nil, cooling_system)
|
@@ -226,7 +261,14 @@ class HVAC
|
|
226
261
|
|
227
262
|
def self.apply_ground_to_air_heat_pump(model, runner, weather, heat_pump,
|
228
263
|
sequential_heat_load_fracs, sequential_cool_load_fracs,
|
229
|
-
control_zone, ground_conductivity, hvac_unavailable_periods
|
264
|
+
control_zone, ground_conductivity, hvac_unavailable_periods,
|
265
|
+
unit_multiplier)
|
266
|
+
|
267
|
+
if unit_multiplier > 1
|
268
|
+
# FUTURE: Figure out how to allow this. If we allow it, update docs and hpxml_translator_test.rb too.
|
269
|
+
# https://github.com/NREL/OpenStudio-HPXML/issues/1499
|
270
|
+
fail 'NumberofUnits greater than 1 is not supported for ground-to-air heat pumps.'
|
271
|
+
end
|
230
272
|
|
231
273
|
obj_name = Constants.ObjectNameGroundSourceHeatPump
|
232
274
|
|
@@ -241,13 +283,17 @@ class HVAC
|
|
241
283
|
runner.registerWarning("Specified #{hp_ap.fluid_type} fluid type and 0 fraction of glycol, so assuming #{Constants.FluidWater} fluid type.")
|
242
284
|
end
|
243
285
|
|
286
|
+
# Apply unit multiplier
|
287
|
+
hp_ap.GSHP_Loop_flow *= unit_multiplier
|
288
|
+
hp_ap.GSHP_Bore_Holes = hp_ap.GSHP_Bore_Holes.to_i * unit_multiplier
|
289
|
+
|
244
290
|
# Cooling Coil
|
245
291
|
clg_total_cap_curve = create_curve_quad_linear(model, hp_ap.cool_cap_curve_spec[0], obj_name + ' clg total cap curve')
|
246
292
|
clg_sens_cap_curve = create_curve_quint_linear(model, hp_ap.cool_sh_curve_spec[0], obj_name + ' clg sens cap curve')
|
247
293
|
clg_power_curve = create_curve_quad_linear(model, hp_ap.cool_power_curve_spec[0], obj_name + ' clg power curve')
|
248
294
|
clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model, clg_total_cap_curve, clg_sens_cap_curve, clg_power_curve)
|
249
295
|
clg_coil.setName(obj_name + ' clg coil')
|
250
|
-
clg_coil.setRatedCoolingCoefficientofPerformance(
|
296
|
+
clg_coil.setRatedCoolingCoefficientofPerformance(hp_ap.cool_rated_cops[0])
|
251
297
|
clg_coil.setNominalTimeforCondensateRemovaltoBegin(1000)
|
252
298
|
clg_coil.setRatioofInitialMoistureEvaporationRateandSteadyStateLatentCapacity(1.5)
|
253
299
|
clg_coil.setRatedAirFlowRate(UnitConversions.convert(clg_cfm_rated, 'cfm', 'm^3/s'))
|
@@ -261,7 +307,7 @@ class HVAC
|
|
261
307
|
htg_power_curve = create_curve_quad_linear(model, hp_ap.heat_power_curve_spec[0], obj_name + ' htg power curve')
|
262
308
|
htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model, htg_cap_curve, htg_power_curve)
|
263
309
|
htg_coil.setName(obj_name + ' htg coil')
|
264
|
-
htg_coil.setRatedHeatingCoefficientofPerformance(
|
310
|
+
htg_coil.setRatedHeatingCoefficientofPerformance(hp_ap.heat_rated_cops[0])
|
265
311
|
htg_coil.setRatedAirFlowRate(UnitConversions.convert(htg_cfm_rated, 'cfm', 'm^3/s'))
|
266
312
|
htg_coil.setRatedWaterFlowRate(UnitConversions.convert(hp_ap.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
|
267
313
|
htg_coil.setRatedHeatingCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
|
@@ -270,13 +316,20 @@ class HVAC
|
|
270
316
|
# Supplemental Heating Coil
|
271
317
|
htg_supp_coil = create_supp_heating_coil(model, obj_name, heat_pump)
|
272
318
|
|
319
|
+
# Site Ground Temperature Undisturbed
|
320
|
+
xing = OpenStudio::Model::SiteGroundTemperatureUndisturbedXing.new(model)
|
321
|
+
xing.setSoilSurfaceTemperatureAmplitude1(UnitConversions.convert(weather.data.DeepGroundSurfTempAmp1, 'deltaf', 'deltac'))
|
322
|
+
xing.setSoilSurfaceTemperatureAmplitude2(UnitConversions.convert(weather.data.DeepGroundSurfTempAmp2, 'deltaf', 'deltac'))
|
323
|
+
xing.setPhaseShiftofTemperatureAmplitude1(weather.data.DeepGroundPhaseShiftTempAmp1)
|
324
|
+
xing.setPhaseShiftofTemperatureAmplitude2(weather.data.DeepGroundPhaseShiftTempAmp2)
|
325
|
+
|
273
326
|
# Ground Heat Exchanger
|
274
|
-
ground_heat_exch_vert = OpenStudio::Model::GroundHeatExchangerVertical.new(model)
|
327
|
+
ground_heat_exch_vert = OpenStudio::Model::GroundHeatExchangerVertical.new(model, xing)
|
275
328
|
ground_heat_exch_vert.setName(obj_name + ' exchanger')
|
276
329
|
ground_heat_exch_vert.setBoreHoleRadius(UnitConversions.convert(hp_ap.bore_diameter / 2.0, 'in', 'm'))
|
277
330
|
ground_heat_exch_vert.setGroundThermalConductivity(UnitConversions.convert(ground_conductivity, 'Btu/(hr*ft*R)', 'W/(m*K)'))
|
278
331
|
ground_heat_exch_vert.setGroundThermalHeatCapacity(UnitConversions.convert(ground_conductivity / hp_ap.ground_diffusivity, 'Btu/(ft^3*F)', 'J/(m^3*K)'))
|
279
|
-
ground_heat_exch_vert.setGroundTemperature(UnitConversions.convert(weather.data.
|
332
|
+
ground_heat_exch_vert.setGroundTemperature(UnitConversions.convert(weather.data.DeepGroundAnnualTemp, 'F', 'C'))
|
280
333
|
ground_heat_exch_vert.setGroutThermalConductivity(UnitConversions.convert(hp_ap.grout_conductivity, 'Btu/(hr*ft*R)', 'W/(m*K)'))
|
281
334
|
ground_heat_exch_vert.setPipeThermalConductivity(UnitConversions.convert(hp_ap.pipe_cond, 'Btu/(hr*ft*R)', 'W/(m*K)'))
|
282
335
|
ground_heat_exch_vert.setPipeOutDiameter(UnitConversions.convert(hp_ap.pipe_od, 'in', 'm'))
|
@@ -285,12 +338,16 @@ class HVAC
|
|
285
338
|
ground_heat_exch_vert.setMaximumLengthofSimulation(1)
|
286
339
|
ground_heat_exch_vert.setGFunctionReferenceRatio(0.0005)
|
287
340
|
ground_heat_exch_vert.setDesignFlowRate(UnitConversions.convert(hp_ap.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
|
288
|
-
ground_heat_exch_vert.setNumberofBoreHoles(hp_ap.GSHP_Bore_Holes
|
341
|
+
ground_heat_exch_vert.setNumberofBoreHoles(hp_ap.GSHP_Bore_Holes)
|
289
342
|
ground_heat_exch_vert.setBoreHoleLength(UnitConversions.convert(hp_ap.GSHP_Bore_Depth, 'ft', 'm'))
|
290
343
|
ground_heat_exch_vert.removeAllGFunctions
|
291
344
|
for i in 0..(hp_ap.GSHP_G_Functions[0].size - 1)
|
292
345
|
ground_heat_exch_vert.addGFunction(hp_ap.GSHP_G_Functions[0][i], hp_ap.GSHP_G_Functions[1][i])
|
293
346
|
end
|
347
|
+
xing = ground_heat_exch_vert.undisturbedGroundTemperatureModel.to_SiteGroundTemperatureUndisturbedXing.get
|
348
|
+
xing.setSoilThermalConductivity(ground_heat_exch_vert.groundThermalConductivity.get)
|
349
|
+
xing.setSoilSpecificHeat(ground_heat_exch_vert.groundThermalHeatCapacity.get / xing.soilDensity)
|
350
|
+
xing.setAverageSoilSurfaceTemperature(ground_heat_exch_vert.groundTemperature.get)
|
294
351
|
|
295
352
|
# Plant Loop
|
296
353
|
plant_loop = OpenStudio::Model::PlantLoop.new(model)
|
@@ -379,7 +436,7 @@ class HVAC
|
|
379
436
|
equip_def.setFractionLatent(0)
|
380
437
|
equip_def.setFractionLost(1)
|
381
438
|
equip.setSchedule(model.alwaysOnDiscreteSchedule)
|
382
|
-
equip.setEndUseSubcategory(
|
439
|
+
equip.setEndUseSubcategory(Constants.ObjectNameGSHPSharedPump)
|
383
440
|
equip.additionalProperties.setFeature('HPXML_ID', heat_pump.id) # Used by reporting measure
|
384
441
|
end
|
385
442
|
|
@@ -437,8 +494,7 @@ class HVAC
|
|
437
494
|
return air_loop
|
438
495
|
end
|
439
496
|
|
440
|
-
def self.apply_boiler(model, runner, heating_system,
|
441
|
-
sequential_heat_load_fracs, control_zone, hvac_unavailable_periods)
|
497
|
+
def self.apply_boiler(model, runner, heating_system, sequential_heat_load_fracs, control_zone, hvac_unavailable_periods)
|
442
498
|
obj_name = Constants.ObjectNameBoiler
|
443
499
|
is_condensing = false # FUTURE: Expose as input; default based on AFUE
|
444
500
|
oat_reset_enabled = false
|
@@ -514,16 +570,14 @@ class HVAC
|
|
514
570
|
boiler.setBoilerFlowMode('LeavingSetpointModulated')
|
515
571
|
boiler.setOptimumPartLoadRatio(1.0)
|
516
572
|
boiler.setWaterOutletUpperTemperatureLimit(99.9)
|
517
|
-
boiler.
|
573
|
+
boiler.setOnCycleParasiticElectricLoad(0)
|
518
574
|
boiler.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
|
575
|
+
boiler.setOffCycleParasiticFuelLoad(UnitConversions.convert(heating_system.pilot_light_btuh.to_f, 'Btu/hr', 'W'))
|
519
576
|
plant_loop.addSupplyBranchForComponent(boiler)
|
520
577
|
boiler.additionalProperties.setFeature('HPXML_ID', heating_system.id) # Used by reporting measure
|
578
|
+
boiler.additionalProperties.setFeature('IsHeatPumpBackup', heating_system.is_heat_pump_backup_system) # Used by reporting measure
|
521
579
|
set_pump_power_ems_program(model, pump_w, pump, boiler)
|
522
580
|
|
523
|
-
# FIXME: EMS program to model pilot light
|
524
|
-
# Can be replaced if https://github.com/NREL/EnergyPlus/issues/9875 is ever implemented
|
525
|
-
set_boiler_pilot_light_ems_program(model, boiler, heating_system)
|
526
|
-
|
527
581
|
if is_condensing && oat_reset_enabled
|
528
582
|
setpoint_manager_oar = OpenStudio::Model::SetpointManagerOutdoorAirReset.new(model)
|
529
583
|
setpoint_manager_oar.setName(obj_name + ' outdoor reset')
|
@@ -657,8 +711,8 @@ class HVAC
|
|
657
711
|
else
|
658
712
|
htg_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
659
713
|
htg_coil.setGasBurnerEfficiency(efficiency)
|
660
|
-
htg_coil.
|
661
|
-
htg_coil.
|
714
|
+
htg_coil.setOnCycleParasiticElectricLoad(0.0)
|
715
|
+
htg_coil.setOffCycleParasiticGasLoad(UnitConversions.convert(heating_system.pilot_light_btuh.to_f, 'Btu/hr', 'W'))
|
662
716
|
htg_coil.setFuelType(EPlus.fuel_type(heating_system.heating_system_fuel))
|
663
717
|
end
|
664
718
|
htg_coil.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
|
@@ -680,9 +734,11 @@ class HVAC
|
|
680
734
|
set_sequential_load_fractions(model, control_zone, unitary_system, sequential_heat_load_fracs, nil, hvac_unavailable_periods, heating_system)
|
681
735
|
end
|
682
736
|
|
683
|
-
def self.apply_ideal_air_loads(model,
|
737
|
+
def self.apply_ideal_air_loads(model, sequential_cool_load_fracs,
|
684
738
|
sequential_heat_load_fracs, control_zone, hvac_unavailable_periods)
|
685
739
|
|
740
|
+
obj_name = Constants.ObjectNameIdealAirSystem
|
741
|
+
|
686
742
|
# Ideal Air System
|
687
743
|
ideal_air = OpenStudio::Model::ZoneHVACIdealLoadsAirSystem.new(model)
|
688
744
|
ideal_air.setName(obj_name)
|
@@ -709,13 +765,19 @@ class HVAC
|
|
709
765
|
set_sequential_load_fractions(model, control_zone, ideal_air, sequential_heat_load_fracs, sequential_cool_load_fracs, hvac_unavailable_periods)
|
710
766
|
end
|
711
767
|
|
712
|
-
def self.apply_dehumidifiers(runner, model, dehumidifiers,
|
768
|
+
def self.apply_dehumidifiers(runner, model, dehumidifiers, conditioned_space, unavailable_periods, unit_multiplier)
|
713
769
|
dehumidifier_id = dehumidifiers[0].id # Syncs with the ReportSimulationOutput measure, which only looks at first dehumidifier ID
|
714
770
|
|
715
771
|
if dehumidifiers.map { |d| d.rh_setpoint }.uniq.size > 1
|
716
772
|
fail 'All dehumidifiers must have the same setpoint but multiple setpoints were specified.'
|
717
773
|
end
|
718
774
|
|
775
|
+
if unit_multiplier > 1
|
776
|
+
# FUTURE: Figure out how to allow this. If we allow it, update docs and hpxml_translator_test.rb too.
|
777
|
+
# https://github.com/NREL/OpenStudio-HPXML/issues/1499
|
778
|
+
fail 'NumberofUnits greater than 1 is not supported for dehumidifiers.'
|
779
|
+
end
|
780
|
+
|
719
781
|
# Dehumidifier coefficients
|
720
782
|
# Generic model coefficients from Winkler, Christensen, and Tomerlin (2011)
|
721
783
|
w_coeff = [-1.162525707, 0.02271469, -0.000113208, 0.021110538, -0.0000693034, 0.000378843]
|
@@ -733,12 +795,15 @@ class HVAC
|
|
733
795
|
avg_energy_factor = dehumidifiers.map { |d| d.energy_factor * d.capacity }.sum / total_capacity
|
734
796
|
total_fraction_served = dehumidifiers.map { |d| d.fraction_served }.sum
|
735
797
|
|
736
|
-
|
798
|
+
# Apply unit multiplier
|
799
|
+
total_capacity *= unit_multiplier
|
800
|
+
|
801
|
+
control_zone = conditioned_space.thermalZone.get
|
737
802
|
obj_name = Constants.ObjectNameDehumidifier
|
738
803
|
|
739
804
|
rh_setpoint = dehumidifiers[0].rh_setpoint * 100.0 # (EnergyPlus uses 60 for 60% RH)
|
740
805
|
relative_humidity_setpoint_sch = OpenStudio::Model::ScheduleConstant.new(model)
|
741
|
-
relative_humidity_setpoint_sch.setName(
|
806
|
+
relative_humidity_setpoint_sch.setName("#{obj_name} rh setpoint")
|
742
807
|
relative_humidity_setpoint_sch.setValue(rh_setpoint)
|
743
808
|
|
744
809
|
capacity_curve = create_curve_biquadratic(model, w_coeff, 'DXDH-CAP-fT', -100, 100, -100, 100)
|
@@ -773,11 +838,11 @@ class HVAC
|
|
773
838
|
zone_hvac.additionalProperties.setFeature('HPXML_ID', dehumidifier_id) # Used by reporting measure
|
774
839
|
|
775
840
|
if total_fraction_served < 1.0
|
776
|
-
adjust_dehumidifier_load_EMS(total_fraction_served, zone_hvac, model,
|
841
|
+
adjust_dehumidifier_load_EMS(total_fraction_served, zone_hvac, model, conditioned_space)
|
777
842
|
end
|
778
843
|
end
|
779
844
|
|
780
|
-
def self.apply_ceiling_fans(model, runner, weather, ceiling_fan,
|
845
|
+
def self.apply_ceiling_fans(model, runner, weather, ceiling_fan, conditioned_space, schedules_file,
|
781
846
|
unavailable_periods)
|
782
847
|
obj_name = Constants.ObjectNameCeilingFan
|
783
848
|
medium_cfm = 3000.0 # From ANSI 301-2019
|
@@ -792,7 +857,7 @@ class HVAC
|
|
792
857
|
if not schedules_file.nil?
|
793
858
|
annual_kwh *= Schedule.CeilingFanMonthlyMultipliers(weather: weather).split(',').map(&:to_f).sum(0.0) / 12.0
|
794
859
|
ceiling_fan_design_level = schedules_file.calc_design_level_from_annual_kwh(col_name: ceiling_fan_col_name, annual_kwh: annual_kwh)
|
795
|
-
ceiling_fan_sch = schedules_file.create_schedule_file(col_name: ceiling_fan_col_name)
|
860
|
+
ceiling_fan_sch = schedules_file.create_schedule_file(model, col_name: ceiling_fan_col_name)
|
796
861
|
end
|
797
862
|
if ceiling_fan_sch.nil?
|
798
863
|
ceiling_fan_unavailable_periods = Schedule.get_unavailable_periods(runner, ceiling_fan_col_name, unavailable_periods)
|
@@ -813,7 +878,7 @@ class HVAC
|
|
813
878
|
equip_def.setName(obj_name)
|
814
879
|
equip = OpenStudio::Model::ElectricEquipment.new(equip_def)
|
815
880
|
equip.setName(equip_def.name.to_s)
|
816
|
-
equip.setSpace(
|
881
|
+
equip.setSpace(conditioned_space)
|
817
882
|
equip_def.setDesignLevel(ceiling_fan_design_level)
|
818
883
|
equip_def.setFractionRadiant(0.558)
|
819
884
|
equip_def.setFractionLatent(0)
|
@@ -822,14 +887,14 @@ class HVAC
|
|
822
887
|
equip.setSchedule(ceiling_fan_sch)
|
823
888
|
end
|
824
889
|
|
825
|
-
def self.apply_setpoints(model, runner, weather, hvac_control,
|
890
|
+
def self.apply_setpoints(model, runner, weather, hvac_control, conditioned_zone, has_ceiling_fan, heating_days, cooling_days, year, schedules_file)
|
826
891
|
heating_sch = nil
|
827
892
|
cooling_sch = nil
|
828
893
|
if not schedules_file.nil?
|
829
|
-
heating_sch = schedules_file.create_schedule_file(col_name: SchedulesFile::ColumnHeatingSetpoint)
|
894
|
+
heating_sch = schedules_file.create_schedule_file(model, col_name: SchedulesFile::ColumnHeatingSetpoint)
|
830
895
|
end
|
831
896
|
if not schedules_file.nil?
|
832
|
-
cooling_sch = schedules_file.create_schedule_file(col_name: SchedulesFile::ColumnCoolingSetpoint)
|
897
|
+
cooling_sch = schedules_file.create_schedule_file(model, col_name: SchedulesFile::ColumnCoolingSetpoint)
|
833
898
|
end
|
834
899
|
|
835
900
|
# permit mixing detailed schedules with simple schedules
|
@@ -851,21 +916,21 @@ class HVAC
|
|
851
916
|
end
|
852
917
|
|
853
918
|
if heating_sch.nil?
|
854
|
-
heating_setpoint = HourlyByDaySchedule.new(model,
|
919
|
+
heating_setpoint = HourlyByDaySchedule.new(model, 'heating setpoint', htg_weekday_setpoints, htg_weekend_setpoints, nil, false)
|
855
920
|
heating_sch = heating_setpoint.schedule
|
856
921
|
end
|
857
922
|
|
858
923
|
if cooling_sch.nil?
|
859
|
-
cooling_setpoint = HourlyByDaySchedule.new(model,
|
924
|
+
cooling_setpoint = HourlyByDaySchedule.new(model, 'cooling setpoint', clg_weekday_setpoints, clg_weekend_setpoints, nil, false)
|
860
925
|
cooling_sch = cooling_setpoint.schedule
|
861
926
|
end
|
862
927
|
|
863
928
|
# Set the setpoint schedules
|
864
929
|
thermostat_setpoint = OpenStudio::Model::ThermostatSetpointDualSetpoint.new(model)
|
865
|
-
thermostat_setpoint.setName("#{
|
930
|
+
thermostat_setpoint.setName("#{conditioned_zone.name} temperature setpoint")
|
866
931
|
thermostat_setpoint.setHeatingSetpointTemperatureSchedule(heating_sch)
|
867
932
|
thermostat_setpoint.setCoolingSetpointTemperatureSchedule(cooling_sch)
|
868
|
-
|
933
|
+
conditioned_zone.setThermostatSetpointDualSetpoint(thermostat_setpoint)
|
869
934
|
end
|
870
935
|
|
871
936
|
def self.create_setpoint_schedules(runner, heating_days, cooling_days, htg_weekday_setpoints, htg_weekend_setpoints, clg_weekday_setpoints, clg_weekend_setpoints, year)
|
@@ -1024,189 +1089,357 @@ class HVAC
|
|
1024
1089
|
return clg_sp, clg_setup_sp, clg_setup_hrs_per_week, clg_setup_start_hr
|
1025
1090
|
end
|
1026
1091
|
|
1027
|
-
def self.
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1092
|
+
def self.get_default_heating_capacity_retention(compressor_type, hspf = nil)
|
1093
|
+
retention_temp = 5.0
|
1094
|
+
if [HPXML::HVACCompressorTypeSingleStage, HPXML::HVACCompressorTypeTwoStage].include? compressor_type
|
1095
|
+
retention_fraction = 0.425
|
1096
|
+
elsif [HPXML::HVACCompressorTypeVariableSpeed].include? compressor_type
|
1097
|
+
# Default maximum capacity maintenance based on NEEP data for all var speed heat pump types, if not provided
|
1098
|
+
retention_fraction = (0.0461 * hspf + 0.1594).round(4)
|
1099
|
+
end
|
1100
|
+
return retention_temp, retention_fraction
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
def self.get_cool_cap_eir_ft_spec(compressor_type)
|
1104
|
+
if compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1105
|
+
cap_ft_spec = [[3.68637657, -0.098352478, 0.000956357, 0.005838141, -0.0000127, -0.000131702]]
|
1106
|
+
eir_ft_spec = [[-3.437356399, 0.136656369, -0.001049231, -0.0079378, 0.000185435, -0.0001441]]
|
1107
|
+
elsif compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1108
|
+
cap_ft_spec = [[3.998418659, -0.108728222, 0.001056818, 0.007512314, -0.0000139, -0.000164716],
|
1109
|
+
[3.466810106, -0.091476056, 0.000901205, 0.004163355, -0.00000919, -0.000110829]]
|
1110
|
+
eir_ft_spec = [[-4.282911381, 0.181023691, -0.001357391, -0.026310378, 0.000333282, -0.000197405],
|
1111
|
+
[-3.557757517, 0.112737397, -0.000731381, 0.013184877, 0.000132645, -0.000338716]]
|
1112
|
+
end
|
1113
|
+
return cap_ft_spec, eir_ft_spec
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
def self.get_cool_cap_eir_fflow_spec(compressor_type)
|
1117
|
+
if compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1118
|
+
# Single stage systems have PSC or constant torque ECM blowers, so the airflow rate is affected by the static pressure losses.
|
1119
|
+
cap_fflow_spec = [[0.718664047, 0.41797409, -0.136638137]]
|
1120
|
+
eir_fflow_spec = [[1.143487507, -0.13943972, -0.004047787]]
|
1121
|
+
elsif compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1122
|
+
# Most two stage systems have PSC or constant torque ECM blowers, so the airflow rate is affected by the static pressure losses.
|
1123
|
+
cap_fflow_spec = [[0.655239515, 0.511655216, -0.166894731],
|
1124
|
+
[0.618281092, 0.569060264, -0.187341356]]
|
1125
|
+
eir_fflow_spec = [[1.639108268, -0.998953996, 0.359845728],
|
1126
|
+
[1.570774717, -0.914152018, 0.343377302]]
|
1127
|
+
elsif compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1128
|
+
# Variable speed systems have constant flow ECM blowers, so the air handler can always achieve the design airflow rate by sacrificing blower power.
|
1129
|
+
# So we assume that there is only one corresponding airflow rate for each compressor speed.
|
1130
|
+
eir_fflow_spec = [[1, 0, 0]] * 2
|
1131
|
+
cap_fflow_spec = [[1, 0, 0]] * 2
|
1132
|
+
end
|
1133
|
+
return cap_fflow_spec, eir_fflow_spec
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
def self.get_heat_cap_eir_ft_spec(compressor_type, heating_capacity_retention_temp, heating_capacity_retention_fraction)
|
1137
|
+
cap_ft_spec = calc_heat_cap_ft_spec(compressor_type, heating_capacity_retention_temp, heating_capacity_retention_fraction)
|
1138
|
+
if compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1139
|
+
# From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler et al
|
1032
1140
|
# https://www.nrel.gov/docs/fy13osti/56354.pdf
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
if not use_eer
|
1037
|
-
hp_ap.cool_rated_airflow_rate = hp_ap.cool_rated_cfm_per_ton[0]
|
1038
|
-
hp_ap.cool_fan_speed_ratios = calc_fan_speed_ratios(hp_ap.cool_capacity_ratios, hp_ap.cool_rated_cfm_per_ton, hp_ap.cool_rated_airflow_rate)
|
1039
|
-
# Single stage systems have PSC or constant torque ECM blowers, so the airflow rate is affected by the static pressure losses.
|
1040
|
-
cap_fflow_spec, eir_fflow_spec = get_airflow_fault_cooling_coeff()
|
1041
|
-
hp_ap.cool_cap_fflow_spec = [cap_fflow_spec]
|
1042
|
-
hp_ap.cool_eir_fflow_spec = [eir_fflow_spec]
|
1043
|
-
hp_ap.cool_eers = [calc_eer_cooling_1speed(heat_pump.cooling_efficiency_seer, hp_ap.cool_c_d, hp_ap.fan_power_rated, hp_ap.cool_eir_ft_spec)]
|
1044
|
-
else
|
1045
|
-
hp_ap.cool_fan_speed_ratios = [1.0]
|
1046
|
-
hp_ap.cool_cap_fflow_spec = [[1.0, 0.0, 0.0]]
|
1047
|
-
hp_ap.cool_eir_fflow_spec = [[1.0, 0.0, 0.0]]
|
1048
|
-
end
|
1049
|
-
elsif hp_ap.num_speeds == 2
|
1050
|
-
# From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler at al
|
1141
|
+
eir_ft_spec = [[0.718398423, 0.003498178, 0.000142202, -0.005724331, 0.00014085, -0.000215321]]
|
1142
|
+
elsif compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1143
|
+
# From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler et al
|
1051
1144
|
# https://www.nrel.gov/docs/fy13osti/56354.pdf
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1145
|
+
eir_ft_spec = [[0.36338171, 0.013523725, 0.000258872, -0.009450269, 0.000439519, -0.000653723],
|
1146
|
+
[0.981100941, -0.005158493, 0.000243416, -0.005274352, 0.000230742, -0.000336954]]
|
1147
|
+
end
|
1148
|
+
return cap_ft_spec, eir_ft_spec
|
1149
|
+
end
|
1150
|
+
|
1151
|
+
def self.get_heat_cap_eir_fflow_spec(compressor_type)
|
1152
|
+
if compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1153
|
+
# Single stage systems have PSC or constant torque ECM blowers, so the airflow rate is affected by the static pressure losses.
|
1154
|
+
cap_fflow_spec = [[0.694045465, 0.474207981, -0.168253446]]
|
1155
|
+
eir_fflow_spec = [[2.185418751, -1.942827919, 0.757409168]]
|
1156
|
+
elsif compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1059
1157
|
# Most two stage systems have PSC or constant torque ECM blowers, so the airflow rate is affected by the static pressure losses.
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
elsif hp_ap.num_speeds == 4
|
1066
|
-
# From Carrier heat pump lab testing
|
1067
|
-
hp_ap.cool_rated_airflow_rate = hp_ap.cool_rated_cfm_per_ton[-1]
|
1068
|
-
hp_ap.cool_capacity_ratios = [0.36, 0.51, 0.67, 1.0]
|
1069
|
-
hp_ap.cool_fan_speed_ratios = calc_fan_speed_ratios(hp_ap.cool_capacity_ratios, hp_ap.cool_rated_cfm_per_ton, hp_ap.cool_rated_airflow_rate)
|
1070
|
-
hp_ap.cool_cap_coeff_perf_map = [[1.6516044444444447, 0.0698916049382716, -0.0005546296296296296, -0.08870160493827162, 0.0004135802469135802, 0.00029077160493827157],
|
1071
|
-
[-6.84948049382716, 0.26946, -0.0019413580246913577, -0.03281469135802469, 0.00015694444444444442, 3.32716049382716e-05],
|
1072
|
-
[-4.53543086419753, 0.15358543209876546, -0.0009345679012345678, 0.002666913580246914, -7.993827160493826e-06, -0.00011617283950617283],
|
1073
|
-
[-3.500948395061729, 0.11738987654320988, -0.0006580246913580248, 0.007003148148148148, -2.8518518518518517e-05, -0.0001284259259259259],
|
1074
|
-
[1.8769221728395058, -0.04768641975308643, 0.0006885802469135801, 0.006643395061728395, 1.4209876543209876e-05, -0.00024043209876543206]]
|
1075
|
-
hp_ap.cool_cap_ft_spec = hp_ap.cool_cap_coeff_perf_map.select { |i| [0, 1, 2, 4].include? hp_ap.cool_cap_coeff_perf_map.index(i) }
|
1076
|
-
hp_ap.cool_cap_ft_spec_3 = hp_ap.cool_cap_coeff_perf_map.select { |i| [0, 1, 4].include? hp_ap.cool_cap_coeff_perf_map.index(i) }
|
1077
|
-
hp_ap.cool_eir_coeff_perf_map = [[2.896298765432099, -0.12487654320987657, 0.0012148148148148148, 0.04492037037037037, 8.734567901234567e-05, -0.0006348765432098764],
|
1078
|
-
[6.428076543209876, -0.20913209876543212, 0.0018521604938271604, 0.024392592592592594, 0.00019691358024691356, -0.0006012345679012346],
|
1079
|
-
[5.136356049382716, -0.1591530864197531, 0.0014151234567901232, 0.018665555555555557, 0.00020398148148148147, -0.0005407407407407407],
|
1080
|
-
[1.3823471604938273, -0.02875123456790123, 0.00038302469135802463, 0.006344814814814816, 0.00024836419753086417, -0.00047469135802469134],
|
1081
|
-
[-1.0411735802469133, 0.055261604938271605, -0.0004404320987654321, 0.0002154938271604939, 0.00017484567901234564, -0.0002017901234567901]]
|
1082
|
-
hp_ap.cool_eir_ft_spec = hp_ap.cool_eir_coeff_perf_map.select { |i| [0, 1, 2, 4].include? hp_ap.cool_eir_coeff_perf_map.index(i) }
|
1083
|
-
hp_ap.cool_eir_ft_spec_3 = hp_ap.cool_eir_coeff_perf_map.select { |i| [0, 1, 4].include? hp_ap.cool_eir_coeff_perf_map.index(i) }
|
1158
|
+
cap_fflow_spec = [[0.741466907, 0.378645444, -0.119754733],
|
1159
|
+
[0.76634609, 0.32840943, -0.094701495]]
|
1160
|
+
eir_fflow_spec = [[2.153618211, -1.737190609, 0.584269478],
|
1161
|
+
[2.001041353, -1.58869128, 0.587593517]]
|
1162
|
+
elsif compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1084
1163
|
# Variable speed systems have constant flow ECM blowers, so the air handler can always achieve the design airflow rate by sacrificing blower power.
|
1085
1164
|
# So we assume that there is only one corresponding airflow rate for each compressor speed.
|
1086
|
-
|
1087
|
-
|
1088
|
-
hp_ap.cap_ratio_seer_3 = hp_ap.cool_capacity_ratios.select { |i| [0, 1, 3].include? hp_ap.cool_capacity_ratios.index(i) }
|
1089
|
-
hp_ap.fan_speed_seer_3 = hp_ap.cool_fan_speed_ratios.select { |i| [0, 1, 3].include? hp_ap.cool_fan_speed_ratios.index(i) }
|
1090
|
-
hp_ap.cool_eers = calc_eers_cooling_4speed(heat_pump.cooling_efficiency_seer, hp_ap.cool_c_d, hp_ap.cap_ratio_seer_3, hp_ap.fan_speed_seer_3, hp_ap.fan_power_rated, hp_ap.cool_eir_ft_spec_3, hp_ap.cool_cap_ft_spec_3)
|
1165
|
+
cap_fflow_spec = [[1, 0, 0]] * 3
|
1166
|
+
eir_fflow_spec = [[1, 0, 0]] * 3
|
1091
1167
|
end
|
1168
|
+
return cap_fflow_spec, eir_fflow_spec
|
1092
1169
|
end
|
1093
1170
|
|
1094
|
-
def self.
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
hp_ap.heat_rated_airflow_rate = hp_ap.heat_rated_cfm_per_ton[0]
|
1109
|
-
hp_ap.heat_fan_speed_ratios = calc_fan_speed_ratios(hp_ap.heat_capacity_ratios, hp_ap.heat_rated_cfm_per_ton, hp_ap.heat_rated_airflow_rate)
|
1171
|
+
def self.set_cool_curves_central_air_source(runner, cooling_system, use_eer = false)
|
1172
|
+
clg_ap = cooling_system.additional_properties
|
1173
|
+
clg_ap.cool_rated_cfm_per_ton = get_default_cool_cfm_per_ton(cooling_system.compressor_type, use_eer)
|
1174
|
+
clg_ap.cool_capacity_ratios = get_cool_capacity_ratios(cooling_system)
|
1175
|
+
set_cool_c_d(cooling_system)
|
1176
|
+
|
1177
|
+
seer = cooling_system.cooling_efficiency_seer
|
1178
|
+
if cooling_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1179
|
+
clg_ap.cool_cap_ft_spec, clg_ap.cool_eir_ft_spec = get_cool_cap_eir_ft_spec(cooling_system.compressor_type)
|
1180
|
+
if not use_eer
|
1181
|
+
clg_ap.cool_rated_airflow_rate = clg_ap.cool_rated_cfm_per_ton[0]
|
1182
|
+
clg_ap.cool_fan_speed_ratios = calc_fan_speed_ratios(clg_ap.cool_capacity_ratios, clg_ap.cool_rated_cfm_per_ton, clg_ap.cool_rated_airflow_rate)
|
1183
|
+
clg_ap.cool_cap_fflow_spec, clg_ap.cool_eir_fflow_spec = get_cool_cap_eir_fflow_spec(cooling_system.compressor_type)
|
1184
|
+
clg_ap.cool_rated_cops = [0.2692 * seer + 0.2706] # Regression based on inverse model
|
1110
1185
|
else
|
1111
|
-
|
1186
|
+
clg_ap.cool_fan_speed_ratios = [1.0]
|
1187
|
+
clg_ap.cool_cap_fflow_spec = [[1.0, 0.0, 0.0]]
|
1188
|
+
clg_ap.cool_eir_fflow_spec = [[1.0, 0.0, 0.0]]
|
1112
1189
|
end
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
# From manufacturers data
|
1129
|
-
hp_ap.heat_rated_airflow_rate = hp_ap.heat_rated_cfm_per_ton[-2]
|
1130
|
-
hp_ap.heat_capacity_ratios = [0.33, 0.56, 1.0, 1.17]
|
1131
|
-
hp_ap.heat_fan_speed_ratios = calc_fan_speed_ratios(hp_ap.heat_capacity_ratios, hp_ap.heat_rated_cfm_per_ton, hp_ap.heat_rated_airflow_rate)
|
1132
|
-
hp_ap.heat_eir_ft_spec = [[0.708311527, 0.020732093, 0.000391479, -0.037640031, 0.000979937, -0.001079042],
|
1133
|
-
[0.025480155, 0.020169585, 0.000121341, -0.004429789, 0.000166472, -0.00036447],
|
1134
|
-
[0.379003189, 0.014195012, 0.0000821046, -0.008894061, 0.000151519, -0.000210299],
|
1135
|
-
[0.690404655, 0.00616619, 0.000137643, -0.009350199, 0.000153427, -0.000213258]]
|
1136
|
-
hp_ap.heat_cap_fflow_spec = [[1, 0, 0]] * 4
|
1137
|
-
hp_ap.heat_eir_fflow_spec = [[1, 0, 0]] * 4
|
1138
|
-
hp_ap.heat_cap_ft_spec = calc_heat_cap_ft_spec(heat_pump, heat_pump.additional_properties.num_speeds)
|
1139
|
-
hp_ap.heat_cops = calc_cops_heating_4speed(heat_pump.heating_efficiency_hspf, hp_ap.heat_c_d, hp_ap.heat_capacity_ratios, hp_ap.heat_fan_speed_ratios, hp_ap.fan_power_rated, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)
|
1190
|
+
|
1191
|
+
elsif cooling_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1192
|
+
clg_ap.cool_rated_airflow_rate = clg_ap.cool_rated_cfm_per_ton[-1]
|
1193
|
+
clg_ap.cool_fan_speed_ratios = calc_fan_speed_ratios(clg_ap.cool_capacity_ratios, clg_ap.cool_rated_cfm_per_ton, clg_ap.cool_rated_airflow_rate)
|
1194
|
+
clg_ap.cool_cap_ft_spec, clg_ap.cool_eir_ft_spec = get_cool_cap_eir_ft_spec(cooling_system.compressor_type)
|
1195
|
+
clg_ap.cool_cap_fflow_spec, clg_ap.cool_eir_fflow_spec = get_cool_cap_eir_fflow_spec(cooling_system.compressor_type)
|
1196
|
+
clg_ap.cool_rated_cops = [0.2773 * seer - 0.0018] # Regression based on inverse model
|
1197
|
+
clg_ap.cool_rated_cops << clg_ap.cool_rated_cops[0] * 0.91 # COP ratio based on Dylan's data as seen in BEopt 2.8 options
|
1198
|
+
|
1199
|
+
elsif cooling_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1200
|
+
clg_ap.cooling_capacity_retention_temperature = 82.0
|
1201
|
+
clg_ap.cooling_capacity_retention_fraction = 1.033 # From NEEP data
|
1202
|
+
clg_ap.cool_rated_airflow_rate = clg_ap.cool_rated_cfm_per_ton[-1]
|
1203
|
+
clg_ap.cool_fan_speed_ratios = calc_fan_speed_ratios(clg_ap.cool_capacity_ratios, clg_ap.cool_rated_cfm_per_ton, clg_ap.cool_rated_airflow_rate)
|
1204
|
+
clg_ap.cool_cap_fflow_spec, clg_ap.cool_eir_fflow_spec = get_cool_cap_eir_fflow_spec(cooling_system.compressor_type)
|
1140
1205
|
end
|
1206
|
+
|
1207
|
+
set_cool_rated_shrs_gross(runner, cooling_system)
|
1141
1208
|
end
|
1142
1209
|
|
1143
|
-
def self.
|
1144
|
-
|
1210
|
+
def self.get_cool_capacity_ratios(hvac_system)
|
1211
|
+
# For each speed, ratio of capacity to nominal capacity
|
1212
|
+
if hvac_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1213
|
+
return [1.0]
|
1214
|
+
elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1215
|
+
return [0.72, 1.0]
|
1216
|
+
elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1217
|
+
is_ducted = !hvac_system.distribution_system_idref.nil?
|
1218
|
+
if is_ducted
|
1219
|
+
return [0.394, 1.0]
|
1220
|
+
else
|
1221
|
+
return [0.255, 1.0]
|
1222
|
+
end
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
fail 'Unable to get cooling capacity ratios.'
|
1226
|
+
end
|
1227
|
+
|
1228
|
+
def self.set_heat_curves_central_air_source(heating_system, use_cop = false)
|
1229
|
+
htg_ap = heating_system.additional_properties
|
1230
|
+
htg_ap.heat_rated_cfm_per_ton = get_default_heat_cfm_per_ton(heating_system.compressor_type, use_cop)
|
1231
|
+
heating_capacity_retention_temp, heating_capacity_retention_fraction = get_heating_capacity_retention(heating_system)
|
1232
|
+
htg_ap.heat_cap_fflow_spec, htg_ap.heat_eir_fflow_spec = get_heat_cap_eir_fflow_spec(heating_system.compressor_type)
|
1233
|
+
htg_ap.heat_capacity_ratios = get_heat_capacity_ratios(heating_system)
|
1234
|
+
set_heat_c_d(heating_system)
|
1235
|
+
|
1236
|
+
hspf = heating_system.heating_efficiency_hspf
|
1237
|
+
if heating_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1238
|
+
htg_ap.heat_cap_ft_spec, htg_ap.heat_eir_ft_spec = get_heat_cap_eir_ft_spec(heating_system.compressor_type, heating_capacity_retention_temp, heating_capacity_retention_fraction)
|
1239
|
+
if not use_cop
|
1240
|
+
htg_ap.heat_rated_cops = [0.0353 * hspf**2 + 0.0331 * hspf + 0.9447] # Regression based on inverse model
|
1241
|
+
htg_ap.heat_rated_airflow_rate = htg_ap.heat_rated_cfm_per_ton[0]
|
1242
|
+
htg_ap.heat_fan_speed_ratios = calc_fan_speed_ratios(htg_ap.heat_capacity_ratios, htg_ap.heat_rated_cfm_per_ton, htg_ap.heat_rated_airflow_rate)
|
1243
|
+
else
|
1244
|
+
htg_ap.heat_fan_speed_ratios = [1.0]
|
1245
|
+
end
|
1145
1246
|
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1247
|
+
elsif heating_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1248
|
+
htg_ap.heat_cap_ft_spec, htg_ap.heat_eir_ft_spec = get_heat_cap_eir_ft_spec(heating_system.compressor_type, heating_capacity_retention_temp, heating_capacity_retention_fraction)
|
1249
|
+
htg_ap.heat_rated_airflow_rate = htg_ap.heat_rated_cfm_per_ton[-1]
|
1250
|
+
htg_ap.heat_fan_speed_ratios = calc_fan_speed_ratios(htg_ap.heat_capacity_ratios, htg_ap.heat_rated_cfm_per_ton, htg_ap.heat_rated_airflow_rate)
|
1251
|
+
htg_ap.heat_rated_cops = [0.0426 * hspf**2 - 0.0747 * hspf + 1.5374] # Regression based on inverse model
|
1252
|
+
htg_ap.heat_rated_cops << htg_ap.heat_rated_cops[0] * 0.87 # COP ratio based on Dylan's data as seen in BEopt 2.8 options
|
1151
1253
|
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1254
|
+
elsif heating_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1255
|
+
htg_ap.heat_rated_airflow_rate = htg_ap.heat_rated_cfm_per_ton[-1]
|
1256
|
+
htg_ap.heat_capacity_ratios = get_heat_capacity_ratios(heating_system)
|
1257
|
+
htg_ap.heat_fan_speed_ratios = calc_fan_speed_ratios(htg_ap.heat_capacity_ratios, htg_ap.heat_rated_cfm_per_ton, htg_ap.heat_rated_airflow_rate)
|
1258
|
+
end
|
1156
1259
|
end
|
1157
1260
|
|
1158
|
-
def self.
|
1261
|
+
def self.set_heat_detailed_performance_data(heat_pump)
|
1262
|
+
hp_ap = heat_pump.additional_properties
|
1263
|
+
is_ducted = !heat_pump.distribution_system_idref.nil?
|
1264
|
+
hspf = heat_pump.heating_efficiency_hspf
|
1265
|
+
|
1266
|
+
# Default data inputs based on NEEP data
|
1267
|
+
detailed_performance_data = heat_pump.heating_detailed_performance_data
|
1268
|
+
heating_capacity_retention_temp, heating_capacity_retention_fraction = get_heating_capacity_retention(heat_pump)
|
1269
|
+
max_cap_maint_5 = 1.0 - (1.0 - heating_capacity_retention_fraction) * (HVAC::AirSourceHeatRatedODB - 5.0) /
|
1270
|
+
(HVAC::AirSourceHeatRatedODB - heating_capacity_retention_temp)
|
1271
|
+
|
1272
|
+
if is_ducted
|
1273
|
+
a, b, c, d, e = 0.4348, 0.008923, 1.090, -0.1861, -0.07564
|
1274
|
+
else
|
1275
|
+
a, b, c, d, e = 0.1914, -1.822, 1.364, -0.07783, 2.221
|
1276
|
+
end
|
1277
|
+
max_cop_47 = a * hspf + b * max_cap_maint_5 + c * max_cap_maint_5**2 + d * max_cap_maint_5 * hspf + e
|
1278
|
+
max_capacity_47 = heat_pump.heating_capacity * hp_ap.heat_capacity_ratios[-1]
|
1279
|
+
min_capacity_47 = max_capacity_47 / hp_ap.heat_capacity_ratios[-1] * hp_ap.heat_capacity_ratios[0]
|
1280
|
+
min_cop_47 = is_ducted ? max_cop_47 * (-0.0306 * hspf + 1.5385) : max_cop_47 * (-0.01698 * hspf + 1.5907)
|
1281
|
+
max_capacity_5 = max_capacity_47 * max_cap_maint_5
|
1282
|
+
max_cop_5 = is_ducted ? max_cop_47 * 0.587 : max_cop_47 * 0.671
|
1283
|
+
min_capacity_5 = is_ducted ? min_capacity_47 * 1.106 : min_capacity_47 * 0.611
|
1284
|
+
min_cop_5 = is_ducted ? min_cop_47 * 0.502 : min_cop_47 * 0.538
|
1285
|
+
|
1286
|
+
# performance data at 47F, maximum speed
|
1287
|
+
detailed_performance_data.add(capacity: max_capacity_47.round(1),
|
1288
|
+
efficiency_cop: max_cop_47.round(4),
|
1289
|
+
capacity_description: HPXML::CapacityDescriptionMaximum,
|
1290
|
+
outdoor_temperature: 47,
|
1291
|
+
isdefaulted: true)
|
1292
|
+
# performance data at 47F, minimum speed
|
1293
|
+
detailed_performance_data.add(capacity: min_capacity_47.round(1),
|
1294
|
+
efficiency_cop: min_cop_47.round(4),
|
1295
|
+
capacity_description: HPXML::CapacityDescriptionMinimum,
|
1296
|
+
outdoor_temperature: 47,
|
1297
|
+
isdefaulted: true)
|
1298
|
+
# performance data at 5F, maximum speed
|
1299
|
+
detailed_performance_data.add(capacity: max_capacity_5.round(1),
|
1300
|
+
efficiency_cop: max_cop_5.round(4),
|
1301
|
+
capacity_description: HPXML::CapacityDescriptionMaximum,
|
1302
|
+
outdoor_temperature: 5,
|
1303
|
+
isdefaulted: true)
|
1304
|
+
# performance data at 5F, minimum speed
|
1305
|
+
detailed_performance_data.add(capacity: min_capacity_5.round(1),
|
1306
|
+
efficiency_cop: min_cop_5.round(4),
|
1307
|
+
capacity_description: HPXML::CapacityDescriptionMinimum,
|
1308
|
+
outdoor_temperature: 5,
|
1309
|
+
isdefaulted: true)
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
def self.set_cool_detailed_performance_data(heat_pump)
|
1159
1313
|
hp_ap = heat_pump.additional_properties
|
1314
|
+
is_ducted = !heat_pump.distribution_system_idref.nil?
|
1315
|
+
seer = heat_pump.cooling_efficiency_seer
|
1316
|
+
|
1317
|
+
# Default data inputs based on NEEP data
|
1318
|
+
detailed_performance_data = heat_pump.cooling_detailed_performance_data
|
1319
|
+
max_cap_maint_82 = 1.0 - (1.0 - hp_ap.cooling_capacity_retention_fraction) * (HVAC::AirSourceCoolRatedODB - 82.0) /
|
1320
|
+
(HVAC::AirSourceCoolRatedODB - hp_ap.cooling_capacity_retention_temperature)
|
1321
|
+
|
1322
|
+
max_cop_95 = is_ducted ? 0.1953 * seer : 0.06635 * seer + 1.8707
|
1323
|
+
max_capacity_95 = heat_pump.cooling_capacity * hp_ap.cool_capacity_ratios[-1]
|
1324
|
+
min_capacity_95 = max_capacity_95 / hp_ap.cool_capacity_ratios[-1] * hp_ap.cool_capacity_ratios[0]
|
1325
|
+
min_cop_95 = is_ducted ? max_cop_95 * 1.231 : max_cop_95 * (0.01377 * seer + 1.13948)
|
1326
|
+
max_capacity_82 = max_capacity_95 * max_cap_maint_82
|
1327
|
+
max_cop_82 = is_ducted ? (1.297 * max_cop_95) : (1.300 * max_cop_95)
|
1328
|
+
min_capacity_82 = min_capacity_95 * 1.099
|
1329
|
+
min_cop_82 = is_ducted ? (1.402 * min_cop_95) : (1.333 * min_cop_95)
|
1330
|
+
|
1331
|
+
# performance data at 95F, maximum speed
|
1332
|
+
detailed_performance_data.add(capacity: max_capacity_95.round(1),
|
1333
|
+
efficiency_cop: max_cop_95.round(4),
|
1334
|
+
capacity_description: HPXML::CapacityDescriptionMaximum,
|
1335
|
+
outdoor_temperature: 95,
|
1336
|
+
isdefaulted: true)
|
1337
|
+
# performance data at 95F, minimum speed
|
1338
|
+
detailed_performance_data.add(capacity: min_capacity_95.round(1),
|
1339
|
+
efficiency_cop: min_cop_95.round(4),
|
1340
|
+
capacity_description: HPXML::CapacityDescriptionMinimum,
|
1341
|
+
outdoor_temperature: 95,
|
1342
|
+
isdefaulted: true)
|
1343
|
+
# performance data at 82F, maximum speed
|
1344
|
+
detailed_performance_data.add(capacity: max_capacity_82.round(1),
|
1345
|
+
efficiency_cop: max_cop_82.round(4),
|
1346
|
+
capacity_description: HPXML::CapacityDescriptionMaximum,
|
1347
|
+
outdoor_temperature: 82,
|
1348
|
+
isdefaulted: true)
|
1349
|
+
# performance data at 82F, minimum speed
|
1350
|
+
detailed_performance_data.add(capacity: min_capacity_82.round(1),
|
1351
|
+
efficiency_cop: min_cop_82.round(4),
|
1352
|
+
capacity_description: HPXML::CapacityDescriptionMinimum,
|
1353
|
+
outdoor_temperature: 82,
|
1354
|
+
isdefaulted: true)
|
1355
|
+
end
|
1356
|
+
|
1357
|
+
def self.get_heat_capacity_ratios(heat_pump)
|
1358
|
+
# For each speed, ratio of capacity to nominal capacity
|
1359
|
+
if heat_pump.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1360
|
+
return [1.0]
|
1361
|
+
elsif heat_pump.compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1362
|
+
return [0.72, 1.0]
|
1363
|
+
elsif heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1364
|
+
is_ducted = !heat_pump.distribution_system_idref.nil?
|
1365
|
+
if is_ducted
|
1366
|
+
nominal_to_max_ratio = 0.972
|
1367
|
+
else
|
1368
|
+
nominal_to_max_ratio = 0.812
|
1369
|
+
end
|
1370
|
+
if is_ducted && heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpAirToAir
|
1371
|
+
# central ducted
|
1372
|
+
return [0.358 / nominal_to_max_ratio, 1.0, 1.0 / nominal_to_max_ratio]
|
1373
|
+
elsif !is_ducted
|
1374
|
+
# wall placement
|
1375
|
+
return [0.252 / nominal_to_max_ratio, 1.0, 1.0 / nominal_to_max_ratio]
|
1376
|
+
else
|
1377
|
+
# ducted minisplit
|
1378
|
+
return [0.305 / nominal_to_max_ratio, 1.0, 1.0 / nominal_to_max_ratio]
|
1379
|
+
end
|
1380
|
+
end
|
1381
|
+
|
1382
|
+
fail 'Unable to get heating capacity ratios.'
|
1383
|
+
end
|
1160
1384
|
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1385
|
+
def self.drop_intermediate_speeds(hvac_system)
|
1386
|
+
# For variable-speed systems, we only want to model min/max speeds in E+.
|
1387
|
+
# Here we drop any intermediate speeds that we may have added for other purposes (e.g. hvac sizing).
|
1388
|
+
return unless hvac_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1165
1389
|
|
1166
|
-
|
1390
|
+
hvac_ap = hvac_system.additional_properties
|
1167
1391
|
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1392
|
+
while hvac_ap.cool_capacity_ratios.size > 2
|
1393
|
+
hvac_ap.cool_cap_fflow_spec.delete_at(1)
|
1394
|
+
hvac_ap.cool_eir_fflow_spec.delete_at(1)
|
1395
|
+
hvac_ap.cool_plf_fplr_spec.delete_at(1)
|
1396
|
+
hvac_ap.cool_rated_cfm_per_ton.delete_at(1)
|
1397
|
+
hvac_ap.cool_capacity_ratios.delete_at(1)
|
1398
|
+
hvac_ap.cool_fan_speed_ratios.delete_at(1)
|
1399
|
+
end
|
1400
|
+
if hvac_system.is_a? HPXML::HeatPump
|
1401
|
+
while hvac_ap.heat_capacity_ratios.size > 2
|
1402
|
+
hvac_ap.heat_cap_fflow_spec.delete_at(1)
|
1403
|
+
hvac_ap.heat_eir_fflow_spec.delete_at(1)
|
1404
|
+
hvac_ap.heat_plf_fplr_spec.delete_at(1)
|
1405
|
+
hvac_ap.heat_rated_cfm_per_ton.delete_at(1)
|
1406
|
+
hvac_ap.heat_capacity_ratios.delete_at(1)
|
1407
|
+
hvac_ap.heat_fan_speed_ratios.delete_at(1)
|
1408
|
+
end
|
1409
|
+
end
|
1173
1410
|
end
|
1174
1411
|
|
1175
|
-
def self.get_default_cool_cfm_per_ton(
|
1412
|
+
def self.get_default_cool_cfm_per_ton(compressor_type, use_eer = false)
|
1176
1413
|
# cfm/ton of rated capacity
|
1177
|
-
if
|
1414
|
+
if compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1178
1415
|
if not use_eer
|
1179
1416
|
return [394.2]
|
1180
1417
|
else
|
1181
1418
|
return [312] # medium speed
|
1182
1419
|
end
|
1183
|
-
elsif
|
1420
|
+
elsif compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1184
1421
|
return [411.0083, 344.1]
|
1185
|
-
elsif
|
1186
|
-
return [
|
1187
|
-
elsif num_speeds == 10
|
1188
|
-
return [470.6, 433.1356, 407.1997, 388.2406, 373.6898, 362.2454, 352.9412, 345.2945, 338.8354, 333.3333]
|
1422
|
+
elsif compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1423
|
+
return [400.0, 400.0]
|
1189
1424
|
else
|
1190
|
-
fail '
|
1425
|
+
fail 'Compressor type not supported.'
|
1191
1426
|
end
|
1192
1427
|
end
|
1193
1428
|
|
1194
|
-
def self.get_default_heat_cfm_per_ton(
|
1429
|
+
def self.get_default_heat_cfm_per_ton(compressor_type, use_cop_or_htg_sys = false)
|
1195
1430
|
# cfm/ton of rated capacity
|
1196
|
-
if
|
1431
|
+
if compressor_type == HPXML::HVACCompressorTypeSingleStage
|
1197
1432
|
if not use_cop_or_htg_sys
|
1198
1433
|
return [384.1]
|
1199
1434
|
else
|
1200
1435
|
return [350]
|
1201
1436
|
end
|
1202
|
-
elsif
|
1437
|
+
elsif compressor_type == HPXML::HVACCompressorTypeTwoStage
|
1203
1438
|
return [391.3333, 352.2]
|
1204
|
-
elsif
|
1205
|
-
return [
|
1206
|
-
elsif num_speeds == 10
|
1207
|
-
return [666.6667, 555.6000, 488.8800, 444.4667, 412.6857, 388.9000, 370.3556, 355.5600, 343.4182, 333.3333]
|
1439
|
+
elsif compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
1440
|
+
return [400.0, 400.0, 400.0]
|
1208
1441
|
else
|
1209
|
-
fail '
|
1442
|
+
fail 'Compressor type not supported.'
|
1210
1443
|
end
|
1211
1444
|
end
|
1212
1445
|
|
@@ -1222,19 +1455,22 @@ class HVAC
|
|
1222
1455
|
hp_ap.cool_power_curve_spec = [[-4.42471086639888, 0.658017281046304, 4.37331801294626, 0.174096187531254, -0.0526514790164159]]
|
1223
1456
|
hp_ap.cool_sh_curve_spec = [[4.54172823345154, 14.7653304889134, -18.3541272090485, -0.74401391092935, 0.545560799548833, 0.0182620032235494]]
|
1224
1457
|
hp_ap.cool_rated_shrs_gross = [heat_pump.cooling_shr]
|
1225
|
-
# FUTURE: Reconcile these fan/pump adjustments with ANSI/RESNET/ICC 301-2019 Section 4.4.5
|
1226
|
-
fan_adjust_kw = UnitConversions.convert(400.0, 'Btu/hr', 'ton') * UnitConversions.convert(1.0, 'cfm', 'm^3/s') * 1000.0 * 0.35 * 249.0 / 300.0 # Adjustment per ISO 13256-1 Internal pressure drop across heat pump assumed to be 0.5 in. w.g.
|
1227
|
-
pump_adjust_kw = UnitConversions.convert(3.0, 'Btu/hr', 'ton') * UnitConversions.convert(1.0, 'gal/min', 'm^3/s') * 1000.0 * 6.0 * 2990.0 / 3000.0 # Adjustment per ISO 13256-1 Internal Pressure drop across heat pump coil assumed to be 11ft w.g.
|
1228
|
-
cool_eir = UnitConversions.convert((1.0 - heat_pump.cooling_efficiency_eer * (fan_adjust_kw + pump_adjust_kw)) / (heat_pump.cooling_efficiency_eer * (1.0 + UnitConversions.convert(fan_adjust_kw, 'Wh', 'Btu'))), 'Wh', 'Btu')
|
1229
|
-
hp_ap.cool_rated_eirs = [cool_eir]
|
1230
1458
|
|
1231
1459
|
# E+ equation fit coil coefficients from Tang's thesis:
|
1232
1460
|
# See Appendix B Figure B.3 of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
|
1233
1461
|
# Coefficients generated by catalog data
|
1234
1462
|
hp_ap.heat_cap_curve_spec = [[-5.12650150, -0.93997630, 7.21443206, 0.121065721, 0.051809805]]
|
1235
1463
|
hp_ap.heat_power_curve_spec = [[-7.73235249, 6.43390775, 2.29152262, -0.175598629, 0.005888871]]
|
1236
|
-
|
1237
|
-
|
1464
|
+
|
1465
|
+
# Fan/pump adjustments calculations
|
1466
|
+
power_f = heat_pump.fan_watts_per_cfm * 400.0 / UnitConversions.convert(1.0, 'ton', 'Btu/hr') * UnitConversions.convert(1.0, 'W', 'kW') # 400 cfm/ton, result is in kW per Btu/hr of capacity
|
1467
|
+
power_p = heat_pump.pump_watts_per_ton / UnitConversions.convert(1.0, 'ton', 'Btu/hr') * UnitConversions.convert(1.0, 'W', 'kW') # result is in kW per Btu/hr of capacity
|
1468
|
+
|
1469
|
+
cool_eir = (1 - UnitConversions.convert(power_f, 'Wh', 'Btu')) / UnitConversions.convert(heat_pump.cooling_efficiency_eer, 'Btu', 'Wh') - power_f - power_p
|
1470
|
+
heat_eir = (1 + UnitConversions.convert(power_f, 'Wh', 'Btu')) / heat_pump.heating_efficiency_cop - power_f - power_p
|
1471
|
+
|
1472
|
+
hp_ap.cool_rated_cops = [1.0 / cool_eir]
|
1473
|
+
hp_ap.heat_rated_cops = [1.0 / heat_eir]
|
1238
1474
|
end
|
1239
1475
|
|
1240
1476
|
def self.get_default_compressor_type(hvac_type, seer)
|
@@ -1428,44 +1664,6 @@ class HVAC
|
|
1428
1664
|
pump_program_calling_manager.addProgram(pump_program)
|
1429
1665
|
end
|
1430
1666
|
|
1431
|
-
def self.set_boiler_pilot_light_ems_program(model, boiler, heating_system)
|
1432
|
-
# Create Equipment object for fuel consumption
|
1433
|
-
loc_space = model.getSpaces[0] # Arbitrary; not used
|
1434
|
-
fuel_type = heating_system.heating_system_fuel
|
1435
|
-
pilot_light_object = HotWaterAndAppliances.add_other_equipment(model, Constants.ObjectNameBoilerPilotLight(boiler.name), loc_space, 0.01, 0, 0, model.alwaysOnDiscreteSchedule, fuel_type)
|
1436
|
-
|
1437
|
-
# Sensor
|
1438
|
-
boiler_plr_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Boiler Part Load Ratio')
|
1439
|
-
boiler_plr_sensor.setName("#{boiler.name} plr s")
|
1440
|
-
boiler_plr_sensor.setKeyName(boiler.name.to_s)
|
1441
|
-
|
1442
|
-
# Actuator
|
1443
|
-
pilot_light_act = OpenStudio::Model::EnergyManagementSystemActuator.new(pilot_light_object, *EPlus::EMSActuatorOtherEquipmentPower, pilot_light_object.space.get)
|
1444
|
-
pilot_light_act.setName("#{boiler.name} pilot light act")
|
1445
|
-
|
1446
|
-
# Program
|
1447
|
-
pilot_light_program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
|
1448
|
-
pilot_light_program.setName("#{boiler.name} pilot light program")
|
1449
|
-
pilot_light_program.addLine("Set #{pilot_light_act.name} = (1.0 - #{boiler_plr_sensor.name}) * #{UnitConversions.convert(heating_system.pilot_light_btuh.to_f, 'Btu/hr', 'W')}")
|
1450
|
-
pilot_light_program.addLine("Set boiler_pilot_energy = #{pilot_light_act.name} * 3600 * SystemTimeStep")
|
1451
|
-
|
1452
|
-
# Program Calling Manager
|
1453
|
-
program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
|
1454
|
-
program_calling_manager.setName("#{boiler.name} pilot light program manager")
|
1455
|
-
program_calling_manager.setCallingPoint('EndOfSystemTimestepBeforeHVACReporting')
|
1456
|
-
program_calling_manager.addProgram(pilot_light_program)
|
1457
|
-
|
1458
|
-
# EMS Output Variable for reporting
|
1459
|
-
pilot_light_output_var = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, 'boiler_pilot_energy')
|
1460
|
-
pilot_light_output_var.setName("#{Constants.ObjectNameBoilerPilotLight(boiler.name)} outvar")
|
1461
|
-
pilot_light_output_var.setTypeOfDataInVariable('Summed')
|
1462
|
-
pilot_light_output_var.setUpdateFrequency('SystemTimestep')
|
1463
|
-
pilot_light_output_var.setEMSProgramOrSubroutineName(pilot_light_program)
|
1464
|
-
pilot_light_output_var.setUnits('J')
|
1465
|
-
pilot_light_output_var.additionalProperties.setFeature('FuelType', EPlus.fuel_type(fuel_type)) # Used by reporting measure
|
1466
|
-
pilot_light_output_var.additionalProperties.setFeature('HPXML_ID', heating_system.id) # Used by reporting measure
|
1467
|
-
end
|
1468
|
-
|
1469
1667
|
def self.disaggregate_fan_or_pump(model, fan_or_pump, htg_object, clg_object, backup_htg_object, hpxml_object)
|
1470
1668
|
# Disaggregate into heating/cooling output energy use.
|
1471
1669
|
|
@@ -1548,15 +1746,23 @@ class HVAC
|
|
1548
1746
|
fan_or_pump_program.addLine("Set #{fan_or_pump_var}_#{mode} = 0")
|
1549
1747
|
end
|
1550
1748
|
sensors.each_with_index do |(mode, sensor), i|
|
1551
|
-
|
1749
|
+
if i == 0
|
1750
|
+
if_else_str = "If #{sensor.name} > 0"
|
1751
|
+
elsif i == sensors.size - 1
|
1752
|
+
# Use else for last mode to make sure we don't miss any energy use
|
1753
|
+
# See https://github.com/NREL/OpenStudio-HPXML/issues/1424
|
1754
|
+
if_else_str = 'Else'
|
1755
|
+
else
|
1756
|
+
if_else_str = "ElseIf #{sensor.name} > 0"
|
1757
|
+
end
|
1552
1758
|
if mode == 'primary_htg' && sensors.keys[i + 1] == 'backup_htg'
|
1553
1759
|
# HP with both primary and backup heating
|
1554
1760
|
# If both are operating, apportion energy use
|
1555
|
-
fan_or_pump_program.addLine("#{
|
1761
|
+
fan_or_pump_program.addLine("#{if_else_str} && (#{sensors.values[i + 1].name} > 0)")
|
1556
1762
|
fan_or_pump_program.addLine(" Set #{fan_or_pump_var}_#{mode} = #{fan_or_pump_sensor.name} * #{sensor.name} / (#{sensor.name} + #{sensors.values[i + 1].name})")
|
1557
1763
|
fan_or_pump_program.addLine(" Set #{fan_or_pump_var}_#{sensors.keys[i + 1]} = #{fan_or_pump_sensor.name} * #{sensors.values[i + 1].name} / (#{sensor.name} + #{sensors.values[i + 1].name})")
|
1558
1764
|
end
|
1559
|
-
fan_or_pump_program.addLine(
|
1765
|
+
fan_or_pump_program.addLine(if_else_str)
|
1560
1766
|
fan_or_pump_program.addLine(" Set #{fan_or_pump_var}_#{mode} = #{fan_or_pump_sensor.name}")
|
1561
1767
|
end
|
1562
1768
|
fan_or_pump_program.addLine('EndIf')
|
@@ -1571,19 +1777,20 @@ class HVAC
|
|
1571
1777
|
next if sensor.nil?
|
1572
1778
|
|
1573
1779
|
fan_or_pump_ems_output_var = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model, "#{fan_or_pump_var}_#{mode}")
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
fan_or_pump_ems_output_var.setName(name)
|
1780
|
+
object_type = { 'clg' => Constants.ObjectNameFanPumpDisaggregateCool,
|
1781
|
+
'primary_htg' => Constants.ObjectNameFanPumpDisaggregatePrimaryHeat,
|
1782
|
+
'backup_htg' => Constants.ObjectNameFanPumpDisaggregateBackupHeat }[mode]
|
1783
|
+
fan_or_pump_ems_output_var.setName("#{fan_or_pump.name} #{object_type}")
|
1578
1784
|
fan_or_pump_ems_output_var.setTypeOfDataInVariable('Summed')
|
1579
1785
|
fan_or_pump_ems_output_var.setUpdateFrequency('SystemTimestep')
|
1580
1786
|
fan_or_pump_ems_output_var.setEMSProgramOrSubroutineName(fan_or_pump_program)
|
1581
1787
|
fan_or_pump_ems_output_var.setUnits('J')
|
1582
1788
|
fan_or_pump_ems_output_var.additionalProperties.setFeature('HPXML_ID', sys_id) # Used by reporting measure
|
1789
|
+
fan_or_pump_ems_output_var.additionalProperties.setFeature('ObjectType', object_type) # Used by reporting measure
|
1583
1790
|
end
|
1584
1791
|
end
|
1585
1792
|
|
1586
|
-
def self.adjust_dehumidifier_load_EMS(fraction_served, zone_hvac, model,
|
1793
|
+
def self.adjust_dehumidifier_load_EMS(fraction_served, zone_hvac, model, conditioned_space)
|
1587
1794
|
# adjust hvac load to space when dehumidifier serves less than 100% dehumidification load. (With E+ dehumidifier object, it can only model 100%)
|
1588
1795
|
|
1589
1796
|
# sensor
|
@@ -1603,7 +1810,7 @@ class HVAC
|
|
1603
1810
|
dehumidifier_load_adj_def.setFractionLost(0)
|
1604
1811
|
dehumidifier_load_adj = OpenStudio::Model::OtherEquipment.new(dehumidifier_load_adj_def)
|
1605
1812
|
dehumidifier_load_adj.setName("#{zone_hvac.name} sens htg adj")
|
1606
|
-
dehumidifier_load_adj.setSpace(
|
1813
|
+
dehumidifier_load_adj.setSpace(conditioned_space)
|
1607
1814
|
dehumidifier_load_adj.setSchedule(model.alwaysOnDiscreteSchedule)
|
1608
1815
|
|
1609
1816
|
dehumidifier_load_adj_act = OpenStudio::Model::EnergyManagementSystemActuator.new(dehumidifier_load_adj, *EPlus::EMSActuatorOtherEquipmentPower, dehumidifier_load_adj.space.get)
|
@@ -1640,12 +1847,12 @@ class HVAC
|
|
1640
1847
|
else
|
1641
1848
|
htg_supp_coil = OpenStudio::Model::CoilHeatingGas.new(model)
|
1642
1849
|
htg_supp_coil.setGasBurnerEfficiency(efficiency)
|
1643
|
-
htg_supp_coil.
|
1644
|
-
htg_supp_coil.
|
1850
|
+
htg_supp_coil.setOnCycleParasiticElectricLoad(0)
|
1851
|
+
htg_supp_coil.setOffCycleParasiticGasLoad(0)
|
1645
1852
|
htg_supp_coil.setFuelType(EPlus.fuel_type(fuel))
|
1646
1853
|
end
|
1647
1854
|
htg_supp_coil.setNominalCapacity(UnitConversions.convert(capacity, 'Btu/hr', 'W'))
|
1648
|
-
htg_supp_coil.setName(obj_name + '
|
1855
|
+
htg_supp_coil.setName(obj_name + ' backup htg coil')
|
1649
1856
|
htg_supp_coil.additionalProperties.setFeature('HPXML_ID', heat_pump.id) # Used by reporting measure
|
1650
1857
|
htg_supp_coil.additionalProperties.setFeature('IsHeatPumpBackup', true) # Used by reporting measure
|
1651
1858
|
|
@@ -1668,13 +1875,18 @@ class HVAC
|
|
1668
1875
|
|
1669
1876
|
fan_cfms.sort.each do |fan_cfm|
|
1670
1877
|
fan_ratio = fan_cfm / max_fan_cfm
|
1671
|
-
power_fraction = fan_ratio
|
1878
|
+
power_fraction = calculate_fan_power_from_curve(1.0, fan_ratio)
|
1672
1879
|
fan.addSpeed(fan_ratio.round(5), power_fraction.round(5))
|
1673
1880
|
end
|
1674
1881
|
|
1675
1882
|
return fan
|
1676
1883
|
end
|
1677
1884
|
|
1885
|
+
def self.calculate_fan_power_from_curve(max_fan_power, fan_ratio)
|
1886
|
+
# Cubic relationship fan power curve
|
1887
|
+
return max_fan_power * (fan_ratio**3)
|
1888
|
+
end
|
1889
|
+
|
1678
1890
|
def self.set_fan_power(fan, fan_watts_per_cfm)
|
1679
1891
|
if fan_watts_per_cfm > 0
|
1680
1892
|
fan_eff = 0.75 # Overall Efficiency of the Fan, Motor and Drive
|
@@ -1699,14 +1911,12 @@ class HVAC
|
|
1699
1911
|
air_loop_unitary.setSupplyFan(fan)
|
1700
1912
|
air_loop_unitary.setFanPlacement('BlowThrough')
|
1701
1913
|
air_loop_unitary.setSupplyAirFanOperatingModeSchedule(cycle_fan_sch)
|
1702
|
-
air_loop_unitary.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
|
1703
1914
|
if htg_coil.nil?
|
1704
1915
|
air_loop_unitary.setSupplyAirFlowRateDuringHeatingOperation(0.0)
|
1705
1916
|
else
|
1706
1917
|
air_loop_unitary.setHeatingCoil(htg_coil)
|
1707
1918
|
air_loop_unitary.setSupplyAirFlowRateDuringHeatingOperation(UnitConversions.convert(htg_cfm, 'cfm', 'm^3/s'))
|
1708
1919
|
end
|
1709
|
-
air_loop_unitary.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
|
1710
1920
|
if clg_coil.nil?
|
1711
1921
|
air_loop_unitary.setSupplyAirFlowRateDuringCoolingOperation(0.0)
|
1712
1922
|
else
|
@@ -1841,38 +2051,22 @@ class HVAC
|
|
1841
2051
|
end
|
1842
2052
|
end
|
1843
2053
|
|
1844
|
-
def self.calc_heat_cap_ft_spec(
|
1845
|
-
if
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
|
1851
|
-
|
1852
|
-
|
1853
|
-
elsif num_speeds == 2
|
1854
|
-
iat_slope = -0.002947013
|
1855
|
-
iat_intercept = 0.23168251
|
1856
|
-
elsif num_speeds == 4
|
1857
|
-
iat_slope = -0.002897048
|
1858
|
-
iat_intercept = 0.209319129
|
1859
|
-
end
|
2054
|
+
def self.calc_heat_cap_ft_spec(compressor_type, heating_capacity_retention_temp, heating_capacity_retention_fraction)
|
2055
|
+
if compressor_type == HPXML::HVACCompressorTypeSingleStage
|
2056
|
+
iat_slope = -0.002303414
|
2057
|
+
iat_intercept = 0.18417308
|
2058
|
+
num_speeds = 1
|
2059
|
+
elsif compressor_type == HPXML::HVACCompressorTypeTwoStage
|
2060
|
+
iat_slope = -0.002947013
|
2061
|
+
iat_intercept = 0.23168251
|
2062
|
+
num_speeds = 2
|
1860
2063
|
end
|
1861
2064
|
|
1862
2065
|
# Biquadratic: capacity multiplier = a + b*IAT + c*IAT^2 + d*OAT + e*OAT^2 + f*IAT*OAT
|
1863
2066
|
# Derive coefficients from user input for capacity retention at outdoor drybulb temperature X [C].
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
y_A = heat_pump.heating_capacity_17F / heat_pump.heating_capacity
|
1868
|
-
else
|
1869
|
-
y_A = 0.0
|
1870
|
-
end
|
1871
|
-
else
|
1872
|
-
x_A = heat_pump.heating_capacity_retention_temp
|
1873
|
-
y_A = heat_pump.heating_capacity_retention_fraction
|
1874
|
-
end
|
1875
|
-
x_B = 47.0 # 47F is the rating point
|
2067
|
+
x_A = heating_capacity_retention_temp
|
2068
|
+
y_A = heating_capacity_retention_fraction
|
2069
|
+
x_B = HVAC::AirSourceHeatRatedODB
|
1876
2070
|
y_B = 1.0
|
1877
2071
|
|
1878
2072
|
oat_slope = (y_B - y_A) / (x_B - x_A)
|
@@ -1881,960 +2075,429 @@ class HVAC
|
|
1881
2075
|
return [[oat_intercept + iat_intercept, iat_slope, 0, oat_slope, 0, 0]] * num_speeds
|
1882
2076
|
end
|
1883
2077
|
|
1884
|
-
def self.
|
1885
|
-
|
2078
|
+
def self.get_heating_capacity_retention(heat_pump)
|
2079
|
+
if not heat_pump.heating_capacity_17F.nil?
|
2080
|
+
heating_capacity_retention_temp = 17.0
|
2081
|
+
heating_capacity_retention_fraction = heat_pump.heating_capacity == 0.0 ? 0.0 : heat_pump.heating_capacity_17F / heat_pump.heating_capacity
|
2082
|
+
elsif not heat_pump.heating_capacity_retention_fraction.nil?
|
2083
|
+
heating_capacity_retention_temp = heat_pump.heating_capacity_retention_temp
|
2084
|
+
heating_capacity_retention_fraction = heat_pump.heating_capacity_retention_fraction
|
2085
|
+
else
|
2086
|
+
fail 'Missing heating capacity retention or 17F heating capacity.'
|
2087
|
+
end
|
2088
|
+
return heating_capacity_retention_temp, heating_capacity_retention_fraction
|
1886
2089
|
end
|
1887
2090
|
|
1888
|
-
def self.
|
1889
|
-
|
2091
|
+
def self.calc_fan_speed_ratios(capacity_ratios, rated_cfm_per_tons, rated_airflow_rate)
|
2092
|
+
fan_speed_ratios = []
|
2093
|
+
capacity_ratios.each_with_index do |capacity_ratio, i|
|
2094
|
+
fan_speed_ratios << rated_cfm_per_tons[i] * capacity_ratio / rated_airflow_rate
|
2095
|
+
end
|
2096
|
+
return fan_speed_ratios
|
1890
2097
|
end
|
1891
2098
|
|
1892
|
-
def self.
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
2099
|
+
def self.convert_curve_biquadratic(coeff)
|
2100
|
+
# Convert IP curves to SI curves
|
2101
|
+
si_coeff = []
|
2102
|
+
si_coeff << coeff[0] + 32.0 * (coeff[1] + coeff[3]) + 1024.0 * (coeff[2] + coeff[4] + coeff[5])
|
2103
|
+
si_coeff << 9.0 / 5.0 * coeff[1] + 576.0 / 5.0 * coeff[2] + 288.0 / 5.0 * coeff[5]
|
2104
|
+
si_coeff << 81.0 / 25.0 * coeff[2]
|
2105
|
+
si_coeff << 9.0 / 5.0 * coeff[3] + 576.0 / 5.0 * coeff[4] + 288.0 / 5.0 * coeff[5]
|
2106
|
+
si_coeff << 81.0 / 25.0 * coeff[4]
|
2107
|
+
si_coeff << 81.0 / 25.0 * coeff[5]
|
2108
|
+
return si_coeff
|
1896
2109
|
end
|
1897
2110
|
|
1898
|
-
def self.
|
1899
|
-
|
2111
|
+
def self.create_table_lookup(model, name, independent_vars, output_values, output_min = nil, output_max = nil)
|
2112
|
+
if (not output_min.nil?) && (output_values.min < output_min)
|
2113
|
+
fail "Minimum table lookup output value (#{output_values.min}) is less than #{output_min} for #{name}."
|
2114
|
+
end
|
2115
|
+
if (not output_max.nil?) && (output_values.max > output_max)
|
2116
|
+
fail "Maximum table lookup output value (#{output_values.max}) is greater than #{output_max} for #{name}."
|
2117
|
+
end
|
1900
2118
|
|
1901
|
-
|
2119
|
+
table = OpenStudio::Model::TableLookup.new(model)
|
2120
|
+
table.setName(name)
|
2121
|
+
independent_vars.each do |var|
|
2122
|
+
ind_var = OpenStudio::Model::TableIndependentVariable.new(model)
|
2123
|
+
ind_var.setName(var[:name])
|
2124
|
+
ind_var.setMinimumValue(var[:min])
|
2125
|
+
ind_var.setMaximumValue(var[:max])
|
2126
|
+
ind_var.setExtrapolationMethod('Constant')
|
2127
|
+
ind_var.setValues(var[:values])
|
2128
|
+
table.addIndependentVariable(ind_var)
|
2129
|
+
end
|
2130
|
+
table.setMinimumOutput(output_min) unless output_min.nil?
|
2131
|
+
table.setMaximumOutput(output_max) unless output_max.nil?
|
2132
|
+
table.setOutputValues(output_values)
|
2133
|
+
return table
|
2134
|
+
end
|
1902
2135
|
|
1903
|
-
|
2136
|
+
def self.create_curve_biquadratic_constant(model)
|
2137
|
+
curve = OpenStudio::Model::CurveBiquadratic.new(model)
|
2138
|
+
curve.setName('ConstantBiquadratic')
|
2139
|
+
curve.setCoefficient1Constant(1)
|
2140
|
+
curve.setCoefficient2x(0)
|
2141
|
+
curve.setCoefficient3xPOW2(0)
|
2142
|
+
curve.setCoefficient4y(0)
|
2143
|
+
curve.setCoefficient5yPOW2(0)
|
2144
|
+
curve.setCoefficient6xTIMESY(0)
|
2145
|
+
curve.setMinimumValueofx(-100)
|
2146
|
+
curve.setMaximumValueofx(100)
|
2147
|
+
curve.setMinimumValueofy(-100)
|
2148
|
+
curve.setMaximumValueofy(100)
|
2149
|
+
return curve
|
2150
|
+
end
|
1904
2151
|
|
1905
|
-
|
2152
|
+
def self.create_curve_quadratic_constant(model)
|
2153
|
+
curve = OpenStudio::Model::CurveQuadratic.new(model)
|
2154
|
+
curve.setName('ConstantQuadratic')
|
2155
|
+
curve.setCoefficient1Constant(1)
|
2156
|
+
curve.setCoefficient2x(0)
|
2157
|
+
curve.setCoefficient3xPOW2(0)
|
2158
|
+
curve.setMinimumValueofx(-100)
|
2159
|
+
curve.setMaximumValueofx(100)
|
2160
|
+
curve.setMinimumCurveOutput(-100)
|
2161
|
+
curve.setMaximumCurveOutput(100)
|
2162
|
+
return curve
|
1906
2163
|
end
|
1907
2164
|
|
1908
|
-
def self.
|
1909
|
-
|
2165
|
+
def self.create_curve_biquadratic(model, coeff, name, min_x, max_x, min_y, max_y)
|
2166
|
+
curve = OpenStudio::Model::CurveBiquadratic.new(model)
|
2167
|
+
curve.setName(name)
|
2168
|
+
curve.setCoefficient1Constant(coeff[0])
|
2169
|
+
curve.setCoefficient2x(coeff[1])
|
2170
|
+
curve.setCoefficient3xPOW2(coeff[2])
|
2171
|
+
curve.setCoefficient4y(coeff[3])
|
2172
|
+
curve.setCoefficient5yPOW2(coeff[4])
|
2173
|
+
curve.setCoefficient6xTIMESY(coeff[5])
|
2174
|
+
curve.setMinimumValueofx(min_x)
|
2175
|
+
curve.setMaximumValueofx(max_x)
|
2176
|
+
curve.setMinimumValueofy(min_y)
|
2177
|
+
curve.setMaximumValueofy(max_y)
|
2178
|
+
return curve
|
2179
|
+
end
|
1910
2180
|
|
1911
|
-
|
2181
|
+
def self.create_curve_bicubic(model, coeff, name, min_x, max_x, min_y, max_y)
|
2182
|
+
curve = OpenStudio::Model::CurveBicubic.new(model)
|
2183
|
+
curve.setName(name)
|
2184
|
+
curve.setCoefficient1Constant(coeff[0])
|
2185
|
+
curve.setCoefficient2x(coeff[1])
|
2186
|
+
curve.setCoefficient3xPOW2(coeff[2])
|
2187
|
+
curve.setCoefficient4y(coeff[3])
|
2188
|
+
curve.setCoefficient5yPOW2(coeff[4])
|
2189
|
+
curve.setCoefficient6xTIMESY(coeff[5])
|
2190
|
+
curve.setCoefficient7xPOW3(coeff[6])
|
2191
|
+
curve.setCoefficient8yPOW3(coeff[7])
|
2192
|
+
curve.setCoefficient9xPOW2TIMESY(coeff[8])
|
2193
|
+
curve.setCoefficient10xTIMESYPOW2(coeff[9])
|
2194
|
+
curve.setMinimumValueofx(min_x)
|
2195
|
+
curve.setMaximumValueofx(max_x)
|
2196
|
+
curve.setMinimumValueofy(min_y)
|
2197
|
+
curve.setMaximumValueofy(max_y)
|
2198
|
+
return curve
|
2199
|
+
end
|
1912
2200
|
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
2201
|
+
def self.create_curve_quadratic(model, coeff, name, min_x, max_x, min_y, max_y, is_dimensionless = false)
|
2202
|
+
curve = OpenStudio::Model::CurveQuadratic.new(model)
|
2203
|
+
curve.setName(name)
|
2204
|
+
curve.setCoefficient1Constant(coeff[0])
|
2205
|
+
curve.setCoefficient2x(coeff[1])
|
2206
|
+
curve.setCoefficient3xPOW2(coeff[2])
|
2207
|
+
curve.setMinimumValueofx(min_x)
|
2208
|
+
curve.setMaximumValueofx(max_x)
|
2209
|
+
if not min_y.nil?
|
2210
|
+
curve.setMinimumCurveOutput(min_y)
|
1917
2211
|
end
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
# Seer calculation is based on performance at three speeds
|
1922
|
-
cops = [cop_ratios[indices[0]], cop_ratios[indices[1]], cop_ratios[indices[2]]]
|
1923
|
-
|
1924
|
-
if calc_type != 'seer'
|
1925
|
-
cops << cop_ratios[indices[3]]
|
2212
|
+
if not max_y.nil?
|
2213
|
+
curve.setMaximumCurveOutput(max_y)
|
1926
2214
|
end
|
1927
|
-
|
1928
|
-
|
1929
|
-
|
1930
|
-
eir = eir_nom / mult
|
1931
|
-
eers << calc_eer_from_eir(eir, fan_power_rated)
|
2215
|
+
if is_dimensionless
|
2216
|
+
curve.setInputUnitTypeforX('Dimensionless')
|
2217
|
+
curve.setOutputUnitType('Dimensionless')
|
1932
2218
|
end
|
2219
|
+
return curve
|
2220
|
+
end
|
1933
2221
|
|
1934
|
-
|
2222
|
+
def self.create_curve_quad_linear(model, coeff, name)
|
2223
|
+
curve = OpenStudio::Model::CurveQuadLinear.new(model)
|
2224
|
+
curve.setName(name)
|
2225
|
+
curve.setCoefficient1Constant(coeff[0])
|
2226
|
+
curve.setCoefficient2w(coeff[1])
|
2227
|
+
curve.setCoefficient3x(coeff[2])
|
2228
|
+
curve.setCoefficient4y(coeff[3])
|
2229
|
+
curve.setCoefficient5z(coeff[4])
|
2230
|
+
return curve
|
1935
2231
|
end
|
1936
2232
|
|
1937
|
-
def self.
|
1938
|
-
|
1939
|
-
|
1940
|
-
|
2233
|
+
def self.create_curve_quint_linear(model, coeff, name)
|
2234
|
+
curve = OpenStudio::Model::CurveQuintLinear.new(model)
|
2235
|
+
curve.setName(name)
|
2236
|
+
curve.setCoefficient1Constant(coeff[0])
|
2237
|
+
curve.setCoefficient2v(coeff[1])
|
2238
|
+
curve.setCoefficient3w(coeff[2])
|
2239
|
+
curve.setCoefficient4x(coeff[3])
|
2240
|
+
curve.setCoefficient5y(coeff[4])
|
2241
|
+
curve.setCoefficient6z(coeff[5])
|
2242
|
+
return curve
|
1941
2243
|
end
|
1942
2244
|
|
1943
|
-
def self.
|
1944
|
-
|
2245
|
+
def self.convert_net_to_gross_capacity_cop(net_cap, fan_power, mode, net_cop = nil)
|
2246
|
+
net_cap_watts = UnitConversions.convert(net_cap, 'Btu/hr', 'w')
|
2247
|
+
if mode == :clg
|
2248
|
+
gross_cap_watts = net_cap_watts + fan_power
|
2249
|
+
else
|
2250
|
+
gross_cap_watts = net_cap_watts - fan_power
|
2251
|
+
end
|
2252
|
+
if not net_cop.nil?
|
2253
|
+
net_power = net_cap_watts / net_cop
|
2254
|
+
gross_power = net_power - fan_power
|
2255
|
+
gross_cop = gross_cap_watts / gross_power
|
2256
|
+
end
|
2257
|
+
gross_cap_btu_hr = UnitConversions.convert(gross_cap_watts, 'w', 'Btu/hr')
|
2258
|
+
return gross_cap_btu_hr, gross_cop
|
2259
|
+
end
|
1945
2260
|
|
1946
|
-
|
2261
|
+
def self.process_neep_detailed_performance(detailed_performance_data, hvac_ap, mode, max_rated_fan_cfm, weather_temp, compressor_lockout_temp = nil)
|
2262
|
+
data_array = Array.new(2) { Array.new }
|
2263
|
+
detailed_performance_data.sort_by { |dp| dp.outdoor_temperature }.each do |data_point|
|
2264
|
+
# Only process min and max capacities at each outdoor drybulb
|
2265
|
+
next unless [HPXML::CapacityDescriptionMinimum, HPXML::CapacityDescriptionMaximum].include? data_point.capacity_description
|
1947
2266
|
|
1948
|
-
|
2267
|
+
if data_point.capacity_description == HPXML::CapacityDescriptionMinimum
|
2268
|
+
data_array[0] << data_point
|
2269
|
+
elsif data_point.capacity_description == HPXML::CapacityDescriptionMaximum
|
2270
|
+
data_array[1] << data_point
|
2271
|
+
end
|
2272
|
+
end
|
1949
2273
|
|
1950
|
-
|
2274
|
+
# convert net to gross, adds more data points for table lookup, etc.
|
2275
|
+
if mode == :clg
|
2276
|
+
cfm_per_ton = hvac_ap.cool_rated_cfm_per_ton
|
2277
|
+
hvac_ap.cooling_performance_data_array = data_array
|
2278
|
+
hvac_ap.cool_rated_capacities_gross = []
|
2279
|
+
hvac_ap.cool_rated_capacities_net = []
|
2280
|
+
hvac_ap.cool_rated_cops = []
|
2281
|
+
elsif mode == :htg
|
2282
|
+
cfm_per_ton = hvac_ap.heat_rated_cfm_per_ton
|
2283
|
+
hvac_ap.heating_performance_data_array = data_array
|
2284
|
+
hvac_ap.heat_rated_capacities_gross = []
|
2285
|
+
hvac_ap.heat_rated_capacities_net = []
|
2286
|
+
hvac_ap.heat_rated_cops = []
|
2287
|
+
end
|
2288
|
+
# convert net to gross
|
2289
|
+
data_array.each_with_index do |data, speed|
|
2290
|
+
data.each do |dp|
|
2291
|
+
this_cfm = UnitConversions.convert(dp.capacity, 'Btu/hr', 'ton') * cfm_per_ton[speed]
|
2292
|
+
fan_ratio = this_cfm / max_rated_fan_cfm
|
2293
|
+
fan_power = calculate_fan_power_from_curve(hvac_ap.fan_power_rated * max_rated_fan_cfm, fan_ratio)
|
2294
|
+
dp.gross_capacity, dp.gross_efficiency_cop = convert_net_to_gross_capacity_cop(dp.capacity, fan_power, mode, dp.efficiency_cop)
|
2295
|
+
end
|
2296
|
+
end
|
2297
|
+
# convert to table lookup data
|
2298
|
+
interpolate_to_odb_table_points(data_array, mode, compressor_lockout_temp, weather_temp)
|
2299
|
+
add_data_point_adaptive_step_size(data_array, mode)
|
2300
|
+
correct_ft_cap_eir(data_array, mode)
|
2301
|
+
end
|
2302
|
+
|
2303
|
+
def self.interpolate_to_odb_table_points(data_array, mode, compressor_lockout_temp, weather_temp)
|
2304
|
+
# Set of data used for table lookup
|
2305
|
+
data_array.each do |data|
|
2306
|
+
user_odbs = data.map { |dp| dp.outdoor_temperature }
|
2307
|
+
# Determine min/max ODB temperatures to cover full range of heat pump operation
|
2308
|
+
if mode == :clg
|
2309
|
+
outdoor_dry_bulbs = []
|
2310
|
+
# Calculate ODB temperature at which COP or capacity is zero
|
2311
|
+
high_odb_at_zero_cop = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_efficiency_cop, true)
|
2312
|
+
high_odb_at_zero_capacity = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_capacity, true)
|
2313
|
+
low_odb_at_zero_cop = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_efficiency_cop, false)
|
2314
|
+
low_odb_at_zero_capacity = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_capacity, false)
|
2315
|
+
outdoor_dry_bulbs << [low_odb_at_zero_cop, low_odb_at_zero_capacity, 55.0].max # Min cooling ODB
|
2316
|
+
outdoor_dry_bulbs << [high_odb_at_zero_cop, high_odb_at_zero_capacity, weather_temp].min # Max cooling ODB
|
2317
|
+
else
|
2318
|
+
outdoor_dry_bulbs = []
|
2319
|
+
# Calculate ODB temperature at which COP or capacity is zero
|
2320
|
+
low_odb_at_zero_cop = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_efficiency_cop, false)
|
2321
|
+
low_odb_at_zero_capacity = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_capacity, false)
|
2322
|
+
high_odb_at_zero_cop = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_efficiency_cop, true)
|
2323
|
+
high_odb_at_zero_capacity = calculate_odb_at_zero_cop_or_capacity(data, mode, user_odbs, :gross_capacity, true)
|
2324
|
+
outdoor_dry_bulbs << [low_odb_at_zero_cop, low_odb_at_zero_capacity, compressor_lockout_temp, weather_temp].max # Min heating ODB
|
2325
|
+
outdoor_dry_bulbs << [high_odb_at_zero_cop, high_odb_at_zero_capacity, 60.0].min # Max heating ODB
|
2326
|
+
end
|
2327
|
+
capacity_description = data[0].capacity_description
|
2328
|
+
outdoor_dry_bulbs.each do |target_odb|
|
2329
|
+
next if user_odbs.include? target_odb
|
2330
|
+
|
2331
|
+
if mode == :clg
|
2332
|
+
new_dp = HPXML::CoolingPerformanceDataPoint.new(nil)
|
2333
|
+
else
|
2334
|
+
new_dp = HPXML::HeatingPerformanceDataPoint.new(nil)
|
2335
|
+
end
|
2336
|
+
new_dp.outdoor_temperature = target_odb
|
2337
|
+
new_dp.gross_capacity = interpolate_to_odb_table_point(data, capacity_description, target_odb, :gross_capacity)
|
2338
|
+
new_dp.gross_efficiency_cop = interpolate_to_odb_table_point(data, capacity_description, target_odb, :gross_efficiency_cop)
|
2339
|
+
data << new_dp
|
2340
|
+
end
|
2341
|
+
end
|
1951
2342
|
end
|
1952
2343
|
|
1953
|
-
def self.
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
2344
|
+
def self.calculate_odb_at_zero_cop_or_capacity(data, _mode, user_odbs, property, find_high)
|
2345
|
+
if find_high
|
2346
|
+
odb_dp1 = data.find { |dp| dp.outdoor_temperature == user_odbs[-1] }
|
2347
|
+
odb_dp2 = data.find { |dp| dp.outdoor_temperature == user_odbs[-2] }
|
2348
|
+
else
|
2349
|
+
odb_dp1 = data.find { |dp| dp.outdoor_temperature == user_odbs[0] }
|
2350
|
+
odb_dp2 = data.find { |dp| dp.outdoor_temperature == user_odbs[1] }
|
2351
|
+
end
|
1957
2352
|
|
1958
|
-
|
2353
|
+
slope = (odb_dp1.send(property) - odb_dp2.send(property)) / (odb_dp1.outdoor_temperature - odb_dp2.outdoor_temperature)
|
1959
2354
|
|
1960
|
-
#
|
1961
|
-
if
|
1962
|
-
|
1963
|
-
elsif
|
1964
|
-
|
2355
|
+
# Datapoints don't trend toward zero COP?
|
2356
|
+
if (find_high && slope >= 0)
|
2357
|
+
return 999999.0
|
2358
|
+
elsif (!find_high && slope <= 0)
|
2359
|
+
return -999999.0
|
1965
2360
|
end
|
1966
2361
|
|
1967
|
-
|
1968
|
-
|
1969
|
-
eir = eir_nom / cop_ratios[i]
|
1970
|
-
cops_net << calc_cop_from_eir(eir, fan_power_rated)
|
1971
|
-
end
|
2362
|
+
intercept = odb_dp2.send(property) - (slope * odb_dp2.outdoor_temperature)
|
2363
|
+
target_odb = -intercept / slope
|
1972
2364
|
|
1973
|
-
|
2365
|
+
# Return a slightly larger (or smaller, for cooling) ODB so things don't blow up
|
2366
|
+
delta_odb = 1.0
|
2367
|
+
if find_high
|
2368
|
+
return target_odb - delta_odb
|
2369
|
+
else
|
2370
|
+
return target_odb + delta_odb
|
2371
|
+
end
|
1974
2372
|
end
|
1975
2373
|
|
1976
|
-
def self.
|
1977
|
-
|
2374
|
+
def self.interpolate_to_odb_table_point(detailed_performance_data, capacity_description, target_odb, property)
|
2375
|
+
data = detailed_performance_data.select { |dp| dp.capacity_description == capacity_description }
|
1978
2376
|
|
1979
|
-
|
1980
|
-
|
2377
|
+
target_dp = data.find { |dp| dp.outdoor_temperature == target_odb }
|
2378
|
+
if not target_dp.nil?
|
2379
|
+
return target_dp.send(property)
|
2380
|
+
end
|
1981
2381
|
|
1982
|
-
#
|
1983
|
-
|
2382
|
+
# Property can be :capacity, :efficiency_cop, etc.
|
2383
|
+
user_odbs = data.map { |dp| dp.outdoor_temperature }.uniq.sort
|
1984
2384
|
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
2385
|
+
right_odb = user_odbs.find { |e| e > target_odb }
|
2386
|
+
left_odb = user_odbs.reverse.find { |e| e < target_odb }
|
2387
|
+
if right_odb.nil?
|
2388
|
+
# extrapolation
|
2389
|
+
right_odb = user_odbs[-1]
|
2390
|
+
left_odb = user_odbs[-2]
|
2391
|
+
elsif left_odb.nil?
|
2392
|
+
# extrapolation
|
2393
|
+
right_odb = user_odbs[1]
|
2394
|
+
left_odb = user_odbs[0]
|
2395
|
+
end
|
2396
|
+
right_dp = data.find { |dp| dp.outdoor_temperature == right_odb }
|
2397
|
+
left_dp = data.find { |dp| dp.outdoor_temperature == left_odb }
|
1988
2398
|
|
1989
|
-
|
2399
|
+
slope = (right_dp.send(property) - left_dp.send(property)) / (right_odb - left_odb)
|
2400
|
+
val = (target_odb - left_odb) * slope + left_dp.send(property)
|
2401
|
+
return val
|
1990
2402
|
end
|
1991
2403
|
|
1992
|
-
def self.
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
|
1997
|
-
eer_b = 20.0
|
1998
|
-
|
1999
|
-
# Iterate
|
2000
|
-
iter_max = 100
|
2001
|
-
tol = 0.0001
|
2404
|
+
def self.add_data_point_adaptive_step_size(data_array, mode, tol = 0.1)
|
2405
|
+
data_array.each do |data|
|
2406
|
+
data_sorted = data.sort_by { |dp| dp.outdoor_temperature }
|
2407
|
+
data_sorted.each_with_index do |dp, i|
|
2408
|
+
next unless i < (data_sorted.size - 1)
|
2002
2409
|
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2023
|
-
|
2024
|
-
|
2025
|
-
|
2026
|
-
|
2027
|
-
|
2028
|
-
if err > tol
|
2029
|
-
fail 'Two-speed cooling eers iteration failed to converge.'
|
2030
|
-
end
|
2031
|
-
|
2032
|
-
return calc_eers_from_eir_2speed(eer_c, fan_power_rated)
|
2033
|
-
end
|
2034
|
-
|
2035
|
-
def self.calc_eers_cooling_4speed(seer, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
|
2036
|
-
# Iterate to find rated net eers given Seer using simple bisection method for two stage and variable speed air conditioners
|
2037
|
-
|
2038
|
-
# Initial large bracket of eer (A condition) to span possible seer range
|
2039
|
-
eer_a = 5.0
|
2040
|
-
eer_b = 30.0
|
2041
|
-
|
2042
|
-
# Iterate
|
2043
|
-
iter_max = 100
|
2044
|
-
tol = 0.0001
|
2045
|
-
|
2046
|
-
err = 1
|
2047
|
-
eer_c = (eer_a + eer_b) / 2.0
|
2048
|
-
for _n in 1..iter_max
|
2049
|
-
eers = calc_eers_from_eir_4speed(eer_a, fan_power_rated, 'seer')
|
2050
|
-
f_a = calc_seer_4speed(eers, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - seer
|
2051
|
-
|
2052
|
-
eers = calc_eers_from_eir_4speed(eer_c, fan_power_rated, 'seer')
|
2053
|
-
f_c = calc_seer_4speed(eers, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - seer
|
2054
|
-
|
2055
|
-
if f_c == 0
|
2056
|
-
return eer_c
|
2057
|
-
elsif f_a * f_c < 0
|
2058
|
-
eer_b = eer_c
|
2059
|
-
else
|
2060
|
-
eer_a = eer_c
|
2061
|
-
end
|
2062
|
-
|
2063
|
-
eer_c = (eer_a + eer_b) / 2.0
|
2064
|
-
err = (eer_b - eer_a) / 2.0
|
2065
|
-
|
2066
|
-
if err <= tol
|
2067
|
-
break
|
2068
|
-
end
|
2069
|
-
end
|
2070
|
-
|
2071
|
-
if err > tol
|
2072
|
-
fail 'Variable-speed cooling eers iteration failed to converge.'
|
2073
|
-
end
|
2074
|
-
|
2075
|
-
return calc_eers_from_eir_4speed(eer_c, fan_power_rated, 'model')
|
2076
|
-
end
|
2077
|
-
|
2078
|
-
def self.calc_seer_2speed(eers, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
|
2079
|
-
eir_A2 = calc_eir_from_eer(eers[1], fan_power_rated)
|
2080
|
-
eir_B2 = eir_A2 * MathTools.biquadratic(67.0, 82.0, coeff_eir[1])
|
2081
|
-
|
2082
|
-
eir_A1 = calc_eir_from_eer(eers[0], fan_power_rated)
|
2083
|
-
eir_B1 = eir_A1 * MathTools.biquadratic(67.0, 82.0, coeff_eir[0])
|
2084
|
-
eir_F1 = eir_A1 * MathTools.biquadratic(67.0, 67.0, coeff_eir[0])
|
2085
|
-
|
2086
|
-
q_A2 = 1.0
|
2087
|
-
q_B2 = q_A2 * MathTools.biquadratic(67.0, 82.0, coeff_q[1])
|
2088
|
-
|
2089
|
-
q_B1 = q_A2 * capacity_ratios[0] * MathTools.biquadratic(67.0, 82.0, coeff_q[0])
|
2090
|
-
q_F1 = q_A2 * capacity_ratios[0] * MathTools.biquadratic(67.0, 67.0, coeff_q[0])
|
2091
|
-
|
2092
|
-
cfm_Btu_h = 400.0 / 12000.0
|
2093
|
-
|
2094
|
-
q_A2_net = q_A2 - fan_power_rated * 3.412 * cfm_Btu_h
|
2095
|
-
q_B2_net = q_B2 - fan_power_rated * 3.412 * cfm_Btu_h
|
2096
|
-
q_B1_net = q_B1 - fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[0]
|
2097
|
-
q_F1_net = q_F1 - fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[0]
|
2098
|
-
|
2099
|
-
p_A2 = (q_A2 * eir_A2) / 3.412 + fan_power_rated * cfm_Btu_h
|
2100
|
-
p_B2 = (q_B2 * eir_B2) / 3.412 + fan_power_rated * cfm_Btu_h
|
2101
|
-
p_B1 = (q_B1 * eir_B1) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[0]
|
2102
|
-
p_F1 = (q_F1 * eir_F1) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[0]
|
2103
|
-
|
2104
|
-
t_bins = [67.0, 72.0, 77.0, 82.0, 87.0, 92.0, 97.0, 102.0]
|
2105
|
-
frac_hours = [0.214, 0.231, 0.216, 0.161, 0.104, 0.052, 0.018, 0.004]
|
2106
|
-
|
2107
|
-
e_tot = 0.0
|
2108
|
-
q_tot = 0.0
|
2109
|
-
(0..7).each do |i|
|
2110
|
-
bL_i = ((t_bins[i] - 65.0) / (95.0 - 65.0)) * (q_A2_net / 1.1)
|
2111
|
-
q_low_i = q_F1_net + ((q_B1_net - q_F1_net) / (82.0 - 67.0)) * (t_bins[i] - 67.0)
|
2112
|
-
e_low_i = p_F1 + ((p_B1 - p_F1) / (82.0 - 67.0)) * (t_bins[i] - 67.0)
|
2113
|
-
q_high_i = q_B2_net + ((q_A2_net - q_B2_net) / (95.0 - 82.0)) * (t_bins[i] - 82.0)
|
2114
|
-
e_high_i = p_B2 + ((p_A2 - p_B2) / (95.0 - 82.0)) * (t_bins[i] - 82.0)
|
2115
|
-
if q_low_i >= bL_i
|
2116
|
-
pLF_i = 1.0 - c_d * (1.0 - (bL_i / q_low_i))
|
2117
|
-
q_i = bL_i * frac_hours[i]
|
2118
|
-
e_i = (((bL_i / q_low_i) * e_low_i) / pLF_i) * frac_hours[i]
|
2119
|
-
elsif (q_low_i < bL_i) && (bL_i < q_high_i)
|
2120
|
-
x_i = (q_high_i - bL_i) / (q_high_i - q_low_i)
|
2121
|
-
q_i = (x_i * q_low_i + (1.0 - x_i) * q_high_i) * frac_hours[i]
|
2122
|
-
e_i = (x_i * e_low_i + (1.0 - x_i) * e_high_i) * frac_hours[i]
|
2123
|
-
elsif q_high_i <= bL_i
|
2124
|
-
q_i = q_high_i * frac_hours[i]
|
2125
|
-
e_i = e_high_i * frac_hours[i]
|
2126
|
-
end
|
2127
|
-
|
2128
|
-
e_tot += e_i
|
2129
|
-
q_tot += q_i
|
2130
|
-
end
|
2131
|
-
|
2132
|
-
seer = q_tot / e_tot
|
2133
|
-
return seer
|
2134
|
-
end
|
2135
|
-
|
2136
|
-
def self.calc_seer_4speed(eers, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
|
2137
|
-
n_max = 2
|
2138
|
-
n_int = 1
|
2139
|
-
n_min = 0
|
2140
|
-
|
2141
|
-
wBin = 67.0
|
2142
|
-
tout_B = 82.0
|
2143
|
-
tout_E = 87.0
|
2144
|
-
tout_F = 67.0
|
2145
|
-
|
2146
|
-
eir_A2 = calc_eir_from_eer(eers[n_max], fan_power_rated)
|
2147
|
-
eir_B2 = eir_A2 * MathTools.biquadratic(wBin, tout_B, coeff_eir[n_max])
|
2148
|
-
|
2149
|
-
eir_Av = calc_eir_from_eer(eers[n_int], fan_power_rated)
|
2150
|
-
eir_Ev = eir_Av * MathTools.biquadratic(wBin, tout_E, coeff_eir[n_int])
|
2151
|
-
|
2152
|
-
eir_A1 = calc_eir_from_eer(eers[n_min], fan_power_rated)
|
2153
|
-
eir_B1 = eir_A1 * MathTools.biquadratic(wBin, tout_B, coeff_eir[n_min])
|
2154
|
-
eir_F1 = eir_A1 * MathTools.biquadratic(wBin, tout_F, coeff_eir[n_min])
|
2155
|
-
|
2156
|
-
q_A2 = capacity_ratios[n_max]
|
2157
|
-
q_B2 = q_A2 * MathTools.biquadratic(wBin, tout_B, coeff_q[n_max])
|
2158
|
-
q_Ev = capacity_ratios[n_int] * MathTools.biquadratic(wBin, tout_E, coeff_q[n_int])
|
2159
|
-
q_B1 = capacity_ratios[n_min] * MathTools.biquadratic(wBin, tout_B, coeff_q[n_min])
|
2160
|
-
q_F1 = capacity_ratios[n_min] * MathTools.biquadratic(wBin, tout_F, coeff_q[n_min])
|
2161
|
-
|
2162
|
-
cfm_Btu_h = 400.0 / 12000.0
|
2163
|
-
|
2164
|
-
q_A2_net = q_A2 - fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_max]
|
2165
|
-
q_B2_net = q_B2 - fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_max]
|
2166
|
-
q_Ev_net = q_Ev - fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_int]
|
2167
|
-
q_B1_net = q_B1 - fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_min]
|
2168
|
-
q_F1_net = q_F1 - fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_min]
|
2169
|
-
|
2170
|
-
p_A2 = (q_A2 * eir_A2) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[n_max]
|
2171
|
-
p_B2 = (q_B2 * eir_B2) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[n_max]
|
2172
|
-
p_Ev = (q_Ev * eir_Ev) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[n_int]
|
2173
|
-
p_B1 = (q_B1 * eir_B1) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[n_min]
|
2174
|
-
p_F1 = (q_F1 * eir_F1) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[n_min]
|
2175
|
-
|
2176
|
-
q_k1_87 = q_F1_net + (q_B1_net - q_F1_net) / (82.0 - 67.0) * (87.0 - 67.0)
|
2177
|
-
q_k2_87 = q_B2_net + (q_A2_net - q_B2_net) / (95.0 - 82.0) * (87.0 - 82.0)
|
2178
|
-
n_Q = (q_Ev_net - q_k1_87) / (q_k2_87 - q_k1_87)
|
2179
|
-
m_Q = (q_B1_net - q_F1_net) / (82.0 - 67.0) * (1.0 - n_Q) + (q_A2_net - q_B2_net) / (95.0 - 82.0) * n_Q
|
2180
|
-
p_k1_87 = p_F1 + (p_B1 - p_F1) / (82.0 - 67.0) * (87.0 - 67.0)
|
2181
|
-
p_k2_87 = p_B2 + (p_A2 - p_B2) / (95.0 - 82.0) * (87.0 - 82.0)
|
2182
|
-
n_E = (p_Ev - p_k1_87) / (p_k2_87 - p_k1_87)
|
2183
|
-
m_E = (p_B1 - p_F1) / (82.0 - 67.0) * (1.0 - n_E) + (p_A2 - p_B2) / (95.0 - 82.0) * n_E
|
2184
|
-
|
2185
|
-
c_T_1_1 = q_A2_net / (1.1 * (95.0 - 65.0))
|
2186
|
-
c_T_1_2 = q_F1_net
|
2187
|
-
c_T_1_3 = (q_B1_net - q_F1_net) / (82.0 - 67.0)
|
2188
|
-
t_1 = (c_T_1_2 - 67.0 * c_T_1_3 + 65.0 * c_T_1_1) / (c_T_1_1 - c_T_1_3)
|
2189
|
-
q_T_1 = q_F1_net + (q_B1_net - q_F1_net) / (82.0 - 67.0) * (t_1 - 67.0)
|
2190
|
-
p_T_1 = p_F1 + (p_B1 - p_F1) / (82.0 - 67.0) * (t_1 - 67.0)
|
2191
|
-
eer_T_1 = q_T_1 / p_T_1
|
2192
|
-
|
2193
|
-
t_v = (q_Ev_net - 87.0 * m_Q + 65.0 * c_T_1_1) / (c_T_1_1 - m_Q)
|
2194
|
-
q_T_v = q_Ev_net + m_Q * (t_v - 87.0)
|
2195
|
-
p_T_v = p_Ev + m_E * (t_v - 87.0)
|
2196
|
-
eer_T_v = q_T_v / p_T_v
|
2197
|
-
|
2198
|
-
c_T_2_1 = c_T_1_1
|
2199
|
-
c_T_2_2 = q_B2_net
|
2200
|
-
c_T_2_3 = (q_A2_net - q_B2_net) / (95.0 - 82.0)
|
2201
|
-
t_2 = (c_T_2_2 - 82.0 * c_T_2_3 + 65.0 * c_T_2_1) / (c_T_2_1 - c_T_2_3)
|
2202
|
-
q_T_2 = q_B2_net + (q_A2_net - q_B2_net) / (95.0 - 82.0) * (t_2 - 82.0)
|
2203
|
-
p_T_2 = p_B2 + (p_A2 - p_B2) / (95.0 - 82.0) * (t_2 - 82.0)
|
2204
|
-
eer_T_2 = q_T_2 / p_T_2
|
2205
|
-
|
2206
|
-
d = (t_2**2.0 - t_1**2.0) / (t_v**2.0 - t_1**2.0)
|
2207
|
-
b = (eer_T_1 - eer_T_2 - d * (eer_T_1 - eer_T_v)) / (t_1 - t_2 - d * (t_1 - t_v))
|
2208
|
-
c = (eer_T_1 - eer_T_2 - b * (t_1 - t_2)) / (t_1**2.0 - t_2**2.0)
|
2209
|
-
a = eer_T_2 - b * t_2 - c * t_2**2.0
|
2210
|
-
|
2211
|
-
t_bins = [67.0, 72.0, 77.0, 82.0, 87.0, 92.0, 97.0, 102.0]
|
2212
|
-
frac_hours = [0.214, 0.231, 0.216, 0.161, 0.104, 0.052, 0.018, 0.004]
|
2213
|
-
|
2214
|
-
e_tot = 0.0
|
2215
|
-
q_tot = 0.0
|
2216
|
-
(0..7).each do |i|
|
2217
|
-
bL = ((t_bins[i] - 65.0) / (95.0 - 65.0)) * (q_A2_net / 1.1)
|
2218
|
-
q_k1 = q_F1_net + (q_B1_net - q_F1_net) / (82.0 - 67.0) * (t_bins[i] - 67.0)
|
2219
|
-
p_k1 = p_F1 + (p_B1 - p_F1) / (82.0 - 67.0) * (t_bins[i] - 67)
|
2220
|
-
q_k2 = q_B2_net + (q_A2_net - q_B2_net) / (95.0 - 82.0) * (t_bins[i] - 82.0)
|
2221
|
-
p_k2 = p_B2 + (p_A2 - p_B2) / (95.0 - 82.0) * (t_bins[i] - 82.0)
|
2222
|
-
|
2223
|
-
if bL <= q_k1
|
2224
|
-
x_k1 = bL / q_k1
|
2225
|
-
q_Tj_N = x_k1 * q_k1 * frac_hours[i]
|
2226
|
-
e_Tj_N = x_k1 * p_k1 * frac_hours[i] / (1.0 - c_d * (1.0 - x_k1))
|
2227
|
-
elsif (q_k1 < bL) && (bL <= q_k2)
|
2228
|
-
q_Tj_N = bL * frac_hours[i]
|
2229
|
-
eer_T_j = a + b * t_bins[i] + c * t_bins[i]**2.0
|
2230
|
-
e_Tj_N = q_Tj_N / eer_T_j
|
2231
|
-
else
|
2232
|
-
q_Tj_N = frac_hours[i] * q_k2
|
2233
|
-
e_Tj_N = frac_hours[i] * p_k2
|
2234
|
-
end
|
2235
|
-
|
2236
|
-
q_tot += q_Tj_N
|
2237
|
-
e_tot += e_Tj_N
|
2238
|
-
end
|
2239
|
-
|
2240
|
-
seer = q_tot / e_tot
|
2241
|
-
return seer
|
2242
|
-
end
|
2243
|
-
|
2244
|
-
def self.calc_cop_heating_1speed(hspf, c_d, fan_power_rated, coeff_eir, coeff_q)
|
2245
|
-
# Iterate to find rated net cop given HSPF using simple bisection method
|
2246
|
-
|
2247
|
-
# Initial large bracket to span possible hspf range
|
2248
|
-
cop_a = 0.1
|
2249
|
-
cop_b = 10.0
|
2250
|
-
|
2251
|
-
# Iterate
|
2252
|
-
iter_max = 100
|
2253
|
-
tol = 0.0001
|
2254
|
-
|
2255
|
-
err = 1
|
2256
|
-
cop_c = (cop_a + cop_b) / 2.0
|
2257
|
-
for _n in 1..iter_max
|
2258
|
-
f_a = calc_hspf_1speed(cop_a, c_d, fan_power_rated, coeff_eir, coeff_q) - hspf
|
2259
|
-
f_c = calc_hspf_1speed(cop_c, c_d, fan_power_rated, coeff_eir, coeff_q) - hspf
|
2260
|
-
|
2261
|
-
if f_c == 0
|
2262
|
-
return cop_c
|
2263
|
-
elsif f_a * f_c < 0
|
2264
|
-
cop_b = cop_c
|
2265
|
-
else
|
2266
|
-
cop_a = cop_c
|
2267
|
-
end
|
2268
|
-
|
2269
|
-
cop_c = (cop_a + cop_b) / 2.0
|
2270
|
-
err = (cop_b - cop_a) / 2.0
|
2271
|
-
|
2272
|
-
if err <= tol
|
2273
|
-
break
|
2274
|
-
end
|
2275
|
-
end
|
2276
|
-
|
2277
|
-
if err > tol
|
2278
|
-
fail 'Single-speed heating cop iteration failed to converge.'
|
2279
|
-
end
|
2280
|
-
|
2281
|
-
return cop_c
|
2282
|
-
end
|
2283
|
-
|
2284
|
-
def self.calc_cops_heating_2speed(hspf, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
|
2285
|
-
# Iterate to find rated net eers given Seer using simple bisection method for two stage air conditioners
|
2286
|
-
|
2287
|
-
# Initial large bracket of cop to span possible hspf range
|
2288
|
-
cop_a = 1.0
|
2289
|
-
cop_b = 10.0
|
2290
|
-
|
2291
|
-
# Iterate
|
2292
|
-
iter_max = 100
|
2293
|
-
tol = 0.0001
|
2294
|
-
|
2295
|
-
err = 1
|
2296
|
-
cop_c = (cop_a + cop_b) / 2.0
|
2297
|
-
for _n in 1..iter_max
|
2298
|
-
cops = calc_cops_from_eir_2speed(cop_a, fan_power_rated)
|
2299
|
-
f_a = calc_hspf_2speed(cops, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - hspf
|
2300
|
-
|
2301
|
-
cops = calc_cops_from_eir_2speed(cop_c, fan_power_rated)
|
2302
|
-
f_c = calc_hspf_2speed(cops, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - hspf
|
2303
|
-
|
2304
|
-
if f_c == 0
|
2305
|
-
return cop_c
|
2306
|
-
elsif f_a * f_c < 0
|
2307
|
-
cop_b = cop_c
|
2308
|
-
else
|
2309
|
-
cop_a = cop_c
|
2310
|
-
end
|
2311
|
-
|
2312
|
-
cop_c = (cop_a + cop_b) / 2.0
|
2313
|
-
err = (cop_b - cop_a) / 2.0
|
2314
|
-
|
2315
|
-
if err <= tol
|
2316
|
-
break
|
2317
|
-
end
|
2318
|
-
end
|
2319
|
-
|
2320
|
-
if err > tol
|
2321
|
-
fail 'Two-speed heating cop iteration failed to converge.'
|
2322
|
-
end
|
2323
|
-
|
2324
|
-
return calc_cops_from_eir_2speed(cop_c, fan_power_rated)
|
2325
|
-
end
|
2326
|
-
|
2327
|
-
def self.calc_cops_heating_4speed(hspf, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
|
2328
|
-
# Iterate to find rated net cops given HSPF using simple bisection method for variable speed heat pumps
|
2329
|
-
|
2330
|
-
# Initial large bracket of cop to span possible hspf range
|
2331
|
-
cop_a = 1.0
|
2332
|
-
cop_b = 15.0
|
2333
|
-
|
2334
|
-
# Iterate
|
2335
|
-
iter_max = 100
|
2336
|
-
tol = 0.0001
|
2337
|
-
|
2338
|
-
err = 1
|
2339
|
-
cop_c = (cop_a + cop_b) / 2.0
|
2340
|
-
for _n in 1..iter_max
|
2341
|
-
cops = calc_cops_from_eir_4speed(cop_a, fan_power_rated, calc_type: 'hspf')
|
2342
|
-
f_a = calc_hspf_4speed(cops, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - hspf
|
2343
|
-
|
2344
|
-
cops = calc_cops_from_eir_4speed(cop_c, fan_power_rated, calc_type: 'hspf')
|
2345
|
-
f_c = calc_hspf_4speed(cops, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - hspf
|
2346
|
-
|
2347
|
-
if f_c == 0
|
2348
|
-
return cop_c
|
2349
|
-
elsif f_a * f_c < 0
|
2350
|
-
cop_b = cop_c
|
2351
|
-
else
|
2352
|
-
cop_a = cop_c
|
2353
|
-
end
|
2354
|
-
|
2355
|
-
cop_c = (cop_a + cop_b) / 2.0
|
2356
|
-
err = (cop_b - cop_a) / 2.0
|
2357
|
-
|
2358
|
-
if err <= tol
|
2359
|
-
break
|
2360
|
-
end
|
2361
|
-
end
|
2362
|
-
|
2363
|
-
if err > tol
|
2364
|
-
fail 'Variable-speed heating cops iteration failed to converge.'
|
2365
|
-
end
|
2366
|
-
|
2367
|
-
return calc_cops_from_eir_4speed(cop_c, fan_power_rated, calc_type: 'model')
|
2368
|
-
end
|
2369
|
-
|
2370
|
-
def self.calc_hspf_1speed(cop_47, c_d, fan_power_rated, coeff_eir, coeff_q)
|
2371
|
-
eir_47 = calc_eir_from_cop(cop_47, fan_power_rated)
|
2372
|
-
eir_35 = eir_47 * MathTools.biquadratic(70.0, 35.0, coeff_eir[0])
|
2373
|
-
eir_17 = eir_47 * MathTools.biquadratic(70.0, 17.0, coeff_eir[0])
|
2374
|
-
|
2375
|
-
q_47 = 1.0
|
2376
|
-
q_35 = 0.7519
|
2377
|
-
q_17 = q_47 * MathTools.biquadratic(70.0, 17.0, coeff_q[0])
|
2378
|
-
|
2379
|
-
cfm_Btu_h = 400.0 / 12000.0
|
2380
|
-
|
2381
|
-
q_47_net = q_47 + fan_power_rated * 3.412 * cfm_Btu_h
|
2382
|
-
q_35_net = q_35 + fan_power_rated * 3.412 * cfm_Btu_h
|
2383
|
-
q_17_net = q_17 + fan_power_rated * 3.412 * cfm_Btu_h
|
2384
|
-
|
2385
|
-
p_47 = (q_47 * eir_47) / 3.412 + fan_power_rated * cfm_Btu_h
|
2386
|
-
p_35 = (q_35 * eir_35) / 3.412 + fan_power_rated * cfm_Btu_h
|
2387
|
-
p_17 = (q_17 * eir_17) / 3.412 + fan_power_rated * cfm_Btu_h
|
2388
|
-
|
2389
|
-
t_bins = [62.0, 57.0, 52.0, 47.0, 42.0, 37.0, 32.0, 27.0, 22.0, 17.0, 12.0, 7.0, 2.0, -3.0, -8.0]
|
2390
|
-
frac_hours = [0.132, 0.111, 0.103, 0.093, 0.100, 0.109, 0.126, 0.087, 0.055, 0.036, 0.026, 0.013, 0.006, 0.002, 0.001]
|
2391
|
-
|
2392
|
-
designtemp = 5.0
|
2393
|
-
t_off = 10.0
|
2394
|
-
t_on = 14.0
|
2395
|
-
ptot = 0.0
|
2396
|
-
rHtot = 0.0
|
2397
|
-
bLtot = 0.0
|
2398
|
-
dHRmin = q_47
|
2399
|
-
(0..14).each do |i|
|
2400
|
-
bL = ((65.0 - t_bins[i]) / (65.0 - designtemp)) * 0.77 * dHRmin
|
2401
|
-
|
2402
|
-
if (t_bins[i] > 17.0) && (t_bins[i] < 45.0)
|
2403
|
-
q_h = q_17_net + (((q_35_net - q_17_net) * (t_bins[i] - 17.0)) / (35.0 - 17.0))
|
2404
|
-
p_h = p_17 + (((p_35 - p_17) * (t_bins[i] - 17.0)) / (35.0 - 17.0))
|
2405
|
-
else
|
2406
|
-
q_h = q_17_net + (((q_47_net - q_17_net) * (t_bins[i] - 17.0)) / (47.0 - 17.0))
|
2407
|
-
p_h = p_17 + (((p_47 - p_17) * (t_bins[i] - 17.0)) / (47.0 - 17.0))
|
2408
|
-
end
|
2409
|
-
|
2410
|
-
x_t = [bL / q_h, 1.0].min
|
2411
|
-
|
2412
|
-
pLF = 1.0 - (c_d * (1.0 - x_t))
|
2413
|
-
if (t_bins[i] <= t_off) || (q_h / (3.412 * p_h) < 1.0)
|
2414
|
-
sigma_t = 0.0
|
2415
|
-
elsif (t_off < t_bins[i]) && (t_bins[i] <= t_on) && (q_h / (p_h * 3.412) >= 1.0)
|
2416
|
-
sigma_t = 0.5
|
2417
|
-
elsif (t_bins[i] > t_on) && (q_h / (3.412 * p_h) >= 1.0)
|
2418
|
-
sigma_t = 1.0
|
2410
|
+
cap_diff = data_sorted[i + 1].gross_capacity - dp.gross_capacity
|
2411
|
+
odb_diff = data_sorted[i + 1].outdoor_temperature - dp.outdoor_temperature
|
2412
|
+
cop_diff = data_sorted[i + 1].gross_efficiency_cop - dp.gross_efficiency_cop
|
2413
|
+
if mode == :clg
|
2414
|
+
eir_rated = 1 / data_sorted.find { |dp| dp.outdoor_temperature == HVAC::AirSourceCoolRatedODB }.gross_efficiency_cop
|
2415
|
+
else
|
2416
|
+
eir_rated = 1 / data_sorted.find { |dp| dp.outdoor_temperature == HVAC::AirSourceHeatRatedODB }.gross_efficiency_cop
|
2417
|
+
end
|
2418
|
+
eir_diff = ((1 / data_sorted[i + 1].gross_efficiency_cop) / eir_rated) - ((1 / dp.gross_efficiency_cop) / eir_rated)
|
2419
|
+
n_pt = (eir_diff.abs / tol).ceil() - 1
|
2420
|
+
eir_interval = eir_diff / (n_pt + 1)
|
2421
|
+
next if n_pt < 1
|
2422
|
+
|
2423
|
+
for i in 1..n_pt
|
2424
|
+
if mode == :clg
|
2425
|
+
new_dp = HPXML::CoolingPerformanceDataPoint.new(nil)
|
2426
|
+
else
|
2427
|
+
new_dp = HPXML::HeatingPerformanceDataPoint.new(nil)
|
2428
|
+
end
|
2429
|
+
new_eir_normalized = (1 / dp.gross_efficiency_cop) / eir_rated + eir_interval * i
|
2430
|
+
new_dp.gross_efficiency_cop = (1 / (new_eir_normalized * eir_rated))
|
2431
|
+
new_dp.outdoor_temperature = odb_diff / cop_diff * (new_dp.gross_efficiency_cop - dp.gross_efficiency_cop) + dp.outdoor_temperature
|
2432
|
+
new_dp.gross_capacity = cap_diff / odb_diff * (new_dp.outdoor_temperature - dp.outdoor_temperature) + dp.gross_capacity
|
2433
|
+
data << new_dp
|
2434
|
+
end
|
2419
2435
|
end
|
2420
|
-
|
2421
|
-
p_h_i = (x_t * p_h * sigma_t / pLF) * frac_hours[i]
|
2422
|
-
rH_i = ((bL - (x_t * q_h * sigma_t)) / 3.412) * frac_hours[i]
|
2423
|
-
bL_i = bL * frac_hours[i]
|
2424
|
-
ptot += p_h_i
|
2425
|
-
rHtot += rH_i
|
2426
|
-
bLtot += bL_i
|
2427
2436
|
end
|
2428
|
-
|
2429
|
-
hspf = bLtot / (ptot + rHtot)
|
2430
|
-
return hspf
|
2431
2437
|
end
|
2432
2438
|
|
2433
|
-
def self.
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
q_H47_net = q_H47 + fan_power_rated * 3.412 * cfm_Btu_h
|
2455
|
-
q_H35_net = q_H35 + fan_power_rated * 3.412 * cfm_Btu_h
|
2456
|
-
q_H17_net = q_H17 + fan_power_rated * 3.412 * cfm_Btu_h
|
2457
|
-
q_L62_net = q_L62 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[0]
|
2458
|
-
q_L47_net = q_L47 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[0]
|
2459
|
-
q_L35_net = q_L35 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[0]
|
2460
|
-
q_L17_net = q_L17 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[0]
|
2461
|
-
|
2462
|
-
p_H47 = (q_H47 * eir_47_H) / 3.412 + fan_power_rated * cfm_Btu_h
|
2463
|
-
p_H35 = (q_H35 * eir_35_H) / 3.412 + fan_power_rated * cfm_Btu_h
|
2464
|
-
p_H17 = (q_H17 * eir_17_H) / 3.412 + fan_power_rated * cfm_Btu_h
|
2465
|
-
p_L62 = (q_L62 * eir_62_L) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[0]
|
2466
|
-
p_L47 = (q_L47 * eir_47_L) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[0]
|
2467
|
-
p_L35 = (q_L35 * eir_35_L) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[0]
|
2468
|
-
p_L17 = (q_L17 * eir_17_L) / 3.412 + fan_power_rated * cfm_Btu_h * fanspeed_ratios[0]
|
2469
|
-
|
2470
|
-
t_bins = [62.0, 57.0, 52.0, 47.0, 42.0, 37.0, 32.0, 27.0, 22.0, 17.0, 12.0, 7.0, 2.0, -3.0, -8.0]
|
2471
|
-
frac_hours = [0.132, 0.111, 0.103, 0.093, 0.100, 0.109, 0.126, 0.087, 0.055, 0.036, 0.026, 0.013, 0.006, 0.002, 0.001]
|
2472
|
-
|
2473
|
-
designtemp = 5.0
|
2474
|
-
t_off = 10.0
|
2475
|
-
t_on = 14.0
|
2476
|
-
ptot = 0.0
|
2477
|
-
rHtot = 0.0
|
2478
|
-
bLtot = 0.0
|
2479
|
-
dHRmin = q_H47
|
2480
|
-
(0..14).each do |i|
|
2481
|
-
bL = ((65.0 - t_bins[i]) / (65.0 - designtemp)) * 0.77 * dHRmin
|
2482
|
-
|
2483
|
-
if (17.0 < t_bins[i]) && (t_bins[i] < 45.0)
|
2484
|
-
q_h = q_H17_net + (((q_H35_net - q_H17_net) * (t_bins[i] - 17.0)) / (35.0 - 17.0))
|
2485
|
-
p_h = p_H17 + (((p_H35 - p_H17) * (t_bins[i] - 17.0)) / (35.0 - 17.0))
|
2486
|
-
else
|
2487
|
-
q_h = q_H17_net + (((q_H47_net - q_H17_net) * (t_bins[i] - 17.0)) / (47.0 - 17.0))
|
2488
|
-
p_h = p_H17 + (((p_H47 - p_H17) * (t_bins[i] - 17.0)) / (47.0 - 17.0))
|
2489
|
-
end
|
2490
|
-
|
2491
|
-
if t_bins[i] >= 40.0
|
2492
|
-
q_l = q_L47_net + (((q_L62_net - q_L47_net) * (t_bins[i] - 47.0)) / (62.0 - 47.0))
|
2493
|
-
p_l = p_L47 + (((p_L62 - p_L47) * (t_bins[i] - 47.0)) / (62.0 - 47.0))
|
2494
|
-
elsif (17.0 <= t_bins[i]) && (t_bins[i] < 40.0)
|
2495
|
-
q_l = q_L17_net + (((q_L35_net - q_L17_net) * (t_bins[i] - 17.0)) / (35.0 - 17.0))
|
2496
|
-
p_l = p_L17 + (((p_L35 - p_L17) * (t_bins[i] - 17.0)) / (35.0 - 17.0))
|
2497
|
-
else
|
2498
|
-
q_l = q_L17_net + (((q_L47_net - q_L17_net) * (t_bins[i] - 17.0)) / (47.0 - 17.0))
|
2499
|
-
p_l = p_L17 + (((p_L47 - p_L17) * (t_bins[i] - 17.0)) / (47.0 - 17.0))
|
2500
|
-
end
|
2501
|
-
|
2502
|
-
x_t_l = [bL / q_l, 1.0].min
|
2503
|
-
pLF = 1.0 - (c_d * (1.0 - x_t_l))
|
2504
|
-
if (t_bins[i] <= t_off) || (q_h / (p_h * 3.412) < 1.0)
|
2505
|
-
sigma_t_h = 0.0
|
2506
|
-
elsif (t_off < t_bins[i]) && (t_bins[i] <= t_on) && (q_h / (p_h * 3.412) >= 1.0)
|
2507
|
-
sigma_t_h = 0.5
|
2508
|
-
elsif (t_bins[i] > t_on) && (q_h / (p_h * 3.412) >= 1.0)
|
2509
|
-
sigma_t_h = 1.0
|
2510
|
-
end
|
2511
|
-
|
2512
|
-
if t_bins[i] <= t_off
|
2513
|
-
sigma_t_l = 0.0
|
2514
|
-
elsif (t_off < t_bins[i]) && (t_bins[i] <= t_on)
|
2515
|
-
sigma_t_l = 0.5
|
2516
|
-
elsif t_bins[i] > t_on
|
2517
|
-
sigma_t_l = 1.0
|
2518
|
-
end
|
2519
|
-
|
2520
|
-
if q_l > bL
|
2521
|
-
p_h_i = (x_t_l * p_l * sigma_t_l / pLF) * frac_hours[i]
|
2522
|
-
rH_i = (bL * (1.0 - sigma_t_l)) / 3.412 * frac_hours[i]
|
2523
|
-
elsif (q_l < bL) && (q_h > bL)
|
2524
|
-
x_t_l = ((q_h - bL) / (q_h - q_l))
|
2525
|
-
x_t_h = 1.0 - x_t_l
|
2526
|
-
p_h_i = (x_t_l * p_l + x_t_h * p_h) * sigma_t_l * frac_hours[i]
|
2527
|
-
rH_i = (bL * (1.0 - sigma_t_l)) / 3.412 * frac_hours[i]
|
2528
|
-
elsif q_h <= bL
|
2529
|
-
p_h_i = p_h * sigma_t_h * frac_hours[i]
|
2530
|
-
rH_i = (bL - (q_h * sigma_t_l)) / 3.412 * frac_hours[i]
|
2439
|
+
def self.correct_ft_cap_eir(data_array, mode)
|
2440
|
+
# Add sensitivity to indoor conditions
|
2441
|
+
# single speed cutler curve coefficients
|
2442
|
+
if mode == :clg
|
2443
|
+
cap_ft_spec_ss, eir_ft_spec_ss = get_cool_cap_eir_ft_spec(HPXML::HVACCompressorTypeSingleStage)
|
2444
|
+
rated_t_i = HVAC::AirSourceCoolRatedIWB
|
2445
|
+
indoor_t = [50.0, rated_t_i, 80.0]
|
2446
|
+
else
|
2447
|
+
# default capacity retention for single speed
|
2448
|
+
retention_temp, retention_fraction = get_default_heating_capacity_retention(HPXML::HVACCompressorTypeSingleStage)
|
2449
|
+
cap_ft_spec_ss, eir_ft_spec_ss = get_heat_cap_eir_ft_spec(HPXML::HVACCompressorTypeSingleStage, retention_temp, retention_fraction)
|
2450
|
+
rated_t_i = HVAC::AirSourceHeatRatedIDB
|
2451
|
+
indoor_t = [60.0, rated_t_i, 80.0]
|
2452
|
+
end
|
2453
|
+
data_array.each do |data|
|
2454
|
+
data.each do |dp|
|
2455
|
+
if mode == :clg
|
2456
|
+
dp.indoor_wetbulb = rated_t_i
|
2457
|
+
else
|
2458
|
+
dp.indoor_temperature = rated_t_i
|
2459
|
+
end
|
2531
2460
|
end
|
2532
|
-
|
2533
|
-
bL_i = bL * frac_hours[i]
|
2534
|
-
ptot += p_h_i
|
2535
|
-
rHtot += rH_i
|
2536
|
-
bLtot += bL_i
|
2537
2461
|
end
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2565
|
-
|
2566
|
-
|
2567
|
-
|
2568
|
-
|
2569
|
-
|
2570
|
-
cfm_Btu_h = 400.0 / 12000.0
|
2571
|
-
|
2572
|
-
q_H1_2_net = q_H1_2 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_max]
|
2573
|
-
q_H3_2_net = q_H3_2 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_max]
|
2574
|
-
q_H2_v_net = q_H2_v + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_int]
|
2575
|
-
q_H1_1_net = q_H1_1 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_min]
|
2576
|
-
q_H0_1_net = q_H0_1 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_min]
|
2577
|
-
|
2578
|
-
p_H1_2 = q_H1_2 * eir_H1_2 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_max]
|
2579
|
-
p_H3_2 = q_H3_2 * eir_H3_2 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_max]
|
2580
|
-
p_H2_v = q_H2_v * eir_H2_v + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_int]
|
2581
|
-
p_H1_1 = q_H1_1 * eir_H1_1 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_min]
|
2582
|
-
p_H0_1 = q_H0_1 * eir_H0_1 + fan_power_rated * 3.412 * cfm_Btu_h * fanspeed_ratios[n_min]
|
2583
|
-
|
2584
|
-
q_H35_2 = 0.9 * (q_H3_2_net + 0.6 * (q_H1_2_net - q_H3_2_net))
|
2585
|
-
p_H35_2 = 0.985 * (p_H3_2 + 0.6 * (p_H1_2 - p_H3_2))
|
2586
|
-
q_H35_1 = q_H1_1_net + (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (35.0 - 47.0)
|
2587
|
-
p_H35_1 = p_H1_1 + (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (35.0 - 47.0)
|
2588
|
-
n_Q = (q_H2_v_net - q_H35_1) / (q_H35_2 - q_H35_1)
|
2589
|
-
m_Q = (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (1.0 - n_Q) + n_Q * (q_H35_2 - q_H3_2_net) / (35.0 - 17.0)
|
2590
|
-
n_E = (p_H2_v - p_H35_1) / (p_H35_2 - p_H35_1)
|
2591
|
-
m_E = (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (1.0 - n_E) + n_E * (p_H35_2 - p_H3_2) / (35.0 - 17.0)
|
2592
|
-
|
2593
|
-
t_OD = 5.0
|
2594
|
-
dHR = q_H1_2_net * (65.0 - t_OD) / 60.0
|
2595
|
-
|
2596
|
-
c_T_3_1 = q_H1_1_net
|
2597
|
-
c_T_3_2 = (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0)
|
2598
|
-
c_T_3_3 = 0.77 * dHR / (65.0 - t_OD)
|
2599
|
-
t_3 = (47.0 * c_T_3_2 + 65.0 * c_T_3_3 - c_T_3_1) / (c_T_3_2 + c_T_3_3)
|
2600
|
-
q_HT3_1 = q_H1_1_net + (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (t_3 - 47.0)
|
2601
|
-
p_HT3_1 = p_H1_1 + (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (t_3 - 47.0)
|
2602
|
-
cop_T3_1 = q_HT3_1 / p_HT3_1
|
2603
|
-
|
2604
|
-
c_T_v_1 = q_H2_v_net
|
2605
|
-
c_T_v_3 = c_T_3_3
|
2606
|
-
t_v = (35.0 * m_Q + 65 * c_T_v_3 - c_T_v_1) / (m_Q + c_T_v_3)
|
2607
|
-
q_HTv_v = q_H2_v_net + m_Q * (t_v - 35.0)
|
2608
|
-
p_HTv_v = p_H2_v + m_E * (t_v - 35.0)
|
2609
|
-
cop_Tv_v = q_HTv_v / p_HTv_v
|
2610
|
-
|
2611
|
-
c_T_4_1 = q_H3_2_net
|
2612
|
-
c_T_4_2 = (q_H35_2 - q_H3_2_net) / (35.0 - 17.0)
|
2613
|
-
c_T_4_3 = c_T_v_3
|
2614
|
-
t_4 = (17.0 * c_T_4_2 + 65.0 * c_T_4_3 - c_T_4_1) / (c_T_4_2 + c_T_4_3)
|
2615
|
-
q_HT4_2 = q_H3_2_net + (q_H35_2 - q_H3_2_net) / (35.0 - 17.0) * (t_4 - 17.0)
|
2616
|
-
p_HT4_2 = p_H3_2 + (p_H35_2 - p_H3_2) / (35.0 - 17.0) * (t_4 - 17.0)
|
2617
|
-
cop_T4_2 = q_HT4_2 / p_HT4_2
|
2618
|
-
|
2619
|
-
d = (t_3**2.0 - t_4**2.0) / (t_v**2.0 - t_4**2.0)
|
2620
|
-
b = (cop_T4_2 - cop_T3_1 - d * (cop_T4_2 - cop_Tv_v)) / (t_4 - t_3 - d * (t_4 - t_v))
|
2621
|
-
c = (cop_T4_2 - cop_T3_1 - b * (t_4 - t_3)) / (t_4**2.0 - t_3**2.0)
|
2622
|
-
a = cop_T4_2 - b * t_4 - c * t_4**2.0
|
2623
|
-
|
2624
|
-
t_bins = [62.0, 57.0, 52.0, 47.0, 42.0, 37.0, 32.0, 27.0, 22.0, 17.0, 12.0, 7.0, 2.0, -3.0, -8.0]
|
2625
|
-
frac_hours = [0.132, 0.111, 0.103, 0.093, 0.100, 0.109, 0.126, 0.087, 0.055, 0.036, 0.026, 0.013, 0.006, 0.002, 0.001]
|
2626
|
-
|
2627
|
-
t_off = 10.0
|
2628
|
-
t_on = t_off + 4
|
2629
|
-
etot = 0.0
|
2630
|
-
bLtot = 0.0
|
2631
|
-
(0..14).each do |i|
|
2632
|
-
bL = ((65.0 - t_bins[i]) / (65.0 - t_OD)) * 0.77 * dHR
|
2633
|
-
|
2634
|
-
q_1 = q_H1_1_net + (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (t_bins[i] - 47.0)
|
2635
|
-
p_1 = p_H1_1 + (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (t_bins[i] - 47.0)
|
2636
|
-
|
2637
|
-
if (t_bins[i] <= 17.0) || (t_bins[i] >= 45.0)
|
2638
|
-
q_2 = q_H3_2_net + (q_H1_2_net - q_H3_2_net) * (t_bins[i] - 17.0) / (47.0 - 17.0)
|
2639
|
-
p_2 = p_H3_2 + (p_H1_2 - p_H3_2) * (t_bins[i] - 17.0) / (47.0 - 17.0)
|
2640
|
-
else
|
2641
|
-
q_2 = q_H3_2_net + (q_H35_2 - q_H3_2_net) * (t_bins[i] - 17.0) / (35.0 - 17.0)
|
2642
|
-
p_2 = p_H3_2 + (p_H35_2 - p_H3_2) * (t_bins[i] - 17.0) / (35.0 - 17.0)
|
2643
|
-
end
|
2644
|
-
|
2645
|
-
if t_bins[i] <= t_off
|
2646
|
-
delta = 0.0
|
2647
|
-
elsif t_bins[i] >= t_on
|
2648
|
-
delta = 1.0
|
2649
|
-
else
|
2650
|
-
delta = 0.5
|
2462
|
+
# table lookup output values
|
2463
|
+
data_array.each do |data|
|
2464
|
+
# create a new array to temporarily store expanded data points, to concat after the existing data loop
|
2465
|
+
array_tmp = Array.new
|
2466
|
+
indoor_t.each do |t_i|
|
2467
|
+
# introduce indoor conditions other than rated, expand to rated data points
|
2468
|
+
next if t_i == rated_t_i
|
2469
|
+
|
2470
|
+
data_tmp = Array.new
|
2471
|
+
data.each do |dp|
|
2472
|
+
dp_new = dp.dup
|
2473
|
+
data_tmp << dp_new
|
2474
|
+
if mode == :clg
|
2475
|
+
dp_new.indoor_wetbulb = t_i
|
2476
|
+
else
|
2477
|
+
dp_new.indoor_temperature = t_i
|
2478
|
+
end
|
2479
|
+
# capacity FT curve output
|
2480
|
+
cap_ft_curve_output = MathTools.biquadratic(t_i, dp_new.outdoor_temperature, cap_ft_spec_ss[0])
|
2481
|
+
cap_ft_curve_output_rated = MathTools.biquadratic(rated_t_i, dp_new.outdoor_temperature, cap_ft_spec_ss[0])
|
2482
|
+
cap_correction_factor = cap_ft_curve_output / cap_ft_curve_output_rated
|
2483
|
+
# corrected capacity hash, with two temperature independent variables
|
2484
|
+
dp_new.gross_capacity *= cap_correction_factor
|
2485
|
+
|
2486
|
+
# eir FT curve output
|
2487
|
+
eir_ft_curve_output = MathTools.biquadratic(t_i, dp_new.outdoor_temperature, eir_ft_spec_ss[0])
|
2488
|
+
eir_ft_curve_output_rated = MathTools.biquadratic(rated_t_i, dp_new.outdoor_temperature, eir_ft_spec_ss[0])
|
2489
|
+
eir_correction_factor = eir_ft_curve_output / eir_ft_curve_output_rated
|
2490
|
+
dp_new.gross_efficiency_cop /= eir_correction_factor
|
2491
|
+
end
|
2492
|
+
array_tmp << data_tmp
|
2651
2493
|
end
|
2652
|
-
|
2653
|
-
|
2654
|
-
x_1 = bL / q_1
|
2655
|
-
e_Tj_n = delta * x_1 * p_1 * frac_hours[i] / (1.0 - c_d * (1.0 - x_1))
|
2656
|
-
elsif (q_1 < bL) && (bL <= q_2)
|
2657
|
-
cop_T_j = a + b * t_bins[i] + c * t_bins[i]**2.0
|
2658
|
-
e_Tj_n = delta * frac_hours[i] * bL / cop_T_j + (1.0 - delta) * bL * (frac_hours[i])
|
2659
|
-
else
|
2660
|
-
e_Tj_n = delta * frac_hours[i] * p_2 + frac_hours[i] * (bL - delta * q_2)
|
2494
|
+
array_tmp.each do |new_data|
|
2495
|
+
data.concat(new_data)
|
2661
2496
|
end
|
2662
|
-
|
2663
|
-
bLtot += frac_hours[i] * bL
|
2664
|
-
etot += e_Tj_n
|
2665
2497
|
end
|
2666
|
-
|
2667
|
-
hspf = bLtot / (etot / 3.412)
|
2668
|
-
return hspf
|
2669
2498
|
end
|
2670
2499
|
|
2671
|
-
def self.
|
2672
|
-
fan_speed_ratios = []
|
2673
|
-
capacity_ratios.each_with_index do |capacity_ratio, i|
|
2674
|
-
fan_speed_ratios << rated_cfm_per_tons[i] * capacity_ratio / rated_airflow_rate
|
2675
|
-
end
|
2676
|
-
return fan_speed_ratios
|
2677
|
-
end
|
2678
|
-
|
2679
|
-
def self.create_curve_biquadratic_constant(model)
|
2680
|
-
curve = OpenStudio::Model::CurveBiquadratic.new(model)
|
2681
|
-
curve.setName('ConstantBiquadratic')
|
2682
|
-
curve.setCoefficient1Constant(1)
|
2683
|
-
curve.setCoefficient2x(0)
|
2684
|
-
curve.setCoefficient3xPOW2(0)
|
2685
|
-
curve.setCoefficient4y(0)
|
2686
|
-
curve.setCoefficient5yPOW2(0)
|
2687
|
-
curve.setCoefficient6xTIMESY(0)
|
2688
|
-
curve.setMinimumValueofx(-100)
|
2689
|
-
curve.setMaximumValueofx(100)
|
2690
|
-
curve.setMinimumValueofy(-100)
|
2691
|
-
curve.setMaximumValueofy(100)
|
2692
|
-
return curve
|
2693
|
-
end
|
2694
|
-
|
2695
|
-
def self.create_curve_quadratic_constant(model)
|
2696
|
-
curve = OpenStudio::Model::CurveQuadratic.new(model)
|
2697
|
-
curve.setName('ConstantQuadratic')
|
2698
|
-
curve.setCoefficient1Constant(1)
|
2699
|
-
curve.setCoefficient2x(0)
|
2700
|
-
curve.setCoefficient3xPOW2(0)
|
2701
|
-
curve.setMinimumValueofx(-100)
|
2702
|
-
curve.setMaximumValueofx(100)
|
2703
|
-
curve.setMinimumCurveOutput(-100)
|
2704
|
-
curve.setMaximumCurveOutput(100)
|
2705
|
-
return curve
|
2706
|
-
end
|
2707
|
-
|
2708
|
-
def self.create_curve_cubic_constant(model)
|
2709
|
-
curve = OpenStudio::Model::CurveCubic.new(model)
|
2710
|
-
curve.setName('ConstantCubic')
|
2711
|
-
curve.setCoefficient1Constant(1)
|
2712
|
-
curve.setCoefficient2x(0)
|
2713
|
-
curve.setCoefficient3xPOW2(0)
|
2714
|
-
curve.setCoefficient4xPOW3(0)
|
2715
|
-
curve.setMinimumValueofx(-100)
|
2716
|
-
curve.setMaximumValueofx(100)
|
2717
|
-
return curve
|
2718
|
-
end
|
2719
|
-
|
2720
|
-
def self.convert_curve_biquadratic(coeff)
|
2721
|
-
# Convert IP curves to SI curves
|
2722
|
-
si_coeff = []
|
2723
|
-
si_coeff << coeff[0] + 32.0 * (coeff[1] + coeff[3]) + 1024.0 * (coeff[2] + coeff[4] + coeff[5])
|
2724
|
-
si_coeff << 9.0 / 5.0 * coeff[1] + 576.0 / 5.0 * coeff[2] + 288.0 / 5.0 * coeff[5]
|
2725
|
-
si_coeff << 81.0 / 25.0 * coeff[2]
|
2726
|
-
si_coeff << 9.0 / 5.0 * coeff[3] + 576.0 / 5.0 * coeff[4] + 288.0 / 5.0 * coeff[5]
|
2727
|
-
si_coeff << 81.0 / 25.0 * coeff[4]
|
2728
|
-
si_coeff << 81.0 / 25.0 * coeff[5]
|
2729
|
-
return si_coeff
|
2730
|
-
end
|
2731
|
-
|
2732
|
-
def self.create_curve_biquadratic(model, coeff, name, min_x, max_x, min_y, max_y)
|
2733
|
-
curve = OpenStudio::Model::CurveBiquadratic.new(model)
|
2734
|
-
curve.setName(name)
|
2735
|
-
curve.setCoefficient1Constant(coeff[0])
|
2736
|
-
curve.setCoefficient2x(coeff[1])
|
2737
|
-
curve.setCoefficient3xPOW2(coeff[2])
|
2738
|
-
curve.setCoefficient4y(coeff[3])
|
2739
|
-
curve.setCoefficient5yPOW2(coeff[4])
|
2740
|
-
curve.setCoefficient6xTIMESY(coeff[5])
|
2741
|
-
curve.setMinimumValueofx(min_x)
|
2742
|
-
curve.setMaximumValueofx(max_x)
|
2743
|
-
curve.setMinimumValueofy(min_y)
|
2744
|
-
curve.setMaximumValueofy(max_y)
|
2745
|
-
return curve
|
2746
|
-
end
|
2747
|
-
|
2748
|
-
def self.create_curve_bicubic(model, coeff, name, min_x, max_x, min_y, max_y)
|
2749
|
-
curve = OpenStudio::Model::CurveBicubic.new(model)
|
2750
|
-
curve.setName(name)
|
2751
|
-
curve.setCoefficient1Constant(coeff[0])
|
2752
|
-
curve.setCoefficient2x(coeff[1])
|
2753
|
-
curve.setCoefficient3xPOW2(coeff[2])
|
2754
|
-
curve.setCoefficient4y(coeff[3])
|
2755
|
-
curve.setCoefficient5yPOW2(coeff[4])
|
2756
|
-
curve.setCoefficient6xTIMESY(coeff[5])
|
2757
|
-
curve.setCoefficient7xPOW3(coeff[6])
|
2758
|
-
curve.setCoefficient8yPOW3(coeff[7])
|
2759
|
-
curve.setCoefficient9xPOW2TIMESY(coeff[8])
|
2760
|
-
curve.setCoefficient10xTIMESYPOW2(coeff[9])
|
2761
|
-
curve.setMinimumValueofx(min_x)
|
2762
|
-
curve.setMaximumValueofx(max_x)
|
2763
|
-
curve.setMinimumValueofy(min_y)
|
2764
|
-
curve.setMaximumValueofy(max_y)
|
2765
|
-
return curve
|
2766
|
-
end
|
2767
|
-
|
2768
|
-
def self.create_curve_quadratic(model, coeff, name, min_x, max_x, min_y, max_y, is_dimensionless = false)
|
2769
|
-
curve = OpenStudio::Model::CurveQuadratic.new(model)
|
2770
|
-
curve.setName(name)
|
2771
|
-
curve.setCoefficient1Constant(coeff[0])
|
2772
|
-
curve.setCoefficient2x(coeff[1])
|
2773
|
-
curve.setCoefficient3xPOW2(coeff[2])
|
2774
|
-
curve.setMinimumValueofx(min_x)
|
2775
|
-
curve.setMaximumValueofx(max_x)
|
2776
|
-
if not min_y.nil?
|
2777
|
-
curve.setMinimumCurveOutput(min_y)
|
2778
|
-
end
|
2779
|
-
if not max_y.nil?
|
2780
|
-
curve.setMaximumCurveOutput(max_y)
|
2781
|
-
end
|
2782
|
-
if is_dimensionless
|
2783
|
-
curve.setInputUnitTypeforX('Dimensionless')
|
2784
|
-
curve.setOutputUnitType('Dimensionless')
|
2785
|
-
end
|
2786
|
-
return curve
|
2787
|
-
end
|
2788
|
-
|
2789
|
-
def self.create_curve_cubic(model, coeff, name, min_x, max_x, min_y, max_y)
|
2790
|
-
curve = OpenStudio::Model::CurveCubic.new(model)
|
2791
|
-
curve.setName(name)
|
2792
|
-
curve.setCoefficient1Constant(coeff[0])
|
2793
|
-
curve.setCoefficient2x(coeff[1])
|
2794
|
-
curve.setCoefficient3xPOW2(coeff[2])
|
2795
|
-
curve.setCoefficient4xPOW3(coeff[3])
|
2796
|
-
curve.setMinimumValueofx(min_x)
|
2797
|
-
curve.setMaximumValueofx(max_x)
|
2798
|
-
curve.setMinimumCurveOutput(min_y)
|
2799
|
-
curve.setMaximumCurveOutput(max_y)
|
2800
|
-
return curve
|
2801
|
-
end
|
2802
|
-
|
2803
|
-
def self.create_curve_exponent(model, coeff, name, min_x, max_x)
|
2804
|
-
curve = OpenStudio::Model::CurveExponent.new(model)
|
2805
|
-
curve.setName(name)
|
2806
|
-
curve.setCoefficient1Constant(coeff[0])
|
2807
|
-
curve.setCoefficient2Constant(coeff[1])
|
2808
|
-
curve.setCoefficient3Constant(coeff[2])
|
2809
|
-
curve.setMinimumValueofx(min_x)
|
2810
|
-
curve.setMaximumValueofx(max_x)
|
2811
|
-
return curve
|
2812
|
-
end
|
2813
|
-
|
2814
|
-
def self.create_curve_quad_linear(model, coeff, name)
|
2815
|
-
curve = OpenStudio::Model::CurveQuadLinear.new(model)
|
2816
|
-
curve.setName(name)
|
2817
|
-
curve.setCoefficient1Constant(coeff[0])
|
2818
|
-
curve.setCoefficient2w(coeff[1])
|
2819
|
-
curve.setCoefficient3x(coeff[2])
|
2820
|
-
curve.setCoefficient4y(coeff[3])
|
2821
|
-
curve.setCoefficient5z(coeff[4])
|
2822
|
-
return curve
|
2823
|
-
end
|
2824
|
-
|
2825
|
-
def self.create_curve_quint_linear(model, coeff, name)
|
2826
|
-
curve = OpenStudio::Model::CurveQuintLinear.new(model)
|
2827
|
-
curve.setName(name)
|
2828
|
-
curve.setCoefficient1Constant(coeff[0])
|
2829
|
-
curve.setCoefficient2v(coeff[1])
|
2830
|
-
curve.setCoefficient3w(coeff[2])
|
2831
|
-
curve.setCoefficient4x(coeff[3])
|
2832
|
-
curve.setCoefficient5y(coeff[4])
|
2833
|
-
curve.setCoefficient6z(coeff[5])
|
2834
|
-
return curve
|
2835
|
-
end
|
2836
|
-
|
2837
|
-
def self.create_dx_cooling_coil(model, obj_name, cooling_system)
|
2500
|
+
def self.create_dx_cooling_coil(model, obj_name, cooling_system, max_rated_fan_cfm, weather_max_drybulb)
|
2838
2501
|
clg_ap = cooling_system.additional_properties
|
2839
2502
|
|
2840
2503
|
if cooling_system.is_a? HPXML::CoolingSystem
|
@@ -2843,23 +2506,51 @@ class HVAC
|
|
2843
2506
|
clg_type = cooling_system.heat_pump_type
|
2844
2507
|
end
|
2845
2508
|
|
2846
|
-
if
|
2847
|
-
|
2509
|
+
if cooling_system.cooling_detailed_performance_data.empty?
|
2510
|
+
max_clg_cfm = UnitConversions.convert(cooling_system.cooling_capacity * clg_ap.cool_capacity_ratios[-1], 'Btu/hr', 'ton') * clg_ap.cool_rated_cfm_per_ton[-1]
|
2511
|
+
clg_ap.cool_rated_capacities_gross = []
|
2512
|
+
clg_ap.cool_rated_capacities_net = []
|
2513
|
+
clg_ap.cool_capacity_ratios.each_with_index do |capacity_ratio, speed|
|
2514
|
+
fan_ratio = clg_ap.cool_fan_speed_ratios[speed] * max_clg_cfm / max_rated_fan_cfm
|
2515
|
+
fan_power = calculate_fan_power_from_curve(clg_ap.fan_power_rated * max_rated_fan_cfm, fan_ratio)
|
2516
|
+
net_capacity = capacity_ratio * cooling_system.cooling_capacity
|
2517
|
+
clg_ap.cool_rated_capacities_net << net_capacity
|
2518
|
+
gross_capacity = convert_net_to_gross_capacity_cop(net_capacity, fan_power, :clg)[0]
|
2519
|
+
clg_ap.cool_rated_capacities_gross << gross_capacity
|
2520
|
+
end
|
2521
|
+
else
|
2522
|
+
process_neep_detailed_performance(cooling_system.cooling_detailed_performance_data, clg_ap, :clg, max_rated_fan_cfm, weather_max_drybulb)
|
2848
2523
|
end
|
2849
2524
|
|
2850
2525
|
clg_coil = nil
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2526
|
+
num_speeds = clg_ap.cool_rated_cfm_per_ton.size
|
2527
|
+
for i in 0..(num_speeds - 1)
|
2528
|
+
if not cooling_system.cooling_detailed_performance_data.empty?
|
2529
|
+
speed_performance_data = clg_ap.cooling_performance_data_array[i].sort_by { |dp| [dp.indoor_wetbulb, dp.outdoor_temperature] }
|
2530
|
+
var_wb = { name: 'wet_bulb_temp_in', min: -100, max: 100, values: speed_performance_data.map { |dp| UnitConversions.convert(dp.indoor_wetbulb, 'F', 'C') }.uniq }
|
2531
|
+
var_db = { name: 'dry_bulb_temp_out', min: -100, max: 100, values: speed_performance_data.map { |dp| UnitConversions.convert(dp.outdoor_temperature, 'F', 'C') }.uniq }
|
2532
|
+
cap_ft_independent_vars = [var_wb, var_db]
|
2533
|
+
eir_ft_independent_vars = [var_wb, var_db]
|
2534
|
+
|
2535
|
+
rate_dp = speed_performance_data.find { |dp| (dp.indoor_wetbulb == HVAC::AirSourceCoolRatedIWB) && (dp.outdoor_temperature == HVAC::AirSourceCoolRatedODB) }
|
2536
|
+
clg_ap.cool_rated_cops << rate_dp.gross_efficiency_cop
|
2537
|
+
clg_ap.cool_rated_capacities_gross << rate_dp.gross_capacity
|
2538
|
+
clg_ap.cool_rated_capacities_net << rate_dp.capacity
|
2539
|
+
cap_ft_output_values = speed_performance_data.map { |dp| dp.gross_capacity / rate_dp.gross_capacity }
|
2540
|
+
eir_ft_output_values = speed_performance_data.map { |dp| (1.0 / dp.gross_efficiency_cop) / (1.0 / rate_dp.gross_efficiency_cop) }
|
2541
|
+
cap_ft_curve = create_table_lookup(model, "Cool-CAP-fT#{i + 1}", cap_ft_independent_vars, cap_ft_output_values, 0.0)
|
2542
|
+
eir_ft_curve = create_table_lookup(model, "Cool-EIR-fT#{i + 1}", eir_ft_independent_vars, eir_ft_output_values, 0.0)
|
2543
|
+
else
|
2544
|
+
cap_ft_spec_si = convert_curve_biquadratic(clg_ap.cool_cap_ft_spec[i])
|
2545
|
+
eir_ft_spec_si = convert_curve_biquadratic(clg_ap.cool_eir_ft_spec[i])
|
2546
|
+
cap_ft_curve = create_curve_biquadratic(model, cap_ft_spec_si, "Cool-CAP-fT#{i + 1}", -100, 100, -100, 100)
|
2547
|
+
eir_ft_curve = create_curve_biquadratic(model, eir_ft_spec_si, "Cool-EIR-fT#{i + 1}", -100, 100, -100, 100)
|
2548
|
+
end
|
2859
2549
|
cap_fff_curve = create_curve_quadratic(model, clg_ap.cool_cap_fflow_spec[i], "Cool-CAP-fFF#{i + 1}", 0, 2, 0, 2)
|
2860
2550
|
eir_fff_curve = create_curve_quadratic(model, clg_ap.cool_eir_fflow_spec[i], "Cool-EIR-fFF#{i + 1}", 0, 2, 0, 2)
|
2551
|
+
plf_fplr_curve = create_curve_quadratic(model, clg_ap.cool_plf_fplr_spec[i], "Cool-PLF-fPLR#{i + 1}", 0, 1, 0.7, 1)
|
2861
2552
|
|
2862
|
-
if
|
2553
|
+
if num_speeds == 1
|
2863
2554
|
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model, model.alwaysOnDiscreteSchedule, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve)
|
2864
2555
|
# Coil COP calculation based on system type
|
2865
2556
|
if [HPXML::HVACTypeRoomAirConditioner, HPXML::HVACTypePTAC, HPXML::HVACTypeHeatPumpPTHP, HPXML::HVACTypeHeatPumpRoom].include? clg_type
|
@@ -2870,16 +2561,16 @@ class HVAC
|
|
2870
2561
|
end
|
2871
2562
|
clg_coil.setRatedCOP(UnitConversions.convert(ceer, 'Btu/hr', 'W'))
|
2872
2563
|
else
|
2873
|
-
clg_coil.setRatedCOP(
|
2564
|
+
clg_coil.setRatedCOP(clg_ap.cool_rated_cops[i])
|
2874
2565
|
end
|
2875
|
-
clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(UnitConversions.convert(
|
2566
|
+
clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(UnitConversions.convert(CrankcaseHeaterTemp, 'F', 'C')) if cooling_system.crankcase_heater_watts.to_f > 0.0 # From RESNET Publication No. 002-2017
|
2876
2567
|
clg_coil.setRatedSensibleHeatRatio(clg_ap.cool_rated_shrs_gross[i])
|
2877
2568
|
clg_coil.setNominalTimeForCondensateRemovalToBegin(1000.0)
|
2878
2569
|
clg_coil.setRatioOfInitialMoistureEvaporationRateAndSteadyStateLatentCapacity(1.5)
|
2879
2570
|
clg_coil.setMaximumCyclingRate(3.0)
|
2880
2571
|
clg_coil.setLatentCapacityTimeConstant(45.0)
|
2881
|
-
clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(
|
2882
|
-
clg_coil.setRatedAirFlowRate(calc_rated_airflow(
|
2572
|
+
clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(clg_ap.cool_rated_capacities_gross[i], 'Btu/hr', 'W'))
|
2573
|
+
clg_coil.setRatedAirFlowRate(calc_rated_airflow(clg_ap.cool_rated_capacities_net[i], clg_ap.cool_rated_cfm_per_ton[0]))
|
2883
2574
|
else
|
2884
2575
|
if clg_coil.nil?
|
2885
2576
|
clg_coil = OpenStudio::Model::CoilCoolingDXMultiSpeed.new(model)
|
@@ -2887,18 +2578,19 @@ class HVAC
|
|
2887
2578
|
clg_coil.setApplyLatentDegradationtoSpeedsGreaterthan1(false)
|
2888
2579
|
clg_coil.setFuelType(EPlus::FuelTypeElectricity)
|
2889
2580
|
clg_coil.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
2890
|
-
clg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(
|
2581
|
+
clg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(CrankcaseHeaterTemp, 'F', 'C')) if cooling_system.crankcase_heater_watts.to_f > 0.0 # From RESNET Publication No. 002-2017
|
2582
|
+
constant_biquadratic = create_curve_biquadratic_constant(model)
|
2891
2583
|
end
|
2892
2584
|
stage = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve, constant_biquadratic)
|
2893
|
-
stage.setGrossRatedCoolingCOP(
|
2585
|
+
stage.setGrossRatedCoolingCOP(clg_ap.cool_rated_cops[i])
|
2894
2586
|
stage.setGrossRatedSensibleHeatRatio(clg_ap.cool_rated_shrs_gross[i])
|
2895
2587
|
stage.setNominalTimeforCondensateRemovaltoBegin(1000)
|
2896
2588
|
stage.setRatioofInitialMoistureEvaporationRateandSteadyStateLatentCapacity(1.5)
|
2897
2589
|
stage.setRatedWasteHeatFractionofPowerInput(0.2)
|
2898
2590
|
stage.setMaximumCyclingRate(3.0)
|
2899
2591
|
stage.setLatentCapacityTimeConstant(45.0)
|
2900
|
-
stage.setGrossRatedTotalCoolingCapacity(UnitConversions.convert(
|
2901
|
-
stage.setRatedAirFlowRate(calc_rated_airflow(
|
2592
|
+
stage.setGrossRatedTotalCoolingCapacity(UnitConversions.convert(clg_ap.cool_rated_capacities_gross[i], 'Btu/hr', 'W'))
|
2593
|
+
stage.setRatedAirFlowRate(calc_rated_airflow(clg_ap.cool_rated_capacities_net[i], clg_ap.cool_rated_cfm_per_ton[i]))
|
2902
2594
|
clg_coil.addStage(stage)
|
2903
2595
|
end
|
2904
2596
|
end
|
@@ -2911,46 +2603,75 @@ class HVAC
|
|
2911
2603
|
return clg_coil
|
2912
2604
|
end
|
2913
2605
|
|
2914
|
-
def self.create_dx_heating_coil(model, obj_name, heating_system)
|
2606
|
+
def self.create_dx_heating_coil(model, obj_name, heating_system, max_rated_fan_cfm, weather_min_drybulb)
|
2915
2607
|
htg_ap = heating_system.additional_properties
|
2916
2608
|
|
2917
|
-
if
|
2918
|
-
|
2609
|
+
if heating_system.heating_detailed_performance_data.empty?
|
2610
|
+
max_htg_cfm = UnitConversions.convert(heating_system.heating_capacity * htg_ap.heat_capacity_ratios[-1], 'Btu/hr', 'ton') * htg_ap.heat_rated_cfm_per_ton[-1]
|
2611
|
+
htg_ap.heat_rated_capacities_gross = []
|
2612
|
+
htg_ap.heat_rated_capacities_net = []
|
2613
|
+
htg_ap.heat_capacity_ratios.each_with_index do |capacity_ratio, speed|
|
2614
|
+
fan_ratio = htg_ap.heat_fan_speed_ratios[speed] * max_htg_cfm / max_rated_fan_cfm
|
2615
|
+
fan_power = calculate_fan_power_from_curve(htg_ap.fan_power_rated * max_rated_fan_cfm, fan_ratio)
|
2616
|
+
net_capacity = capacity_ratio * heating_system.heating_capacity
|
2617
|
+
htg_ap.heat_rated_capacities_net << net_capacity
|
2618
|
+
gross_capacity = convert_net_to_gross_capacity_cop(net_capacity, fan_power, :htg)[0]
|
2619
|
+
htg_ap.heat_rated_capacities_gross << gross_capacity
|
2620
|
+
end
|
2621
|
+
else
|
2622
|
+
process_neep_detailed_performance(heating_system.heating_detailed_performance_data, htg_ap, :htg, max_rated_fan_cfm, weather_min_drybulb, htg_ap.hp_min_temp)
|
2919
2623
|
end
|
2920
2624
|
|
2921
2625
|
htg_coil = nil
|
2922
|
-
|
2923
|
-
|
2924
|
-
|
2925
|
-
|
2926
|
-
|
2927
|
-
|
2928
|
-
|
2929
|
-
|
2626
|
+
num_speeds = htg_ap.heat_rated_cfm_per_ton.size
|
2627
|
+
for i in 0..(num_speeds - 1)
|
2628
|
+
if not heating_system.heating_detailed_performance_data.empty?
|
2629
|
+
speed_performance_data = htg_ap.heating_performance_data_array[i].sort_by { |dp| [dp.indoor_temperature, dp.outdoor_temperature] }
|
2630
|
+
var_idb = { name: 'dry_bulb_temp_in', min: -100, max: 100, values: speed_performance_data.map { |dp| UnitConversions.convert(dp.indoor_temperature, 'F', 'C') }.uniq }
|
2631
|
+
var_odb = { name: 'dry_bulb_temp_out', min: -100, max: 100, values: speed_performance_data.map { |dp| UnitConversions.convert(dp.outdoor_temperature, 'F', 'C') }.uniq }
|
2632
|
+
cap_ft_independent_vars = [var_idb, var_odb]
|
2633
|
+
eir_ft_independent_vars = [var_idb, var_odb]
|
2634
|
+
|
2635
|
+
rate_dp = speed_performance_data.find { |dp| (dp.indoor_temperature == HVAC::AirSourceHeatRatedIDB) && (dp.outdoor_temperature == HVAC::AirSourceHeatRatedODB) }
|
2636
|
+
htg_ap.heat_rated_cops << rate_dp.gross_efficiency_cop
|
2637
|
+
htg_ap.heat_rated_capacities_net << rate_dp.capacity
|
2638
|
+
htg_ap.heat_rated_capacities_gross << rate_dp.gross_capacity
|
2639
|
+
cap_ft_output_values = speed_performance_data.map { |dp| dp.gross_capacity / rate_dp.gross_capacity }
|
2640
|
+
eir_ft_output_values = speed_performance_data.map { |dp| (1.0 / dp.gross_efficiency_cop) / (1.0 / rate_dp.gross_efficiency_cop) }
|
2641
|
+
cap_ft_curve = create_table_lookup(model, "Heat-CAP-fT#{i + 1}", cap_ft_independent_vars, cap_ft_output_values, 0)
|
2642
|
+
eir_ft_curve = create_table_lookup(model, "Heat-EIR-fT#{i + 1}", eir_ft_independent_vars, eir_ft_output_values, 0)
|
2643
|
+
else
|
2644
|
+
cap_ft_spec_si = convert_curve_biquadratic(htg_ap.heat_cap_ft_spec[i])
|
2645
|
+
eir_ft_spec_si = convert_curve_biquadratic(htg_ap.heat_eir_ft_spec[i])
|
2646
|
+
cap_ft_curve = create_curve_biquadratic(model, cap_ft_spec_si, "Heat-CAP-fT#{i + 1}", -100, 100, -100, 100)
|
2647
|
+
eir_ft_curve = create_curve_biquadratic(model, eir_ft_spec_si, "Heat-EIR-fT#{i + 1}", -100, 100, -100, 100)
|
2648
|
+
end
|
2930
2649
|
cap_fff_curve = create_curve_quadratic(model, htg_ap.heat_cap_fflow_spec[i], "Heat-CAP-fFF#{i + 1}", 0, 2, 0, 2)
|
2931
2650
|
eir_fff_curve = create_curve_quadratic(model, htg_ap.heat_eir_fflow_spec[i], "Heat-EIR-fFF#{i + 1}", 0, 2, 0, 2)
|
2651
|
+
plf_fplr_curve = create_curve_quadratic(model, htg_ap.heat_plf_fplr_spec[i], "Heat-PLF-fPLR#{i + 1}", 0, 1, 0.7, 1)
|
2932
2652
|
|
2933
|
-
if
|
2653
|
+
if num_speeds == 1
|
2934
2654
|
htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model, model.alwaysOnDiscreteSchedule, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve)
|
2935
2655
|
if heating_system.heating_efficiency_cop.nil?
|
2936
|
-
htg_coil.setRatedCOP(
|
2656
|
+
htg_coil.setRatedCOP(htg_ap.heat_rated_cops[i])
|
2937
2657
|
else # PTHP or room heat pump
|
2938
2658
|
htg_coil.setRatedCOP(heating_system.heating_efficiency_cop)
|
2939
2659
|
end
|
2940
|
-
htg_coil.setRatedTotalHeatingCapacity(UnitConversions.convert(
|
2941
|
-
htg_coil.setRatedAirFlowRate(calc_rated_airflow(
|
2660
|
+
htg_coil.setRatedTotalHeatingCapacity(UnitConversions.convert(htg_ap.heat_rated_capacities_gross[i], 'Btu/hr', 'W'))
|
2661
|
+
htg_coil.setRatedAirFlowRate(calc_rated_airflow(htg_ap.heat_rated_capacities_net[i], htg_ap.heat_rated_cfm_per_ton[0]))
|
2942
2662
|
else
|
2943
2663
|
if htg_coil.nil?
|
2944
2664
|
htg_coil = OpenStudio::Model::CoilHeatingDXMultiSpeed.new(model)
|
2945
2665
|
htg_coil.setFuelType(EPlus::FuelTypeElectricity)
|
2946
2666
|
htg_coil.setApplyPartLoadFractiontoSpeedsGreaterthan1(false)
|
2947
2667
|
htg_coil.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
|
2668
|
+
constant_biquadratic = create_curve_biquadratic_constant(model)
|
2948
2669
|
end
|
2949
2670
|
stage = OpenStudio::Model::CoilHeatingDXMultiSpeedStageData.new(model, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve, constant_biquadratic)
|
2950
|
-
stage.setGrossRatedHeatingCOP(
|
2671
|
+
stage.setGrossRatedHeatingCOP(htg_ap.heat_rated_cops[i])
|
2951
2672
|
stage.setRatedWasteHeatFractionofPowerInput(0.2)
|
2952
|
-
stage.setGrossRatedHeatingCapacity(UnitConversions.convert(
|
2953
|
-
stage.setRatedAirFlowRate(calc_rated_airflow(
|
2673
|
+
stage.setGrossRatedHeatingCapacity(UnitConversions.convert(htg_ap.heat_rated_capacities_gross[i], 'Btu/hr', 'W'))
|
2674
|
+
stage.setRatedAirFlowRate(calc_rated_airflow(htg_ap.heat_rated_capacities_net[i], htg_ap.heat_rated_cfm_per_ton[i]))
|
2954
2675
|
htg_coil.addStage(stage)
|
2955
2676
|
end
|
2956
2677
|
end
|
@@ -2965,31 +2686,13 @@ class HVAC
|
|
2965
2686
|
if heating_system.fraction_heat_load_served == 0
|
2966
2687
|
htg_coil.setResistiveDefrostHeaterCapacity(0)
|
2967
2688
|
end
|
2968
|
-
htg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(
|
2689
|
+
htg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(CrankcaseHeaterTemp, 'F', 'C')) if heating_system.crankcase_heater_watts.to_f > 0.0 # From RESNET Publication No. 002-2017
|
2969
2690
|
htg_coil.setCrankcaseHeaterCapacity(heating_system.crankcase_heater_watts)
|
2970
2691
|
htg_coil.additionalProperties.setFeature('HPXML_ID', heating_system.id) # Used by reporting measure
|
2971
2692
|
|
2972
2693
|
return htg_coil
|
2973
2694
|
end
|
2974
2695
|
|
2975
|
-
def self.set_cool_rated_eirs(cooling_system)
|
2976
|
-
clg_ap = cooling_system.additional_properties
|
2977
|
-
|
2978
|
-
clg_ap.cool_rated_eirs = []
|
2979
|
-
for speed in 0..clg_ap.num_speeds - 1
|
2980
|
-
clg_ap.cool_rated_eirs << calc_eir_from_eer(clg_ap.cool_eers[speed], clg_ap.fan_power_rated)
|
2981
|
-
end
|
2982
|
-
end
|
2983
|
-
|
2984
|
-
def self.set_heat_rated_eirs(heating_system)
|
2985
|
-
htg_ap = heating_system.additional_properties
|
2986
|
-
|
2987
|
-
htg_ap.heat_rated_eirs = []
|
2988
|
-
for speed in 0..htg_ap.num_speeds - 1
|
2989
|
-
htg_ap.heat_rated_eirs << calc_eir_from_cop(htg_ap.heat_cops[speed], htg_ap.fan_power_rated)
|
2990
|
-
end
|
2991
|
-
end
|
2992
|
-
|
2993
2696
|
def self.set_cool_rated_shrs_gross(runner, cooling_system)
|
2994
2697
|
clg_ap = cooling_system.additional_properties
|
2995
2698
|
|
@@ -3001,13 +2704,13 @@ class HVAC
|
|
3001
2704
|
dB_rated = 80.0 # deg-F
|
3002
2705
|
win = 0.01118470 # Humidity ratio corresponding to 80F dry bulb/67F wet bulb (from EnergyPlus)
|
3003
2706
|
|
3004
|
-
if
|
3005
|
-
cool_nominal_cfm_per_ton = (clg_ap.cool_rated_airflow_rate - clg_ap.cool_rated_cfm_per_ton[0] * clg_ap.cool_capacity_ratios[0]) / (clg_ap.cool_capacity_ratios[-1] - clg_ap.cool_capacity_ratios[0]) * (1.0 - clg_ap.cool_capacity_ratios[0]) + clg_ap.cool_rated_cfm_per_ton[0] * clg_ap.cool_capacity_ratios[0]
|
3006
|
-
else
|
2707
|
+
if cooling_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
3007
2708
|
cool_nominal_cfm_per_ton = clg_ap.cool_rated_cfm_per_ton[0]
|
2709
|
+
else
|
2710
|
+
cool_nominal_cfm_per_ton = (clg_ap.cool_rated_airflow_rate - clg_ap.cool_rated_cfm_per_ton[0] * clg_ap.cool_capacity_ratios[0]) / (clg_ap.cool_capacity_ratios[-1] - clg_ap.cool_capacity_ratios[0]) * (1.0 - clg_ap.cool_capacity_ratios[0]) + clg_ap.cool_rated_cfm_per_ton[0] * clg_ap.cool_capacity_ratios[0]
|
3008
2711
|
end
|
3009
2712
|
|
3010
|
-
p_atm =
|
2713
|
+
p_atm = UnitConversions.convert(1, 'atm', 'psi')
|
3011
2714
|
|
3012
2715
|
ao = Psychrometrics.CoilAoFactor(runner, dB_rated, p_atm, UnitConversions.convert(1, 'ton', 'kBtu/hr'), cool_nominal_cfm_per_ton, cooling_system.cooling_shr, win)
|
3013
2716
|
|
@@ -3023,47 +2726,50 @@ class HVAC
|
|
3023
2726
|
return [(1.0 - c_d), c_d, 0.0] # Linear part load model
|
3024
2727
|
end
|
3025
2728
|
|
3026
|
-
def self.set_cool_c_d(cooling_system
|
2729
|
+
def self.set_cool_c_d(cooling_system)
|
3027
2730
|
clg_ap = cooling_system.additional_properties
|
3028
2731
|
|
3029
2732
|
# Degradation coefficient for cooling
|
3030
2733
|
if ((cooling_system.is_a? HPXML::CoolingSystem) && ([HPXML::HVACTypeRoomAirConditioner, HPXML::HVACTypePTAC].include? cooling_system.cooling_system_type)) ||
|
3031
2734
|
((cooling_system.is_a? HPXML::HeatPump) && ([HPXML::HVACTypeHeatPumpPTHP, HPXML::HVACTypeHeatPumpRoom].include? cooling_system.heat_pump_type))
|
3032
2735
|
clg_ap.cool_c_d = 0.22
|
3033
|
-
elsif
|
2736
|
+
elsif cooling_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
3034
2737
|
if cooling_system.cooling_efficiency_seer < 13.0
|
3035
2738
|
clg_ap.cool_c_d = 0.20
|
3036
2739
|
else
|
3037
2740
|
clg_ap.cool_c_d = 0.07
|
3038
2741
|
end
|
3039
|
-
elsif
|
2742
|
+
elsif cooling_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
|
3040
2743
|
clg_ap.cool_c_d = 0.11
|
3041
|
-
elsif
|
2744
|
+
elsif cooling_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
3042
2745
|
clg_ap.cool_c_d = 0.25
|
3043
2746
|
end
|
3044
2747
|
|
3045
2748
|
# PLF curve
|
2749
|
+
num_speeds = clg_ap.cool_capacity_ratios.size
|
3046
2750
|
clg_ap.cool_plf_fplr_spec = [calc_plr_coefficients(clg_ap.cool_c_d)] * num_speeds
|
3047
2751
|
end
|
3048
2752
|
|
3049
|
-
def self.set_heat_c_d(heating_system
|
2753
|
+
def self.set_heat_c_d(heating_system)
|
3050
2754
|
htg_ap = heating_system.additional_properties
|
3051
2755
|
|
3052
2756
|
# Degradation coefficient for heating
|
3053
2757
|
if (heating_system.is_a? HPXML::HeatPump) && ([HPXML::HVACTypeHeatPumpPTHP, HPXML::HVACTypeHeatPumpRoom].include? heating_system.heat_pump_type)
|
3054
2758
|
htg_ap.heat_c_d = 0.22
|
3055
|
-
elsif
|
2759
|
+
elsif heating_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
3056
2760
|
if heating_system.heating_efficiency_hspf < 7.0
|
3057
2761
|
htg_ap.heat_c_d = 0.20
|
3058
2762
|
else
|
3059
2763
|
htg_ap.heat_c_d = 0.11
|
3060
2764
|
end
|
3061
|
-
elsif
|
2765
|
+
elsif heating_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
|
3062
2766
|
htg_ap.heat_c_d = 0.11
|
3063
|
-
elsif
|
2767
|
+
elsif heating_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
3064
2768
|
htg_ap.heat_c_d = 0.25
|
3065
2769
|
end
|
3066
2770
|
|
2771
|
+
# PLF curve
|
2772
|
+
num_speeds = htg_ap.heat_capacity_ratios.size
|
3067
2773
|
htg_ap.heat_plf_fplr_spec = [calc_plr_coefficients(htg_ap.heat_c_d)] * num_speeds
|
3068
2774
|
end
|
3069
2775
|
|
@@ -3072,10 +2778,13 @@ class HVAC
|
|
3072
2778
|
return cooling_system.cooling_efficiency_eer / 1.01
|
3073
2779
|
end
|
3074
2780
|
|
3075
|
-
def self.set_fan_power_rated(hvac_system)
|
2781
|
+
def self.set_fan_power_rated(hvac_system, use_eer_cop)
|
3076
2782
|
hvac_ap = hvac_system.additional_properties
|
3077
2783
|
|
3078
|
-
if
|
2784
|
+
if use_eer_cop
|
2785
|
+
# Fan not separately modeled
|
2786
|
+
hvac_ap.fan_power_rated = 0.0
|
2787
|
+
elsif hvac_system.distribution_system.nil?
|
3079
2788
|
# Ductless, installed and rated value should be equal
|
3080
2789
|
hvac_ap.fan_power_rated = hvac_system.fan_watts_per_cfm # W/cfm
|
3081
2790
|
else
|
@@ -3106,258 +2815,17 @@ class HVAC
|
|
3106
2815
|
return
|
3107
2816
|
end
|
3108
2817
|
|
3109
|
-
def self.set_cool_rated_eirs_mshp(cooling_system, num_speeds)
|
3110
|
-
clg_ap = cooling_system.additional_properties
|
3111
|
-
|
3112
|
-
cops_norm = [1.901, 1.859, 1.746, 1.609, 1.474, 1.353, 1.247, 1.156, 1.079, 1.0]
|
3113
|
-
fan_powers_norm = [0.604, 0.634, 0.670, 0.711, 0.754, 0.800, 0.848, 0.898, 0.948, 1.0]
|
3114
|
-
|
3115
|
-
cop_max_speed = 3.5 # 3.5 is an initial guess, final value solved for below
|
3116
|
-
|
3117
|
-
fan_powers_rated = []
|
3118
|
-
eers_rated = []
|
3119
|
-
|
3120
|
-
for i in 0..num_speeds - 1
|
3121
|
-
fan_powers_rated << clg_ap.fan_power_rated * fan_powers_norm[i]
|
3122
|
-
eers_rated << UnitConversions.convert(cop_max_speed, 'W', 'Btu/hr') * cops_norm[i]
|
3123
|
-
end
|
3124
|
-
|
3125
|
-
cop_max_speed_1 = cop_max_speed
|
3126
|
-
cop_max_speed_2 = cop_max_speed
|
3127
|
-
error = cooling_system.cooling_efficiency_seer - calc_mshp_seer(eers_rated, clg_ap.cool_c_d, clg_ap.cool_capacity_ratios, clg_ap.cool_rated_cfm_per_ton, fan_powers_rated, clg_ap.cool_eir_ft_spec, clg_ap.cool_cap_ft_spec)
|
3128
|
-
error1 = error
|
3129
|
-
error2 = error
|
3130
|
-
|
3131
|
-
itmax = 50 # maximum iterations
|
3132
|
-
cvg = false
|
3133
|
-
final_n = nil
|
3134
|
-
|
3135
|
-
for n in 1..itmax + 1
|
3136
|
-
final_n = n
|
3137
|
-
for i in 0..num_speeds - 1
|
3138
|
-
eers_rated[i] = UnitConversions.convert(cop_max_speed, 'W', 'Btu/hr') * cops_norm[i]
|
3139
|
-
end
|
3140
|
-
|
3141
|
-
error = cooling_system.cooling_efficiency_seer - calc_mshp_seer(eers_rated, clg_ap.cool_c_d, clg_ap.cool_capacity_ratios, clg_ap.cool_rated_cfm_per_ton, fan_powers_rated, clg_ap.cool_eir_ft_spec, clg_ap.cool_cap_ft_spec)
|
3142
|
-
|
3143
|
-
cop_max_speed, cvg, cop_max_speed_1, error1, cop_max_speed_2, error2 = MathTools.Iterate(cop_max_speed, error, cop_max_speed_1, error1, cop_max_speed_2, error2, n, cvg)
|
3144
|
-
|
3145
|
-
if cvg
|
3146
|
-
break
|
3147
|
-
end
|
3148
|
-
end
|
3149
|
-
|
3150
|
-
if (not cvg) || (final_n > itmax)
|
3151
|
-
cop_max_speed = UnitConversions.convert(0.547 * cooling_system.cooling_efficiency_seer - 0.104, 'Btu/hr', 'W') # Correlation developed from JonW's MatLab scripts. Only used if an eer cannot be found.
|
3152
|
-
end
|
3153
|
-
|
3154
|
-
clg_ap.cool_rated_eirs = []
|
3155
|
-
|
3156
|
-
for i in 0..num_speeds - 1
|
3157
|
-
clg_ap.cool_rated_eirs << calc_eir_from_eer(UnitConversions.convert(cop_max_speed, 'W', 'Btu/hr') * cops_norm[i], fan_powers_rated[i])
|
3158
|
-
end
|
3159
|
-
end
|
3160
|
-
|
3161
|
-
def self.set_mshp_downselected_speed_indices(heat_pump)
|
3162
|
-
hp_ap = heat_pump.additional_properties
|
3163
|
-
|
3164
|
-
# Down-select to speed indices
|
3165
|
-
|
3166
|
-
# Cooling
|
3167
|
-
hp_ap.cool_cap_ft_spec = hp_ap.cool_cap_ft_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3168
|
-
hp_ap.cool_eir_ft_spec = hp_ap.cool_eir_ft_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3169
|
-
hp_ap.cool_cap_fflow_spec = hp_ap.cool_cap_fflow_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3170
|
-
hp_ap.cool_eir_fflow_spec = hp_ap.cool_eir_fflow_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3171
|
-
hp_ap.cool_plf_fplr_spec = hp_ap.cool_plf_fplr_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3172
|
-
hp_ap.cool_rated_cfm_per_ton = hp_ap.cool_rated_cfm_per_ton.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3173
|
-
hp_ap.cool_capacity_ratios = hp_ap.cool_capacity_ratios.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3174
|
-
hp_ap.cool_rated_shrs_gross = hp_ap.cool_rated_shrs_gross.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3175
|
-
hp_ap.cool_rated_eirs = hp_ap.cool_rated_eirs.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3176
|
-
hp_ap.cool_fan_speed_ratios = hp_ap.cool_fan_speed_ratios.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3177
|
-
|
3178
|
-
if heat_pump.is_a? HPXML::HeatPump # Skip for mini-split air conditioner
|
3179
|
-
# Heating
|
3180
|
-
hp_ap.heat_eir_ft_spec = hp_ap.heat_eir_ft_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3181
|
-
hp_ap.heat_cap_fflow_spec = hp_ap.heat_cap_fflow_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3182
|
-
hp_ap.heat_eir_fflow_spec = hp_ap.heat_eir_fflow_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3183
|
-
hp_ap.heat_cap_ft_spec = hp_ap.heat_cap_ft_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3184
|
-
hp_ap.heat_plf_fplr_spec = hp_ap.heat_plf_fplr_spec.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3185
|
-
hp_ap.heat_rated_cfm_per_ton = hp_ap.heat_rated_cfm_per_ton.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3186
|
-
hp_ap.heat_capacity_ratios = hp_ap.heat_capacity_ratios.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3187
|
-
hp_ap.heat_rated_eirs = hp_ap.heat_rated_eirs.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3188
|
-
hp_ap.heat_fan_speed_ratios = hp_ap.heat_fan_speed_ratios.select.with_index { |_x, i| hp_ap.speed_indices.include? i }
|
3189
|
-
end
|
3190
|
-
end
|
3191
|
-
|
3192
|
-
def self.calc_mshp_seer(eer_a, c_d, capacity_ratio, cfm_tons, fan_power_rated, cool_eir_ft_spec, cool_cap_ft_spec)
|
3193
|
-
n_max = (eer_a.length - 1.0) - 3.0 # Don't use max speed; FIXME: this is different than calc_mshp_hspf?
|
3194
|
-
n_min = 0
|
3195
|
-
n_int = (n_min + (n_max - n_min) / 3.0).ceil.to_i
|
3196
|
-
|
3197
|
-
wBin = 67.0
|
3198
|
-
tout_B = 82.0
|
3199
|
-
tout_E = 87.0
|
3200
|
-
tout_F = 67.0
|
3201
|
-
|
3202
|
-
eir_A2 = calc_eir_from_eer(eer_a[n_max], fan_power_rated[n_max])
|
3203
|
-
eir_B2 = eir_A2 * MathTools.biquadratic(wBin, tout_B, cool_eir_ft_spec[n_max])
|
3204
|
-
|
3205
|
-
eir_Av = calc_eir_from_eer(eer_a[n_int], fan_power_rated[n_int])
|
3206
|
-
eir_Ev = eir_Av * MathTools.biquadratic(wBin, tout_E, cool_eir_ft_spec[n_int])
|
3207
|
-
|
3208
|
-
eir_A1 = calc_eir_from_eer(eer_a[n_min], fan_power_rated[n_min])
|
3209
|
-
eir_B1 = eir_A1 * MathTools.biquadratic(wBin, tout_B, cool_eir_ft_spec[n_min])
|
3210
|
-
eir_F1 = eir_A1 * MathTools.biquadratic(wBin, tout_F, cool_eir_ft_spec[n_min])
|
3211
|
-
|
3212
|
-
q_A2 = capacity_ratio[n_max]
|
3213
|
-
q_B2 = q_A2 * MathTools.biquadratic(wBin, tout_B, cool_cap_ft_spec[n_max])
|
3214
|
-
q_Ev = capacity_ratio[n_int] * MathTools.biquadratic(wBin, tout_E, cool_cap_ft_spec[n_int])
|
3215
|
-
q_B1 = capacity_ratio[n_min] * MathTools.biquadratic(wBin, tout_B, cool_cap_ft_spec[n_min])
|
3216
|
-
q_F1 = capacity_ratio[n_min] * MathTools.biquadratic(wBin, tout_F, cool_cap_ft_spec[n_min])
|
3217
|
-
|
3218
|
-
q_A2_net = q_A2 - fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3219
|
-
q_B2_net = q_B2 - fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3220
|
-
q_Ev_net = q_Ev - fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_int] * capacity_ratio[n_int]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3221
|
-
q_B1_net = q_B1 - fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3222
|
-
q_F1_net = q_F1 - fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3223
|
-
|
3224
|
-
p_A2 = UnitConversions.convert(q_A2 * eir_A2, 'Btu', 'Wh') + fan_power_rated[n_max] * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3225
|
-
p_B2 = UnitConversions.convert(q_B2 * eir_B2, 'Btu', 'Wh') + fan_power_rated[n_max] * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3226
|
-
p_Ev = UnitConversions.convert(q_Ev * eir_Ev, 'Btu', 'Wh') + fan_power_rated[n_int] * (cfm_tons[n_int] * capacity_ratio[n_int]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3227
|
-
p_B1 = UnitConversions.convert(q_B1 * eir_B1, 'Btu', 'Wh') + fan_power_rated[n_min] * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3228
|
-
p_F1 = UnitConversions.convert(q_F1 * eir_F1, 'Btu', 'Wh') + fan_power_rated[n_min] * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3229
|
-
|
3230
|
-
q_k1_87 = q_F1_net + (q_B1_net - q_F1_net) / (82.0 - 67.0) * (87 - 67.0)
|
3231
|
-
q_k2_87 = q_B2_net + (q_A2_net - q_B2_net) / (95.0 - 82.0) * (87.0 - 82.0)
|
3232
|
-
n_Q = (q_Ev_net - q_k1_87) / (q_k2_87 - q_k1_87)
|
3233
|
-
m_Q = (q_B1_net - q_F1_net) / (82.0 - 67.0) * (1.0 - n_Q) + (q_A2_net - q_B2_net) / (95.0 - 82.0) * n_Q
|
3234
|
-
p_k1_87 = p_F1 + (p_B1 - p_F1) / (82.0 - 67.0) * (87.0 - 67.0)
|
3235
|
-
p_k2_87 = p_B2 + (p_A2 - p_B2) / (95.0 - 82.0) * (87.0 - 82.0)
|
3236
|
-
n_E = (p_Ev - p_k1_87) / (p_k2_87 - p_k1_87)
|
3237
|
-
m_E = (p_B1 - p_F1) / (82.0 - 67.0) * (1.0 - n_E) + (p_A2 - p_B2) / (95.0 - 82.0) * n_E
|
3238
|
-
|
3239
|
-
c_T_1_1 = q_A2_net / (1.1 * (95.0 - 65.0))
|
3240
|
-
c_T_1_2 = q_F1_net
|
3241
|
-
c_T_1_3 = (q_B1_net - q_F1_net) / (82.0 - 67.0)
|
3242
|
-
t_1 = (c_T_1_2 - 67.0 * c_T_1_3 + 65.0 * c_T_1_1) / (c_T_1_1 - c_T_1_3)
|
3243
|
-
q_T_1 = q_F1_net + (q_B1_net - q_F1_net) / (82.0 - 67.0) * (t_1 - 67.0)
|
3244
|
-
p_T_1 = p_F1 + (p_B1 - p_F1) / (82.0 - 67.0) * (t_1 - 67.0)
|
3245
|
-
eer_T_1 = q_T_1 / p_T_1
|
3246
|
-
|
3247
|
-
t_v = (q_Ev_net - 87.0 * m_Q + 65.0 * c_T_1_1) / (c_T_1_1 - m_Q)
|
3248
|
-
q_T_v = q_Ev_net + m_Q * (t_v - 87.0)
|
3249
|
-
p_T_v = p_Ev + m_E * (t_v - 87.0)
|
3250
|
-
eer_T_v = q_T_v / p_T_v
|
3251
|
-
|
3252
|
-
c_T_2_1 = c_T_1_1
|
3253
|
-
c_T_2_2 = q_B2_net
|
3254
|
-
c_T_2_3 = (q_A2_net - q_B2_net) / (95.0 - 82.0)
|
3255
|
-
t_2 = (c_T_2_2 - 82.0 * c_T_2_3 + 65.0 * c_T_2_1) / (c_T_2_1 - c_T_2_3)
|
3256
|
-
q_T_2 = q_B2_net + (q_A2_net - q_B2_net) / (95.0 - 82.0) * (t_2 - 82.0)
|
3257
|
-
p_T_2 = p_B2 + (p_A2 - p_B2) / (95.0 - 82.0) * (t_2 - 82.0)
|
3258
|
-
eer_T_2 = q_T_2 / p_T_2
|
3259
|
-
|
3260
|
-
d = (t_2**2 - t_1**2) / (t_v**2 - t_1**2)
|
3261
|
-
b = (eer_T_1 - eer_T_2 - d * (eer_T_1 - eer_T_v)) / (t_1 - t_2 - d * (t_1 - t_v))
|
3262
|
-
c = (eer_T_1 - eer_T_2 - b * (t_1 - t_2)) / (t_1**2 - t_2**2)
|
3263
|
-
a = eer_T_2 - b * t_2 - c * t_2**2
|
3264
|
-
|
3265
|
-
e_tot = 0
|
3266
|
-
q_tot = 0
|
3267
|
-
t_bins = [67.0, 72.0, 77.0, 82.0, 87.0, 92.0, 97.0, 102.0]
|
3268
|
-
frac_hours = [0.214, 0.231, 0.216, 0.161, 0.104, 0.052, 0.018, 0.004]
|
3269
|
-
|
3270
|
-
for i in 0..7
|
3271
|
-
bL = ((t_bins[i] - 65.0) / (95.0 - 65.0)) * (q_A2_net / 1.1)
|
3272
|
-
q_k1 = q_F1_net + (q_B1_net - q_F1_net) / (82.0 - 67.0) * (t_bins[i] - 67.0)
|
3273
|
-
p_k1 = p_F1 + (p_B1 - p_F1) / (82.0 - 67.0) * (t_bins[i] - 67)
|
3274
|
-
q_k2 = q_B2_net + (q_A2_net - q_B2_net) / (95.0 - 82.0) * (t_bins[i] - 82.0)
|
3275
|
-
p_k2 = p_B2 + (p_A2 - p_B2) / (95.0 - 82.0) * (t_bins[i] - 82.0)
|
3276
|
-
|
3277
|
-
if bL <= q_k1
|
3278
|
-
x_k1 = bL / q_k1
|
3279
|
-
q_Tj_N = x_k1 * q_k1 * frac_hours[i]
|
3280
|
-
e_Tj_N = x_k1 * p_k1 * frac_hours[i] / (1 - c_d * (1 - x_k1))
|
3281
|
-
elsif (q_k1 < bL) && (bL <= q_k2)
|
3282
|
-
q_Tj_N = bL * frac_hours[i]
|
3283
|
-
eer_T_j = a + b * t_bins[i] + c * t_bins[i]**2
|
3284
|
-
e_Tj_N = q_Tj_N / eer_T_j
|
3285
|
-
else
|
3286
|
-
q_Tj_N = frac_hours[i] * q_k2
|
3287
|
-
e_Tj_N = frac_hours[i] * p_k2
|
3288
|
-
end
|
3289
|
-
|
3290
|
-
q_tot += q_Tj_N
|
3291
|
-
e_tot += e_Tj_N
|
3292
|
-
end
|
3293
|
-
|
3294
|
-
seer = q_tot / e_tot
|
3295
|
-
return seer
|
3296
|
-
end
|
3297
|
-
|
3298
|
-
def self.set_heat_rated_eirs_mshp(heat_pump, num_speeds)
|
3299
|
-
hp_ap = heat_pump.additional_properties
|
3300
|
-
|
3301
|
-
cops_norm = [1.792, 1.502, 1.308, 1.207, 1.145, 1.105, 1.077, 1.056, 1.041, 1.0]
|
3302
|
-
fan_powers_norm = [0.577, 0.625, 0.673, 0.720, 0.768, 0.814, 0.861, 0.907, 0.954, 1.0]
|
3303
|
-
|
3304
|
-
cop_max_speed = 3.25 # 3.35 is an initial guess, final value solved for below
|
3305
|
-
|
3306
|
-
fan_powers_rated = []
|
3307
|
-
cops_rated = []
|
3308
|
-
|
3309
|
-
for i in 0..num_speeds - 1
|
3310
|
-
fan_powers_rated << hp_ap.fan_power_rated * fan_powers_norm[i]
|
3311
|
-
cops_rated << cop_max_speed * cops_norm[i]
|
3312
|
-
end
|
3313
|
-
|
3314
|
-
cop_max_speed_1 = cop_max_speed
|
3315
|
-
cop_max_speed_2 = cop_max_speed
|
3316
|
-
error = heat_pump.heating_efficiency_hspf - calc_mshp_hspf(cops_rated, hp_ap.heat_c_d, hp_ap.heat_capacity_ratios, hp_ap.heat_rated_cfm_per_ton, fan_powers_rated, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)
|
3317
|
-
|
3318
|
-
error1 = error
|
3319
|
-
error2 = error
|
3320
|
-
|
3321
|
-
itmax = 50 # maximum iterations
|
3322
|
-
cvg = false
|
3323
|
-
final_n = nil
|
3324
|
-
|
3325
|
-
for n in 1..itmax
|
3326
|
-
final_n = n
|
3327
|
-
for i in 0..num_speeds - 1
|
3328
|
-
cops_rated[i] = cop_max_speed * cops_norm[i]
|
3329
|
-
end
|
3330
|
-
|
3331
|
-
error = heat_pump.heating_efficiency_hspf - calc_mshp_hspf(cops_rated, hp_ap.heat_c_d, hp_ap.heat_capacity_ratios, hp_ap.heat_rated_cfm_per_ton, fan_powers_rated, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)
|
3332
|
-
|
3333
|
-
cop_max_speed, cvg, cop_max_speed_1, error1, cop_max_speed_2, error2 = MathTools.Iterate(cop_max_speed, error, cop_max_speed_1, error1, cop_max_speed_2, error2, n, cvg)
|
3334
|
-
|
3335
|
-
if cvg
|
3336
|
-
break
|
3337
|
-
end
|
3338
|
-
end
|
3339
|
-
|
3340
|
-
if (not cvg) || (final_n > itmax)
|
3341
|
-
cop_max_speed = UnitConversions.convert(0.4174 * heat_pump.heating_efficiency_hspf - 1.1134, 'Btu/hr', 'W') # Correlation developed from JonW's MatLab scripts. Only used if a cop cannot be found.
|
3342
|
-
end
|
3343
|
-
|
3344
|
-
hp_ap.heat_rated_eirs = []
|
3345
|
-
for i in 0..num_speeds - 1
|
3346
|
-
hp_ap.heat_rated_eirs << calc_eir_from_cop(cop_max_speed * cops_norm[i], fan_powers_rated[i])
|
3347
|
-
end
|
3348
|
-
end
|
3349
|
-
|
3350
2818
|
def self.set_gshp_assumptions(heat_pump, weather)
|
3351
2819
|
hp_ap = heat_pump.additional_properties
|
3352
2820
|
|
3353
|
-
hp_ap.design_chw = [85.0, weather.design.CoolingDrybulb - 15.0, weather.data.
|
2821
|
+
hp_ap.design_chw = [85.0, weather.design.CoolingDrybulb - 15.0, weather.data.DeepGroundAnnualTemp + 10.0].max # Temperature of water entering indoor coil,use 85F as lower bound
|
3354
2822
|
hp_ap.design_delta_t = 10.0
|
3355
2823
|
hp_ap.fluid_type = Constants.FluidPropyleneGlycol
|
3356
2824
|
hp_ap.frac_glycol = 0.3
|
3357
2825
|
if hp_ap.fluid_type == Constants.FluidWater
|
3358
|
-
hp_ap.design_hw = [45.0, weather.design.HeatingDrybulb + 35.0, weather.data.
|
2826
|
+
hp_ap.design_hw = [45.0, weather.design.HeatingDrybulb + 35.0, weather.data.DeepGroundAnnualTemp - 10.0].max # Temperature of fluid entering indoor coil, use 45F as lower bound for water
|
3359
2827
|
else
|
3360
|
-
hp_ap.design_hw = [35.0, weather.design.HeatingDrybulb + 35.0, weather.data.
|
2828
|
+
hp_ap.design_hw = [35.0, weather.design.HeatingDrybulb + 35.0, weather.data.DeepGroundAnnualTemp - 10.0].min # Temperature of fluid entering indoor coil, use 35F as upper bound
|
3361
2829
|
end
|
3362
2830
|
hp_ap.ground_diffusivity = 0.0208
|
3363
2831
|
hp_ap.grout_conductivity = 0.4 # Btu/h-ft-R
|
@@ -3391,134 +2859,6 @@ class HVAC
|
|
3391
2859
|
hp_ap.shank_spacing = hp_ap.u_tube_spacing + hp_ap.pipe_od # Distance from center of pipe to center of pipe
|
3392
2860
|
end
|
3393
2861
|
|
3394
|
-
def self.calc_mshp_hspf(cop_47, c_d, capacity_ratio, cfm_tons, fan_power_rated, heat_eir_ft_spec, heat_cap_ft_spec)
|
3395
|
-
n_max = (cop_47.length - 1.0) #-3 # Don't use max speed; FIXME: this is different than calc_mshp_seer?
|
3396
|
-
n_min = 0
|
3397
|
-
n_int = (n_min + (n_max - n_min) / 3.0).ceil.to_i
|
3398
|
-
|
3399
|
-
tin = 70.0
|
3400
|
-
tout_3 = 17.0
|
3401
|
-
tout_2 = 35.0
|
3402
|
-
tout_0 = 62.0
|
3403
|
-
|
3404
|
-
eir_H1_2 = calc_eir_from_cop(cop_47[n_max], fan_power_rated[n_max])
|
3405
|
-
eir_H3_2 = eir_H1_2 * MathTools.biquadratic(tin, tout_3, heat_eir_ft_spec[n_max])
|
3406
|
-
|
3407
|
-
eir_adjv = calc_eir_from_cop(cop_47[n_int], fan_power_rated[n_int])
|
3408
|
-
eir_H2_v = eir_adjv * MathTools.biquadratic(tin, tout_2, heat_eir_ft_spec[n_int])
|
3409
|
-
|
3410
|
-
eir_H1_1 = calc_eir_from_cop(cop_47[n_min], fan_power_rated[n_min])
|
3411
|
-
eir_H0_1 = eir_H1_1 * MathTools.biquadratic(tin, tout_0, heat_eir_ft_spec[n_min])
|
3412
|
-
|
3413
|
-
q_H1_2 = capacity_ratio[n_max]
|
3414
|
-
q_H3_2 = q_H1_2 * MathTools.biquadratic(tin, tout_3, heat_cap_ft_spec[n_max])
|
3415
|
-
|
3416
|
-
q_H2_v = capacity_ratio[n_int] * MathTools.biquadratic(tin, tout_2, heat_cap_ft_spec[n_int])
|
3417
|
-
|
3418
|
-
q_H1_1 = capacity_ratio[n_min]
|
3419
|
-
q_H0_1 = q_H1_1 * MathTools.biquadratic(tin, tout_0, heat_cap_ft_spec[n_min])
|
3420
|
-
|
3421
|
-
q_H1_2_net = q_H1_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3422
|
-
q_H3_2_net = q_H3_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3423
|
-
q_H2_v_net = q_H2_v + fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_int] * capacity_ratio[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3424
|
-
q_H1_1_net = q_H1_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3425
|
-
q_H0_1_net = q_H0_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3426
|
-
|
3427
|
-
p_H1_2 = q_H1_2 * eir_H1_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3428
|
-
p_H3_2 = q_H3_2 * eir_H3_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3429
|
-
p_H2_v = q_H2_v * eir_H2_v + fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_int] * capacity_ratio[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3430
|
-
p_H1_1 = q_H1_1 * eir_H1_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3431
|
-
p_H0_1 = q_H0_1 * eir_H0_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
|
3432
|
-
|
3433
|
-
q_H35_2 = 0.9 * (q_H3_2_net + 0.6 * (q_H1_2_net - q_H3_2_net))
|
3434
|
-
p_H35_2 = 0.985 * (p_H3_2 + 0.6 * (p_H1_2 - p_H3_2))
|
3435
|
-
q_H35_1 = q_H1_1_net + (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (35.0 - 47.0)
|
3436
|
-
p_H35_1 = p_H1_1 + (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (35.0 - 47.0)
|
3437
|
-
n_Q = (q_H2_v_net - q_H35_1) / (q_H35_2 - q_H35_1)
|
3438
|
-
m_Q = (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (1 - n_Q) + n_Q * (q_H35_2 - q_H3_2_net) / (35.0 - 17.0)
|
3439
|
-
n_E = (p_H2_v - p_H35_1) / (p_H35_2 - p_H35_1)
|
3440
|
-
m_E = (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (1.0 - n_E) + n_E * (p_H35_2 - p_H3_2) / (35.0 - 17.0)
|
3441
|
-
|
3442
|
-
t_OD = 5.0
|
3443
|
-
dHR = q_H1_2_net * (65.0 - t_OD) / 60.0
|
3444
|
-
|
3445
|
-
c_T_3_1 = q_H1_1_net
|
3446
|
-
c_T_3_2 = (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0)
|
3447
|
-
c_T_3_3 = 0.77 * dHR / (65.0 - t_OD)
|
3448
|
-
t_3 = (47.0 * c_T_3_2 + 65.0 * c_T_3_3 - c_T_3_1) / (c_T_3_2 + c_T_3_3)
|
3449
|
-
q_HT3_1 = q_H1_1_net + (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (t_3 - 47.0)
|
3450
|
-
p_HT3_1 = p_H1_1 + (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (t_3 - 47.0)
|
3451
|
-
cop_T3_1 = q_HT3_1 / p_HT3_1
|
3452
|
-
|
3453
|
-
c_T_v_1 = q_H2_v_net
|
3454
|
-
c_T_v_3 = c_T_3_3
|
3455
|
-
t_v = (35.0 * m_Q + 65.0 * c_T_v_3 - c_T_v_1) / (m_Q + c_T_v_3)
|
3456
|
-
q_HTv_v = q_H2_v_net + m_Q * (t_v - 35.0)
|
3457
|
-
p_HTv_v = p_H2_v + m_E * (t_v - 35.0)
|
3458
|
-
cop_Tv_v = q_HTv_v / p_HTv_v
|
3459
|
-
|
3460
|
-
c_T_4_1 = q_H3_2_net
|
3461
|
-
c_T_4_2 = (q_H35_2 - q_H3_2_net) / (35.0 - 17.0)
|
3462
|
-
c_T_4_3 = c_T_v_3
|
3463
|
-
t_4 = (17.0 * c_T_4_2 + 65.0 * c_T_4_3 - c_T_4_1) / (c_T_4_2 + c_T_4_3)
|
3464
|
-
q_HT4_2 = q_H3_2_net + (q_H35_2 - q_H3_2_net) / (35.0 - 17.0) * (t_4 - 17.0)
|
3465
|
-
p_HT4_2 = p_H3_2 + (p_H35_2 - p_H3_2) / (35.0 - 17.0) * (t_4 - 17.0)
|
3466
|
-
cop_T4_2 = q_HT4_2 / p_HT4_2
|
3467
|
-
|
3468
|
-
d = (t_3**2 - t_4**2) / (t_v**2 - t_4**2)
|
3469
|
-
b = (cop_T4_2 - cop_T3_1 - d * (cop_T4_2 - cop_Tv_v)) / (t_4 - t_3 - d * (t_4 - t_v))
|
3470
|
-
c = (cop_T4_2 - cop_T3_1 - b * (t_4 - t_3)) / (t_4**2 - t_3**2)
|
3471
|
-
a = cop_T4_2 - b * t_4 - c * t_4**2
|
3472
|
-
|
3473
|
-
t_bins = [62.0, 57.0, 52.0, 47.0, 42.0, 37.0, 32.0, 27.0, 22.0, 17.0, 12.0, 7.0, 2.0, -3.0, -8.0]
|
3474
|
-
frac_hours = [0.132, 0.111, 0.103, 0.093, 0.100, 0.109, 0.126, 0.087, 0.055, 0.036, 0.026, 0.013, 0.006, 0.002, 0.001]
|
3475
|
-
|
3476
|
-
# T_off = hp_min_temp
|
3477
|
-
t_off = 10.0
|
3478
|
-
t_on = t_off + 4.0
|
3479
|
-
etot = 0
|
3480
|
-
bLtot = 0
|
3481
|
-
|
3482
|
-
for i in 0..14
|
3483
|
-
bL = ((65.0 - t_bins[i]) / (65.0 - t_OD)) * 0.77 * dHR
|
3484
|
-
|
3485
|
-
q_1 = q_H1_1_net + (q_H0_1_net - q_H1_1_net) / (62.0 - 47.0) * (t_bins[i] - 47.0)
|
3486
|
-
p_1 = p_H1_1 + (p_H0_1 - p_H1_1) / (62.0 - 47.0) * (t_bins[i] - 47.0)
|
3487
|
-
|
3488
|
-
if (t_bins[i] <= 17.0) || (t_bins[i] >= 45.0)
|
3489
|
-
q_2 = q_H3_2_net + (q_H1_2_net - q_H3_2_net) * (t_bins[i] - 17.0) / (47.0 - 17.0)
|
3490
|
-
p_2 = p_H3_2 + (p_H1_2 - p_H3_2) * (t_bins[i] - 17.0) / (47.0 - 17.0)
|
3491
|
-
else
|
3492
|
-
q_2 = q_H3_2_net + (q_H35_2 - q_H3_2_net) * (t_bins[i] - 17) / (35.0 - 17.0)
|
3493
|
-
p_2 = p_H3_2 + (p_H35_2 - p_H3_2) * (t_bins[i] - 17.0) / (35.0 - 17.0)
|
3494
|
-
end
|
3495
|
-
|
3496
|
-
if t_bins[i] <= t_off
|
3497
|
-
delta = 0
|
3498
|
-
elsif t_bins[i] >= t_on
|
3499
|
-
delta = 1.0
|
3500
|
-
else
|
3501
|
-
delta = 0.5
|
3502
|
-
end
|
3503
|
-
|
3504
|
-
if bL <= q_1
|
3505
|
-
x_1 = bL / q_1
|
3506
|
-
e_Tj_n = delta * x_1 * p_1 * frac_hours[i] / (1.0 - c_d * (1.0 - x_1))
|
3507
|
-
elsif (q_1 < bL) && (bL <= q_2)
|
3508
|
-
cop_T_j = a + b * t_bins[i] + c * t_bins[i]**2
|
3509
|
-
e_Tj_n = delta * frac_hours[i] * bL / cop_T_j + (1.0 - delta) * bL * (frac_hours[i])
|
3510
|
-
else
|
3511
|
-
e_Tj_n = delta * frac_hours[i] * p_2 + frac_hours[i] * (bL - delta * q_2)
|
3512
|
-
end
|
3513
|
-
|
3514
|
-
bLtot += frac_hours[i] * bL
|
3515
|
-
etot += e_Tj_n
|
3516
|
-
end
|
3517
|
-
|
3518
|
-
hspf = bLtot / UnitConversions.convert(etot, 'Btu/hr', 'W')
|
3519
|
-
return hspf
|
3520
|
-
end
|
3521
|
-
|
3522
2862
|
def self.calc_sequential_load_fractions(load_fraction, remaining_fraction, availability_days)
|
3523
2863
|
# Returns the EnergyPlus sequential load fractions for every day of the year
|
3524
2864
|
if remaining_fraction > 0
|
@@ -3605,24 +2945,42 @@ class HVAC
|
|
3605
2945
|
if not heat_pump.backup_heating_switchover_temp.nil?
|
3606
2946
|
hp_ap.hp_min_temp = heat_pump.backup_heating_switchover_temp
|
3607
2947
|
hp_ap.supp_max_temp = heat_pump.backup_heating_switchover_temp
|
3608
|
-
|
3609
|
-
if heat_pump.backup_type == HPXML::HeatPumpBackupTypeIntegrated
|
3610
|
-
hp_backup_fuel = heat_pump.backup_heating_fuel
|
3611
|
-
elsif not heat_pump.backup_system.nil?
|
3612
|
-
hp_backup_fuel = heat_pump.backup_system.heating_system_fuel
|
3613
|
-
end
|
3614
|
-
if (hp_backup_fuel == HPXML::FuelTypeElectricity) && (not runner.nil?)
|
3615
|
-
runner.registerError('Switchover temperature should not be used for a heat pump with electric backup; use compressor lockout temperature instead.')
|
3616
|
-
end
|
3617
2948
|
else
|
3618
2949
|
hp_ap.hp_min_temp = heat_pump.compressor_lockout_temp
|
3619
2950
|
hp_ap.supp_max_temp = heat_pump.backup_heating_lockout_temp
|
3620
2951
|
end
|
2952
|
+
|
2953
|
+
# Error-checking
|
2954
|
+
# Can't do this in Schematron because temperatures can be defaulted
|
2955
|
+
if heat_pump.backup_type == HPXML::HeatPumpBackupTypeIntegrated
|
2956
|
+
hp_backup_fuel = heat_pump.backup_heating_fuel
|
2957
|
+
elsif not heat_pump.backup_system.nil?
|
2958
|
+
hp_backup_fuel = heat_pump.backup_system.heating_system_fuel
|
2959
|
+
end
|
2960
|
+
if (hp_backup_fuel == HPXML::FuelTypeElectricity) && (not runner.nil?)
|
2961
|
+
if (not hp_ap.hp_min_temp.nil?) && (not hp_ap.supp_max_temp.nil?) && ((hp_ap.hp_min_temp - hp_ap.supp_max_temp).abs < 5)
|
2962
|
+
if not heat_pump.backup_heating_switchover_temp.nil?
|
2963
|
+
runner.registerError('Switchover temperature should only be used for a heat pump with fossil fuel backup; use compressor lockout temperature instead.')
|
2964
|
+
else
|
2965
|
+
runner.registerError('Similar compressor/backup lockout temperatures should only be used for a heat pump with fossil fuel backup.')
|
2966
|
+
end
|
2967
|
+
end
|
2968
|
+
end
|
2969
|
+
end
|
2970
|
+
|
2971
|
+
def self.get_default_duct_fraction_outside_conditioned_space(ncfl_ag)
|
2972
|
+
# Equation based on ASHRAE 152
|
2973
|
+
# https://www.energy.gov/eere/buildings/downloads/ashrae-standard-152-spreadsheet
|
2974
|
+
f_out = (ncfl_ag <= 1) ? 1.0 : 0.75
|
2975
|
+
return f_out
|
3621
2976
|
end
|
3622
2977
|
|
3623
2978
|
def self.get_default_duct_surface_area(duct_type, ncfl_ag, cfa_served, n_returns)
|
2979
|
+
# Equations based on ASHRAE 152
|
2980
|
+
# https://www.energy.gov/eere/buildings/downloads/ashrae-standard-152-spreadsheet
|
2981
|
+
|
3624
2982
|
# Fraction of primary ducts (ducts outside conditioned space)
|
3625
|
-
f_out = (ncfl_ag
|
2983
|
+
f_out = get_default_duct_fraction_outside_conditioned_space(ncfl_ag)
|
3626
2984
|
|
3627
2985
|
if duct_type == HPXML::DuctTypeSupply
|
3628
2986
|
primary_duct_area = 0.27 * cfa_served * f_out
|
@@ -3636,7 +2994,7 @@ class HVAC
|
|
3636
2994
|
return primary_duct_area, secondary_duct_area
|
3637
2995
|
end
|
3638
2996
|
|
3639
|
-
def self.get_default_duct_locations(
|
2997
|
+
def self.get_default_duct_locations(hpxml_bldg)
|
3640
2998
|
primary_duct_location_hierarchy = [HPXML::LocationBasementConditioned,
|
3641
2999
|
HPXML::LocationBasementUnconditioned,
|
3642
3000
|
HPXML::LocationCrawlspaceConditioned,
|
@@ -3648,12 +3006,12 @@ class HVAC
|
|
3648
3006
|
|
3649
3007
|
primary_duct_location = nil
|
3650
3008
|
primary_duct_location_hierarchy.each do |location|
|
3651
|
-
if
|
3009
|
+
if hpxml_bldg.has_location(location)
|
3652
3010
|
primary_duct_location = location
|
3653
3011
|
break
|
3654
3012
|
end
|
3655
3013
|
end
|
3656
|
-
secondary_duct_location = HPXML::
|
3014
|
+
secondary_duct_location = HPXML::LocationConditionedSpace
|
3657
3015
|
|
3658
3016
|
return primary_duct_location, secondary_duct_location
|
3659
3017
|
end
|
@@ -3682,21 +3040,7 @@ class HVAC
|
|
3682
3040
|
return qgr_values, p_values, ff_chg_values
|
3683
3041
|
end
|
3684
3042
|
|
3685
|
-
def self.
|
3686
|
-
# Cutler curve coefficients for single speed
|
3687
|
-
cool_cap_fflow_spec = [0.718664047, 0.41797409, -0.136638137]
|
3688
|
-
cool_eir_fflow_spec = [1.143487507, -0.13943972, -0.004047787]
|
3689
|
-
return cool_cap_fflow_spec, cool_eir_fflow_spec
|
3690
|
-
end
|
3691
|
-
|
3692
|
-
def self.get_airflow_fault_heating_coeff()
|
3693
|
-
# Cutler curve coefficients for single speed
|
3694
|
-
heat_cap_fflow_spec = [0.694045465, 0.474207981, -0.168253446]
|
3695
|
-
heat_eir_fflow_spec = [2.185418751, -1.942827919, 0.757409168]
|
3696
|
-
return heat_cap_fflow_spec, heat_eir_fflow_spec
|
3697
|
-
end
|
3698
|
-
|
3699
|
-
def self.add_install_quality_calculations(fault_program, tin_sensor, tout_sensor, airflow_rated_defect_ratio, clg_or_htg_coil, model, f_chg, obj_name, mode, defect_ratio)
|
3043
|
+
def self.add_install_quality_calculations(fault_program, tin_sensor, tout_sensor, airflow_rated_defect_ratio, clg_or_htg_coil, model, f_chg, obj_name, mode, defect_ratio, hvac_ap)
|
3700
3044
|
if mode == :clg
|
3701
3045
|
if clg_or_htg_coil.is_a? OpenStudio::Model::CoilCoolingDXSingleSpeed
|
3702
3046
|
num_speeds = 1
|
@@ -3704,8 +3048,13 @@ class HVAC
|
|
3704
3048
|
eir_pow_fff_curves = [clg_or_htg_coil.energyInputRatioFunctionOfFlowFractionCurve.to_CurveQuadratic.get]
|
3705
3049
|
elsif clg_or_htg_coil.is_a? OpenStudio::Model::CoilCoolingDXMultiSpeed
|
3706
3050
|
num_speeds = clg_or_htg_coil.stages.size
|
3707
|
-
|
3708
|
-
|
3051
|
+
if clg_or_htg_coil.stages[0].totalCoolingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.is_initialized
|
3052
|
+
cap_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.totalCoolingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.get }
|
3053
|
+
eir_pow_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get }
|
3054
|
+
else
|
3055
|
+
cap_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.totalCoolingCapacityFunctionofFlowFractionCurve.to_TableLookup.get }
|
3056
|
+
eir_pow_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_TableLookup.get }
|
3057
|
+
end
|
3709
3058
|
elsif clg_or_htg_coil.is_a? OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit
|
3710
3059
|
num_speeds = 1
|
3711
3060
|
cap_fff_curves = [clg_or_htg_coil.totalCoolingCapacityCurve.to_CurveQuadLinear.get] # quadlinear curve, only forth term is for airflow
|
@@ -3730,8 +3079,13 @@ class HVAC
|
|
3730
3079
|
eir_pow_fff_curves = [clg_or_htg_coil.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get]
|
3731
3080
|
elsif clg_or_htg_coil.is_a? OpenStudio::Model::CoilHeatingDXMultiSpeed
|
3732
3081
|
num_speeds = clg_or_htg_coil.stages.size
|
3733
|
-
|
3734
|
-
|
3082
|
+
if clg_or_htg_coil.stages[0].heatingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.is_initialized
|
3083
|
+
cap_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.heatingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.get }
|
3084
|
+
eir_pow_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get }
|
3085
|
+
else
|
3086
|
+
cap_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.heatingCapacityFunctionofFlowFractionCurve.to_TableLookup.get }
|
3087
|
+
eir_pow_fff_curves = clg_or_htg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_TableLookup.get }
|
3088
|
+
end
|
3735
3089
|
elsif clg_or_htg_coil.is_a? OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit
|
3736
3090
|
num_speeds = 1
|
3737
3091
|
cap_fff_curves = [clg_or_htg_coil.heatingCapacityCurve.to_CurveQuadLinear.get] # quadlinear curve, only forth term is for airflow
|
@@ -3753,20 +3107,20 @@ class HVAC
|
|
3753
3107
|
|
3754
3108
|
# Apply Cutler curve airflow coefficients to later equations
|
3755
3109
|
if mode == :clg
|
3756
|
-
cap_fflow_spec, eir_fflow_spec =
|
3110
|
+
cap_fflow_spec, eir_fflow_spec = get_cool_cap_eir_fflow_spec(HPXML::HVACCompressorTypeSingleStage)
|
3757
3111
|
qgr_values, p_values, ff_chg_values = get_charge_fault_cooling_coeff(f_chg)
|
3758
3112
|
suffix = 'clg'
|
3759
3113
|
elsif mode == :htg
|
3760
|
-
cap_fflow_spec, eir_fflow_spec =
|
3114
|
+
cap_fflow_spec, eir_fflow_spec = get_heat_cap_eir_fflow_spec(HPXML::HVACCompressorTypeSingleStage)
|
3761
3115
|
qgr_values, p_values, ff_chg_values = get_charge_fault_heating_coeff(f_chg)
|
3762
3116
|
suffix = 'htg'
|
3763
3117
|
end
|
3764
|
-
fault_program.addLine("Set a1_AF_Qgr_#{suffix} = #{cap_fflow_spec[0]}")
|
3765
|
-
fault_program.addLine("Set a2_AF_Qgr_#{suffix} = #{cap_fflow_spec[1]}")
|
3766
|
-
fault_program.addLine("Set a3_AF_Qgr_#{suffix} = #{cap_fflow_spec[2]}")
|
3767
|
-
fault_program.addLine("Set a1_AF_EIR_#{suffix} = #{eir_fflow_spec[0]}")
|
3768
|
-
fault_program.addLine("Set a2_AF_EIR_#{suffix} = #{eir_fflow_spec[1]}")
|
3769
|
-
fault_program.addLine("Set a3_AF_EIR_#{suffix} = #{eir_fflow_spec[2]}")
|
3118
|
+
fault_program.addLine("Set a1_AF_Qgr_#{suffix} = #{cap_fflow_spec[0][0]}")
|
3119
|
+
fault_program.addLine("Set a2_AF_Qgr_#{suffix} = #{cap_fflow_spec[0][1]}")
|
3120
|
+
fault_program.addLine("Set a3_AF_Qgr_#{suffix} = #{cap_fflow_spec[0][2]}")
|
3121
|
+
fault_program.addLine("Set a1_AF_EIR_#{suffix} = #{eir_fflow_spec[0][0]}")
|
3122
|
+
fault_program.addLine("Set a2_AF_EIR_#{suffix} = #{eir_fflow_spec[0][1]}")
|
3123
|
+
fault_program.addLine("Set a3_AF_EIR_#{suffix} = #{eir_fflow_spec[0][2]}")
|
3770
3124
|
|
3771
3125
|
# charge fault coefficients
|
3772
3126
|
fault_program.addLine("Set a1_CH_Qgr_#{suffix} = #{qgr_values[0]}")
|
@@ -3821,12 +3175,14 @@ class HVAC
|
|
3821
3175
|
fault_program.addLine("Set EIR_IQ_adj_#{suffix} = EIR_Cutler_Curve_After_#{suffix} / EIR_Cutler_Curve_Pre_#{suffix}")
|
3822
3176
|
# NOTE: heat pump (cooling) curves don't exhibit expected trends at extreme faults;
|
3823
3177
|
if (not clg_or_htg_coil.is_a? OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit) && (not clg_or_htg_coil.is_a? OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit)
|
3824
|
-
|
3825
|
-
|
3826
|
-
fault_program.addLine("Set
|
3827
|
-
fault_program.addLine("Set
|
3828
|
-
fault_program.addLine("Set
|
3829
|
-
fault_program.addLine("Set
|
3178
|
+
cap_fff_specs_coeff = (mode == :clg) ? hvac_ap.cool_cap_fflow_spec[speed] : hvac_ap.heat_cap_fflow_spec[speed]
|
3179
|
+
eir_fff_specs_coeff = (mode == :clg) ? hvac_ap.cool_eir_fflow_spec[speed] : hvac_ap.heat_eir_fflow_spec[speed]
|
3180
|
+
fault_program.addLine("Set CAP_c1_#{suffix} = #{cap_fff_specs_coeff[0]}")
|
3181
|
+
fault_program.addLine("Set CAP_c2_#{suffix} = #{cap_fff_specs_coeff[1]}")
|
3182
|
+
fault_program.addLine("Set CAP_c3_#{suffix} = #{cap_fff_specs_coeff[2]}")
|
3183
|
+
fault_program.addLine("Set EIR_c1_#{suffix} = #{eir_fff_specs_coeff[0]}")
|
3184
|
+
fault_program.addLine("Set EIR_c2_#{suffix} = #{eir_fff_specs_coeff[1]}")
|
3185
|
+
fault_program.addLine("Set EIR_c3_#{suffix} = #{eir_fff_specs_coeff[2]}")
|
3830
3186
|
fault_program.addLine("Set cap_curve_v_pre_#{suffix} = (CAP_c1_#{suffix}) + ((CAP_c2_#{suffix})*FF_AF_nodef_#{suffix}) + ((CAP_c3_#{suffix})*FF_AF_nodef_#{suffix}*FF_AF_nodef_#{suffix})")
|
3831
3187
|
fault_program.addLine("Set eir_curve_v_pre_#{suffix} = (EIR_c1_#{suffix}) + ((EIR_c2_#{suffix})*FF_AF_nodef_#{suffix}) + ((EIR_c3_#{suffix})*FF_AF_nodef_#{suffix}*FF_AF_nodef_#{suffix})")
|
3832
3188
|
fault_program.addLine("Set #{cap_fff_act.name} = cap_curve_v_pre_#{suffix} * CAP_IQ_adj_#{suffix}")
|
@@ -3860,9 +3216,11 @@ class HVAC
|
|
3860
3216
|
if not cooling_system.nil?
|
3861
3217
|
charge_defect_ratio = cooling_system.charge_defect_ratio
|
3862
3218
|
cool_airflow_defect_ratio = cooling_system.airflow_defect_ratio
|
3219
|
+
clg_ap = cooling_system.additional_properties
|
3863
3220
|
end
|
3864
3221
|
if not heating_system.nil?
|
3865
3222
|
heat_airflow_defect_ratio = heating_system.airflow_defect_ratio
|
3223
|
+
htg_ap = heating_system.additional_properties
|
3866
3224
|
end
|
3867
3225
|
return if (charge_defect_ratio.to_f.abs < 0.001) && (cool_airflow_defect_ratio.to_f.abs < 0.001) && (heat_airflow_defect_ratio.to_f.abs < 0.001)
|
3868
3226
|
|
@@ -3907,11 +3265,11 @@ class HVAC
|
|
3907
3265
|
fault_program.addLine("Set F_CH = #{f_chg.round(3)}")
|
3908
3266
|
|
3909
3267
|
if not cool_airflow_rated_defect_ratio.empty?
|
3910
|
-
add_install_quality_calculations(fault_program, tin_sensor, tout_sensor, cool_airflow_rated_defect_ratio, clg_coil, model, f_chg, obj_name, :clg, cool_airflow_defect_ratio)
|
3268
|
+
add_install_quality_calculations(fault_program, tin_sensor, tout_sensor, cool_airflow_rated_defect_ratio, clg_coil, model, f_chg, obj_name, :clg, cool_airflow_defect_ratio, clg_ap)
|
3911
3269
|
end
|
3912
3270
|
|
3913
3271
|
if not heat_airflow_rated_defect_ratio.empty?
|
3914
|
-
add_install_quality_calculations(fault_program, tin_sensor, tout_sensor, heat_airflow_rated_defect_ratio, htg_coil, model, f_chg, obj_name, :htg, heat_airflow_defect_ratio)
|
3272
|
+
add_install_quality_calculations(fault_program, tin_sensor, tout_sensor, heat_airflow_rated_defect_ratio, htg_coil, model, f_chg, obj_name, :htg, heat_airflow_defect_ratio, htg_ap)
|
3915
3273
|
end
|
3916
3274
|
program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
|
3917
3275
|
program_calling_manager.setName("#{obj_name} program manager")
|
@@ -3923,13 +3281,13 @@ class HVAC
|
|
3923
3281
|
return 30.0 # W/ton, per ANSI/RESNET/ICC 301-2019 Section 4.4.5 (closed loop)
|
3924
3282
|
end
|
3925
3283
|
|
3926
|
-
def self.apply_shared_systems(
|
3927
|
-
applied_clg = apply_shared_cooling_systems(
|
3928
|
-
applied_htg = apply_shared_heating_systems(
|
3284
|
+
def self.apply_shared_systems(hpxml_bldg)
|
3285
|
+
applied_clg = apply_shared_cooling_systems(hpxml_bldg)
|
3286
|
+
applied_htg = apply_shared_heating_systems(hpxml_bldg)
|
3929
3287
|
return unless (applied_clg || applied_htg)
|
3930
3288
|
|
3931
3289
|
# Remove WLHP if not serving heating nor cooling
|
3932
|
-
|
3290
|
+
hpxml_bldg.heat_pumps.each do |hp|
|
3933
3291
|
next unless hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir
|
3934
3292
|
next if hp.fraction_heat_load_served > 0
|
3935
3293
|
next if hp.fraction_cool_load_served > 0
|
@@ -3938,9 +3296,9 @@ class HVAC
|
|
3938
3296
|
end
|
3939
3297
|
|
3940
3298
|
# Remove any orphaned HVAC distributions
|
3941
|
-
|
3299
|
+
hpxml_bldg.hvac_distributions.each do |hvac_distribution|
|
3942
3300
|
hvac_systems = []
|
3943
|
-
|
3301
|
+
hpxml_bldg.hvac_systems.each do |hvac_system|
|
3944
3302
|
next if hvac_system.distribution_system_idref.nil?
|
3945
3303
|
next unless hvac_system.distribution_system_idref == hvac_distribution.id
|
3946
3304
|
|
@@ -3952,9 +3310,9 @@ class HVAC
|
|
3952
3310
|
end
|
3953
3311
|
end
|
3954
3312
|
|
3955
|
-
def self.apply_shared_cooling_systems(
|
3313
|
+
def self.apply_shared_cooling_systems(hpxml_bldg)
|
3956
3314
|
applied = false
|
3957
|
-
|
3315
|
+
hpxml_bldg.cooling_systems.each do |cooling_system|
|
3958
3316
|
next unless cooling_system.is_shared_system
|
3959
3317
|
|
3960
3318
|
applied = true
|
@@ -3973,7 +3331,7 @@ class HVAC
|
|
3973
3331
|
chiller_input = UnitConversions.convert(cooling_system.cooling_efficiency_kw_per_ton * UnitConversions.convert(cap, 'Btu/hr', 'ton'), 'kW', 'W')
|
3974
3332
|
if distribution_type == HPXML::HVACDistributionTypeHydronic
|
3975
3333
|
if distribution_system.hydronic_type == HPXML::HydronicTypeWaterLoop
|
3976
|
-
wlhp =
|
3334
|
+
wlhp = hpxml_bldg.heat_pumps.find { |hp| hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir }
|
3977
3335
|
aux_dweq = wlhp.cooling_capacity / wlhp.cooling_efficiency_eer
|
3978
3336
|
else
|
3979
3337
|
aux_dweq = 0.0
|
@@ -3991,7 +3349,7 @@ class HVAC
|
|
3991
3349
|
# Cooling tower w/ water loop heat pump
|
3992
3350
|
if distribution_type == HPXML::HVACDistributionTypeHydronic
|
3993
3351
|
if distribution_system.hydronic_type == HPXML::HydronicTypeWaterLoop
|
3994
|
-
wlhp =
|
3352
|
+
wlhp = hpxml_bldg.heat_pumps.find { |hp| hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir }
|
3995
3353
|
wlhp_cap = wlhp.cooling_capacity
|
3996
3354
|
wlhp_input = wlhp_cap / wlhp.cooling_efficiency_eer
|
3997
3355
|
end
|
@@ -4026,45 +3384,45 @@ class HVAC
|
|
4026
3384
|
wlhp.fraction_heat_load_served = 0.0
|
4027
3385
|
else
|
4028
3386
|
# Assign DSE=1
|
4029
|
-
|
4030
|
-
|
4031
|
-
|
4032
|
-
|
4033
|
-
cooling_system.distribution_system_idref =
|
3387
|
+
hpxml_bldg.hvac_distributions.add(id: "#{cooling_system.id}AirDistributionSystem",
|
3388
|
+
distribution_system_type: HPXML::HVACDistributionTypeDSE,
|
3389
|
+
annual_cooling_dse: 1.0,
|
3390
|
+
annual_heating_dse: 1.0)
|
3391
|
+
cooling_system.distribution_system_idref = hpxml_bldg.hvac_distributions[-1].id
|
4034
3392
|
end
|
4035
3393
|
elsif (distribution_type == HPXML::HVACDistributionTypeAir) && (distribution_system.air_type == HPXML::AirTypeFanCoil)
|
4036
3394
|
# Convert "fan coil" air distribution system to "regular velocity"
|
4037
3395
|
if distribution_system.hvac_systems.size > 1
|
4038
3396
|
# Has attached heating system, so create a copy specifically for the cooling system
|
4039
|
-
|
4040
|
-
|
4041
|
-
|
4042
|
-
|
4043
|
-
|
3397
|
+
hpxml_bldg.hvac_distributions.add(id: "#{distribution_system.id}_#{cooling_system.id}",
|
3398
|
+
distribution_system_type: distribution_system.distribution_system_type,
|
3399
|
+
air_type: distribution_system.air_type,
|
3400
|
+
number_of_return_registers: distribution_system.number_of_return_registers,
|
3401
|
+
conditioned_floor_area_served: distribution_system.conditioned_floor_area_served)
|
4044
3402
|
distribution_system.duct_leakage_measurements.each do |lm|
|
4045
|
-
|
3403
|
+
hpxml_bldg.hvac_distributions[-1].duct_leakage_measurements << lm.dup
|
4046
3404
|
end
|
4047
3405
|
distribution_system.ducts.each do |d|
|
4048
|
-
|
3406
|
+
hpxml_bldg.hvac_distributions[-1].ducts << d.dup
|
4049
3407
|
end
|
4050
|
-
cooling_system.distribution_system_idref =
|
3408
|
+
cooling_system.distribution_system_idref = hpxml_bldg.hvac_distributions[-1].id
|
4051
3409
|
end
|
4052
|
-
|
4053
|
-
if
|
3410
|
+
hpxml_bldg.hvac_distributions[-1].air_type = HPXML::AirTypeRegularVelocity
|
3411
|
+
if hpxml_bldg.hvac_distributions[-1].duct_leakage_measurements.select { |lm| (lm.duct_type == HPXML::DuctTypeSupply) && (lm.duct_leakage_total_or_to_outside == HPXML::DuctLeakageToOutside) }.size == 0
|
4054
3412
|
# Assign zero supply leakage
|
4055
|
-
|
4056
|
-
|
4057
|
-
|
4058
|
-
|
3413
|
+
hpxml_bldg.hvac_distributions[-1].duct_leakage_measurements.add(duct_type: HPXML::DuctTypeSupply,
|
3414
|
+
duct_leakage_units: HPXML::UnitsCFM25,
|
3415
|
+
duct_leakage_value: 0,
|
3416
|
+
duct_leakage_total_or_to_outside: HPXML::DuctLeakageToOutside)
|
4059
3417
|
end
|
4060
|
-
if
|
3418
|
+
if hpxml_bldg.hvac_distributions[-1].duct_leakage_measurements.select { |lm| (lm.duct_type == HPXML::DuctTypeReturn) && (lm.duct_leakage_total_or_to_outside == HPXML::DuctLeakageToOutside) }.size == 0
|
4061
3419
|
# Assign zero return leakage
|
4062
|
-
|
4063
|
-
|
4064
|
-
|
4065
|
-
|
3420
|
+
hpxml_bldg.hvac_distributions[-1].duct_leakage_measurements.add(duct_type: HPXML::DuctTypeReturn,
|
3421
|
+
duct_leakage_units: HPXML::UnitsCFM25,
|
3422
|
+
duct_leakage_value: 0,
|
3423
|
+
duct_leakage_total_or_to_outside: HPXML::DuctLeakageToOutside)
|
4066
3424
|
end
|
4067
|
-
|
3425
|
+
hpxml_bldg.hvac_distributions[-1].ducts.each do |d|
|
4068
3426
|
d.id = "#{d.id}_#{cooling_system.id}"
|
4069
3427
|
end
|
4070
3428
|
end
|
@@ -4073,9 +3431,9 @@ class HVAC
|
|
4073
3431
|
return applied
|
4074
3432
|
end
|
4075
3433
|
|
4076
|
-
def self.apply_shared_heating_systems(
|
3434
|
+
def self.apply_shared_heating_systems(hpxml_bldg)
|
4077
3435
|
applied = false
|
4078
|
-
|
3436
|
+
hpxml_bldg.heating_systems.each do |heating_system|
|
4079
3437
|
next unless heating_system.is_shared_system
|
4080
3438
|
|
4081
3439
|
applied = true
|
@@ -4092,7 +3450,7 @@ class HVAC
|
|
4092
3450
|
|
4093
3451
|
# Heat pump
|
4094
3452
|
# If this approach is ever removed, also remove code in HVACSizing.apply_hvac_loads()
|
4095
|
-
wlhp =
|
3453
|
+
wlhp = hpxml_bldg.heat_pumps.find { |hp| hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir }
|
4096
3454
|
wlhp.fraction_heat_load_served = fraction_heat_load_served * (1.0 / wlhp.heating_efficiency_cop)
|
4097
3455
|
wlhp.fraction_cool_load_served = 0.0
|
4098
3456
|
|
@@ -4106,31 +3464,13 @@ class HVAC
|
|
4106
3464
|
return applied
|
4107
3465
|
end
|
4108
3466
|
|
4109
|
-
def self.
|
4110
|
-
|
4111
|
-
|
4112
|
-
if hvac_system.is_a?(HPXML::CoolingSystem) && ([HPXML::HVACTypeRoomAirConditioner, HPXML::HVACTypePTAC].include? hvac_system.cooling_system_type)
|
4113
|
-
hvac_ap.num_speeds = 1
|
4114
|
-
elsif (hvac_system.is_a?(HPXML::CoolingSystem) && (hvac_system.cooling_system_type == HPXML::HVACTypeMiniSplitAirConditioner)) ||
|
4115
|
-
(hvac_system.is_a?(HPXML::HeatPump) && (hvac_system.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit))
|
4116
|
-
hvac_ap.speed_indices = [1, 3, 5, 9] # Speeds we model
|
4117
|
-
hvac_ap.num_speeds = hvac_ap.speed_indices.size
|
4118
|
-
elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
|
4119
|
-
hvac_ap.num_speeds = 1
|
4120
|
-
elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
|
4121
|
-
hvac_ap.num_speeds = 2
|
4122
|
-
elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
|
4123
|
-
hvac_ap.num_speeds = 4
|
4124
|
-
end
|
4125
|
-
end
|
4126
|
-
|
4127
|
-
def self.calc_rated_airflow(capacity, rated_cfm_per_ton, capacity_ratio)
|
4128
|
-
return UnitConversions.convert(capacity, 'Btu/hr', 'ton') * UnitConversions.convert(rated_cfm_per_ton, 'cfm', 'm^3/s') * capacity_ratio
|
3467
|
+
def self.calc_rated_airflow(capacity, rated_cfm_per_ton)
|
3468
|
+
return UnitConversions.convert(capacity, 'Btu/hr', 'ton') * UnitConversions.convert(rated_cfm_per_ton, 'cfm', 'm^3/s')
|
4129
3469
|
end
|
4130
3470
|
|
4131
|
-
def self.is_attached_heating_and_cooling_systems(
|
3471
|
+
def self.is_attached_heating_and_cooling_systems(hpxml_bldg, heating_system, cooling_system)
|
4132
3472
|
# Now only allows furnace+AC
|
4133
|
-
if not ((
|
3473
|
+
if not ((hpxml_bldg.heating_systems.include? heating_system) && (hpxml_bldg.cooling_systems.include? cooling_system))
|
4134
3474
|
return false
|
4135
3475
|
end
|
4136
3476
|
if not (heating_system.heating_system_type == HPXML::HVACTypeFurnace && cooling_system.cooling_system_type == HPXML::HVACTypeCentralAirConditioner)
|
@@ -4140,23 +3480,23 @@ class HVAC
|
|
4140
3480
|
return true
|
4141
3481
|
end
|
4142
3482
|
|
4143
|
-
def self.get_hpxml_hvac_systems(
|
3483
|
+
def self.get_hpxml_hvac_systems(hpxml_bldg)
|
4144
3484
|
# Returns a list of heating/cooling systems, incorporating whether
|
4145
3485
|
# multiple systems are connected to the same distribution system
|
4146
3486
|
# (e.g., a furnace + central air conditioner w/ the same ducts).
|
4147
3487
|
hvac_systems = []
|
4148
3488
|
|
4149
|
-
|
3489
|
+
hpxml_bldg.cooling_systems.each do |cooling_system|
|
4150
3490
|
heating_system = nil
|
4151
|
-
if is_attached_heating_and_cooling_systems(
|
3491
|
+
if is_attached_heating_and_cooling_systems(hpxml_bldg, cooling_system.attached_heating_system, cooling_system)
|
4152
3492
|
heating_system = cooling_system.attached_heating_system
|
4153
3493
|
end
|
4154
3494
|
hvac_systems << { cooling: cooling_system,
|
4155
3495
|
heating: heating_system }
|
4156
3496
|
end
|
4157
3497
|
|
4158
|
-
|
4159
|
-
if is_attached_heating_and_cooling_systems(
|
3498
|
+
hpxml_bldg.heating_systems.each do |heating_system|
|
3499
|
+
if is_attached_heating_and_cooling_systems(hpxml_bldg, heating_system, heating_system.attached_cooling_system)
|
4160
3500
|
next # Already processed with cooling
|
4161
3501
|
end
|
4162
3502
|
|
@@ -4167,7 +3507,7 @@ class HVAC
|
|
4167
3507
|
# Heat pump with backup system must be sorted last so that the last two
|
4168
3508
|
# HVAC systems in the EnergyPlus EquipmentList are 1) the heat pump and
|
4169
3509
|
# 2) the heat pump backup system.
|
4170
|
-
|
3510
|
+
hpxml_bldg.heat_pumps.sort_by { |hp| hp.backup_system_idref.to_s }.each do |heat_pump|
|
4171
3511
|
hvac_systems << { cooling: heat_pump,
|
4172
3512
|
heating: heat_pump }
|
4173
3513
|
end
|
@@ -4175,30 +3515,85 @@ class HVAC
|
|
4175
3515
|
return hvac_systems
|
4176
3516
|
end
|
4177
3517
|
|
4178
|
-
def self.ensure_nonzero_sizing_values(
|
3518
|
+
def self.ensure_nonzero_sizing_values(hpxml_bldg)
|
4179
3519
|
min_capacity = 1.0 # Btuh
|
4180
3520
|
min_airflow = 3.0 # cfm; E+ min airflow is 0.001 m3/s
|
4181
|
-
|
3521
|
+
hpxml_bldg.heating_systems.each do |htg_sys|
|
4182
3522
|
htg_sys.heating_capacity = [htg_sys.heating_capacity, min_capacity].max
|
4183
|
-
|
4184
|
-
htg_sys.heating_airflow_cfm = [htg_sys.heating_airflow_cfm, min_airflow].max
|
4185
|
-
end
|
3523
|
+
htg_sys.heating_airflow_cfm = [htg_sys.heating_airflow_cfm, min_airflow].max unless htg_sys.heating_airflow_cfm.nil?
|
4186
3524
|
end
|
4187
|
-
|
3525
|
+
hpxml_bldg.cooling_systems.each do |clg_sys|
|
4188
3526
|
clg_sys.cooling_capacity = [clg_sys.cooling_capacity, min_capacity].max
|
4189
3527
|
clg_sys.cooling_airflow_cfm = [clg_sys.cooling_airflow_cfm, min_airflow].max
|
3528
|
+
next unless not clg_sys.cooling_detailed_performance_data.empty?
|
3529
|
+
|
3530
|
+
clg_sys.cooling_detailed_performance_data.each do |dp|
|
3531
|
+
speed = dp.capacity_description == HPXML::CapacityDescriptionMinimum ? 1 : 2
|
3532
|
+
dp.capacity = [dp.capacity, min_capacity * speed].max
|
3533
|
+
end
|
4190
3534
|
end
|
4191
|
-
|
3535
|
+
hpxml_bldg.heat_pumps.each do |hp_sys|
|
4192
3536
|
hp_sys.cooling_capacity = [hp_sys.cooling_capacity, min_capacity].max
|
4193
3537
|
hp_sys.cooling_airflow_cfm = [hp_sys.cooling_airflow_cfm, min_airflow].max
|
4194
3538
|
hp_sys.additional_properties.cooling_capacity_sensible = [hp_sys.additional_properties.cooling_capacity_sensible, min_capacity].max
|
4195
3539
|
hp_sys.heating_capacity = [hp_sys.heating_capacity, min_capacity].max
|
4196
3540
|
hp_sys.heating_airflow_cfm = [hp_sys.heating_airflow_cfm, min_airflow].max
|
4197
|
-
|
4198
|
-
|
3541
|
+
hp_sys.heating_capacity_17F = [hp_sys.heating_capacity_17F, min_capacity].max unless hp_sys.heating_capacity_17F.nil?
|
3542
|
+
hp_sys.backup_heating_capacity = [hp_sys.backup_heating_capacity, min_capacity].max unless hp_sys.backup_heating_capacity.nil?
|
3543
|
+
if not hp_sys.heating_detailed_performance_data.empty?
|
3544
|
+
hp_sys.heating_detailed_performance_data.each do |dp|
|
3545
|
+
speed = dp.capacity_description == HPXML::CapacityDescriptionMinimum ? 1 : 2
|
3546
|
+
dp.capacity = [dp.capacity, min_capacity * speed].max
|
3547
|
+
end
|
3548
|
+
end
|
3549
|
+
next unless not hp_sys.cooling_detailed_performance_data.empty?
|
3550
|
+
|
3551
|
+
hp_sys.cooling_detailed_performance_data.each do |dp|
|
3552
|
+
speed = dp.capacity_description == HPXML::CapacityDescriptionMinimum ? 1 : 2
|
3553
|
+
dp.capacity = [dp.capacity, min_capacity * speed].max
|
3554
|
+
end
|
3555
|
+
end
|
3556
|
+
end
|
3557
|
+
|
3558
|
+
def self.apply_unit_multiplier(hpxml_bldg)
|
3559
|
+
# Apply unit multiplier (E+ thermal zone multiplier); E+ sends the
|
3560
|
+
# multiplied thermal zone load to the HVAC system, so the HVAC system
|
3561
|
+
# needs to be sized to meet the entire multiplied zone load.
|
3562
|
+
unit_multiplier = hpxml_bldg.building_construction.number_of_units
|
3563
|
+
hpxml_bldg.heating_systems.each do |htg_sys|
|
3564
|
+
htg_sys.heating_capacity *= unit_multiplier
|
3565
|
+
htg_sys.heating_airflow_cfm *= unit_multiplier unless htg_sys.heating_airflow_cfm.nil?
|
3566
|
+
htg_sys.pilot_light_btuh *= unit_multiplier unless htg_sys.pilot_light_btuh.nil?
|
3567
|
+
htg_sys.electric_auxiliary_energy *= unit_multiplier unless htg_sys.electric_auxiliary_energy.nil?
|
3568
|
+
htg_sys.fan_watts *= unit_multiplier unless htg_sys.fan_watts.nil?
|
3569
|
+
htg_sys.heating_detailed_performance_data.each do |dp|
|
3570
|
+
dp.capacity *= unit_multiplier unless dp.capacity.nil?
|
3571
|
+
end
|
3572
|
+
end
|
3573
|
+
hpxml_bldg.cooling_systems.each do |clg_sys|
|
3574
|
+
clg_sys.cooling_capacity *= unit_multiplier
|
3575
|
+
clg_sys.cooling_airflow_cfm *= unit_multiplier
|
3576
|
+
clg_sys.crankcase_heater_watts *= unit_multiplier unless clg_sys.crankcase_heater_watts.nil?
|
3577
|
+
clg_sys.integrated_heating_system_capacity *= unit_multiplier unless clg_sys.integrated_heating_system_capacity.nil?
|
3578
|
+
clg_sys.integrated_heating_system_airflow_cfm *= unit_multiplier unless clg_sys.integrated_heating_system_airflow_cfm.nil?
|
3579
|
+
clg_sys.cooling_detailed_performance_data.each do |dp|
|
3580
|
+
dp.capacity *= unit_multiplier unless dp.capacity.nil?
|
3581
|
+
end
|
3582
|
+
end
|
3583
|
+
hpxml_bldg.heat_pumps.each do |hp_sys|
|
3584
|
+
hp_sys.cooling_capacity *= unit_multiplier
|
3585
|
+
hp_sys.cooling_airflow_cfm *= unit_multiplier
|
3586
|
+
hp_sys.additional_properties.cooling_capacity_sensible *= unit_multiplier
|
3587
|
+
hp_sys.heating_capacity *= unit_multiplier
|
3588
|
+
hp_sys.heating_airflow_cfm *= unit_multiplier
|
3589
|
+
hp_sys.heating_capacity_17F *= unit_multiplier unless hp_sys.heating_capacity_17F.nil?
|
3590
|
+
hp_sys.backup_heating_capacity *= unit_multiplier unless hp_sys.backup_heating_capacity.nil?
|
3591
|
+
hp_sys.crankcase_heater_watts *= unit_multiplier unless hp_sys.crankcase_heater_watts.nil?
|
3592
|
+
hp_sys.heating_detailed_performance_data.each do |dp|
|
3593
|
+
dp.capacity *= unit_multiplier unless dp.capacity.nil?
|
4199
3594
|
end
|
4200
|
-
|
4201
|
-
|
3595
|
+
hp_sys.cooling_detailed_performance_data.each do |dp|
|
3596
|
+
dp.capacity *= unit_multiplier unless dp.capacity.nil?
|
4202
3597
|
end
|
4203
3598
|
end
|
4204
3599
|
end
|
@@ -4237,7 +3632,7 @@ class HVAC
|
|
4237
3632
|
# and space-constrained) that we don't handle here.
|
4238
3633
|
if is_ducted # Ducted split system
|
4239
3634
|
return hspf2 / 0.85
|
4240
|
-
else #
|
3635
|
+
else # Ductless system
|
4241
3636
|
return hspf2 / 0.90
|
4242
3637
|
end
|
4243
3638
|
end
|