From 1f884e2e88985f9fea4aecd337c4958878ecc0b5 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Tue, 26 Nov 2024 11:35:47 -0700 Subject: [PATCH 1/5] Initial progress. --- HPXMLtoOpenStudio/measure.rb | 13 +- HPXMLtoOpenStudio/measure.xml | 18 +- HPXMLtoOpenStudio/resources/defaults.rb | 37 ++- HPXMLtoOpenStudio/resources/hpxml.rb | 235 ++++++++++++++---- .../hpxml_schematron/EPvalidator.xml | 24 +- HPXMLtoOpenStudio/resources/hvac.rb | 181 +++++++++++++- HPXMLtoOpenStudio/resources/hvac_sizing.rb | 8 + HPXMLtoOpenStudio/resources/model.rb | 5 +- ReportSimulationOutput/measure.rb | 4 +- ReportSimulationOutput/measure.xml | 6 +- ReportUtilityBills/measure.rb | 6 +- ReportUtilityBills/measure.xml | 8 +- .../tests/test_report_utility_bills.rb | 2 +- 13 files changed, 455 insertions(+), 92 deletions(-) diff --git a/HPXMLtoOpenStudio/measure.rb b/HPXMLtoOpenStudio/measure.rb index b22a139b26..be8b854ec3 100644 --- a/HPXMLtoOpenStudio/measure.rb +++ b/HPXMLtoOpenStudio/measure.rb @@ -126,6 +126,14 @@ def run(model, runner, user_arguments) # Write updated HPXML object (w/ defaults) to file for inspection XMLHelper.write_file(hpxml.to_doc, args[:hpxml_defaults_path]) + # When modeling whole SFA/MF buildings, remove shared systems upfront + # from the HPXML object; handle them at the end once the full model + # has been created. + shared_systems_map = {} + if hpxml.header.whole_sfa_or_mf_building_sim + shared_systems_map = hpxml.delete_shared_systems_serving_multiple_dwelling_units() + end + # Create OpenStudio unit model(s) hpxml_osm_map = {} hpxml.buildings.each do |hpxml_bldg| @@ -141,9 +149,12 @@ def run(model, runner, user_arguments) end end - # Merge unit models into final model if hpxml.buildings.size > 1 + # Merge unit models into final model Model.merge_unit_models(model, hpxml_osm_map) + + # Apply shared systems + HVAC.apply_shared_systems(runner, model, hpxml, hpxml_osm_map, shared_systems_map) end # Create EnergyPlus outputs diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml index c32d17a980..1cdbbc6658 100644 --- a/HPXMLtoOpenStudio/measure.xml +++ b/HPXMLtoOpenStudio/measure.xml @@ -3,8 +3,8 @@ 3.1 hpxm_lto_openstudio b1543b30-9465-45ff-ba04-1d1f85e763bc - 324abf52-e522-49dd-ac49-360bad8eb1ba - 2024-11-21T20:15:41Z + 05d1c691-8e2f-4b24-ac72-37ed91ce927f + 2024-11-26T18:31:43Z D8922A73 HPXMLtoOpenStudio HPXML to OpenStudio Translator @@ -183,7 +183,7 @@ measure.rb rb script - D7F18DFB + 7A8113DC airflow.rb @@ -327,7 +327,7 @@ defaults.rb rb resource - 515B05C5 + 12FBBBA9 energyplus.rb @@ -357,7 +357,7 @@ hpxml.rb rb resource - 5173207E + 68D7F8FA hpxml_schema/HPXML.xsd @@ -375,7 +375,7 @@ hpxml_schematron/EPvalidator.xml xml resource - 71347401 + 3F51B0F0 hpxml_schematron/iso-schematron.xsd @@ -387,13 +387,13 @@ hvac.rb rb resource - 0DF759D2 + FD4CC52B hvac_sizing.rb rb resource - 8A5C303C + 13130390 internal_gains.rb @@ -447,7 +447,7 @@ model.rb rb resource - ED1985F0 + 6909951F output.rb diff --git a/HPXMLtoOpenStudio/resources/defaults.rb b/HPXMLtoOpenStudio/resources/defaults.rb index 69c270f869..968aefc1f2 100644 --- a/HPXMLtoOpenStudio/resources/defaults.rb +++ b/HPXMLtoOpenStudio/resources/defaults.rb @@ -41,7 +41,7 @@ def self.apply(runner, hpxml, hpxml_bldg, weather, schedules_file: nil, convert_ end # Check for presence of fuels once - has_fuel = hpxml_bldg.has_fuels(hpxml.to_doc) + has_fuel = hpxml_bldg.has_fuels() add_zones_spaces_if_needed(hpxml_bldg, unit_num) @@ -72,7 +72,7 @@ def self.apply(runner, hpxml, hpxml_bldg, weather, schedules_file: nil, convert_ apply_doors(hpxml_bldg) apply_partition_wall_mass(hpxml_bldg) apply_furniture_mass(hpxml_bldg) - apply_hvac(runner, hpxml_bldg, weather, convert_shared_systems, unit_num) + apply_hvac(runner, hpxml.header, hpxml_bldg, weather, convert_shared_systems, unit_num) apply_hvac_control(hpxml_bldg, schedules_file, eri_version) apply_hvac_distribution(hpxml_bldg) apply_infiltration(hpxml_bldg) @@ -237,6 +237,13 @@ def self.apply_header(hpxml_header, hpxml_bldg, weather) unavailable_period.natvent_availability_isdefaulted = true end end + + if hpxml_header.shared_boiler_operation.nil? + if hpxml_bldg.heating_systems.select { |htg| htg.heating_system_type == HPXML::HVACTypeBoiler && htg.is_shared_system_serving_multiple_dwelling_units }.size > 0 + hpxml_header.shared_boiler_operation = HPXML::SharedBoilerOperationSequenced + hpxml_header.shared_boiler_operation_isdefaulted = true + end + end end # Assigns default values for omitted optional inputs in the HPXML::BuildingHeader object @@ -1832,14 +1839,15 @@ def self.apply_furniture_mass(hpxml_bldg) # HPXML::CoolingSystem, and HPXML::HeatPump objects # # @param runner [OpenStudio::Measure::OSRunner] Object typically used to display warnings + # @param hpxml_header [HPXML::Header] HPXML Header object (one per HPXML file) # @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit # @param weather [WeatherFile] Weather object containing EPW information # @param convert_shared_systems [Boolean] Whether to convert shared systems to equivalent in-unit systems per ANSI 301 # @param unit_num [Integer] Dwelling unit number # @return [nil] - def self.apply_hvac(runner, hpxml_bldg, weather, convert_shared_systems, unit_num) + def self.apply_hvac(runner, hpxml_header, hpxml_bldg, weather, convert_shared_systems, unit_num) if convert_shared_systems - HVAC.apply_shared_systems(hpxml_bldg) + HVAC.convert_shared_systems_to_in_unit_systems(hpxml_bldg, hpxml_header) end # Convert negative values (e.g., -1) to nil as appropriate @@ -2501,6 +2509,27 @@ def self.apply_hvac_control(hpxml_bldg, schedules_file, eri_version) # @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit # @return [nil] def self.apply_hvac_distribution(hpxml_bldg) + # Hydronic distribution + hpxml_bldg.hvac_distributions.each do |hvac_distribution| + next unless hvac_distribution.hvac_systems.any? { |h| h.is_a?(HPXML::HeatingSystem) && h.heating_system_type == HPXML::HVACTypeBoiler } + + # Supply/return loop temperatures + default_delta_t = 20.0 # deg-F + if hvac_distribution.hydronic_supply_temp.nil? + if not hvac_distribution.hydronic_return_temp.nil? + hvac_distribution.hydronic_supply_temp = hvac_distribution.hydronic_return_temp + default_delta_t # deg-F + else + hvac_distribution.hydronic_supply_temp = 180.0 # deg-F + end + hvac_distribution.hydronic_supply_temp_isdefaulted = true + end + if hvac_distribution.hydronic_return_temp.nil? + hvac_distribution.hydronic_return_temp = hvac_distribution.hydronic_supply_temp - default_delta_t # deg-F + hvac_distribution.hydronic_return_temp_isdefaulted = true + end + end + + # Air distribution ncfl_ag = hpxml_bldg.building_construction.number_of_conditioned_floors_above_grade ncfl = hpxml_bldg.building_construction.number_of_conditioned_floors diff --git a/HPXMLtoOpenStudio/resources/hpxml.rb b/HPXMLtoOpenStudio/resources/hpxml.rb index 3d3798c4f1..cf27dd46eb 100644 --- a/HPXMLtoOpenStudio/resources/hpxml.rb +++ b/HPXMLtoOpenStudio/resources/hpxml.rb @@ -368,6 +368,8 @@ class HPXML < Object ScheduleRegular = 'regular schedule' ScheduleAvailable = 'always available' ScheduleUnavailable = 'always unavailable' + SharedBoilerOperationSequenced = 'sequenced' + SharedBoilerOperationSimultaneous = 'simultaneous' ShieldingExposed = 'exposed' ShieldingNormal = 'normal' ShieldingWellShielded = 'well-shielded' @@ -660,42 +662,85 @@ def set_unique_hpxml_ids(hpxml_doc, last_building_only = false) # Returns a hash with whether each fuel exists in the HPXML Building or Buildings # - # @param hpxml_doc [Oga::XML::Document] HPXML object as an XML document # @param building_id [String] If provided, only search the single HPXML Building with the given ID # @return [Hash] Map of HPXML::FuelTypeXXX => boolean - def has_fuels(hpxml_doc, building_id = nil) + def has_fuels(building_id = nil) has_fuels = {} - fuel_element_names = ['HeatingSystemFuel', - 'CoolingSystemFuel', - 'HeatPumpFuel', - 'BackupSystemFuel', - 'FuelType', - 'IntegratedHeatingSystemFuel', - 'Heater/Type'] - HPXML::fossil_fuels.each do |fuel| has_fuels[fuel] = false - fuel_element_names.each do |fuel_element_name| - if fuel_element_name == 'Heater/Type' && fuel == HPXML::FuelTypeNaturalGas - fuel_element_value = HPXML::HeaterTypeGas - else - fuel_element_value = fuel + + buildings.each do |hpxml_bldg| + next if (not building_id.nil? && hpxml_bldg.building_id != building_id) + + # Check HVAC systems + hpxml_bldg.hvac_systems.each do |hvac_system| + if hvac_system.respond_to?(:heating_system_fuel) && hvac_system.heating_system_fuel == fuel + has_fuels[fuel] = true + end + if hvac_system.respond_to?(:cooling_system_fuel) && hvac_system.cooling_system_fuel == fuel + has_fuels[fuel] = true + end + if hvac_system.respond_to?(:heat_pump_fuel) && hvac_system.heat_pump_fuel == fuel + has_fuels[fuel] = true + end + if hvac_system.respond_to?(:backup_heating_fuel) && hvac_system.backup_heating_fuel == fuel + has_fuels[fuel] = true + end + if hvac_system.respond_to?(:integrated_heating_system_fuel) && hvac_system.integrated_heating_system_fuel == fuel + has_fuels[fuel] = true + end end - search_str = "/HPXML/Building[BuildingID/@id='#{building_id}']//#{fuel_element_name}[text() = '#{fuel_element_value}']" - if building_id.nil? - search_str = "/HPXML/Building//#{fuel_element_name}[text() = '#{fuel_element_value}']" + + # Check other appliances + (hpxml_bldg.water_heating_systems + + hpxml_bldg.generators + + hpxml_bldg.clothes_dryers + + hpxml_bldg.cooking_ranges + + hpxml_bldg.fuel_loads).each do |appliance| + if appliance.fuel_type == fuel + has_fuels[fuel] = true + end end - if XMLHelper.has_element(hpxml_doc, search_str) - has_fuels[fuel] = true - break + + # Check pool/spa heaters + if fuel == HPXML::FuelTypeNaturalGas + (hpxml_bldg.pools + hpxml_bldg.permanent_spas).each do |pool_or_spa| + if pool_or_spa.heater_type == HPXML::HeaterTypeGas + has_fuels[fuel] = true + end + end end + + break if has_fuels[fuel] end end return has_fuels end + # Delete any shared HVAC systems that are actually modeled as systems serving multiple dwelling units. + # Shared systems that are modeled as equivalent in-unit systems per ANSI 301 are not deleted. + # + # @return [Hash] Map of HPXML Building => [deleted_systems] + def delete_shared_systems_serving_multiple_dwelling_units() + deleted_systems_map = {} + buildings.each do |hpxml_bldg| + hpxml_bldg.hvac_systems.each do |hvac_system| + next unless hvac_system.is_shared_system_serving_multiple_dwelling_units + + deleted_systems_map[hpxml_bldg] = [] if deleted_systems_map[hpxml_bldg].nil? + deleted_systems_map[hpxml_bldg] << hvac_system + end + end + deleted_systems_map.values.each do |deleted_systems| + deleted_systems.reverse_each do |deleted_system| + deleted_system.delete + end + end + return deleted_systems_map + end + # Object to store additional properties on an HPXML object that are not intended # to end up in the HPXML file. For example, you can store the OpenStudio::Model::Space # object for an appliance. @@ -844,6 +889,7 @@ def initialize(hpxml_element, *args, **kwargs) :software_program_version, # [String] SoftwareInfo/SoftwareProgramVersion :apply_ashrae140_assumptions, # [Boolean] SoftwareInfo/extension/ApplyASHRAE140Assumptions :whole_sfa_or_mf_building_sim, # [Boolean] SoftwareInfo/extension/WholeSFAorMFBuildingSimulation + :shared_boiler_operation, # [String] SoftwareInfo/extension/SharedHVACSizingControl/SharedBoilerOperation (HPXML::SharedBoilerXXX) :eri_calculation_version, # [String] SoftwareInfo/extension/ERICalculation/Version :co2index_calculation_version, # [String] SoftwareInfo/extension/CO2IndexCalculation/Version :energystar_calculation_version, # [String] SoftwareInfo/extension/EnergyStarCalculation/Version @@ -907,6 +953,10 @@ def to_doc(hpxml_doc) XMLHelper.add_element(software_info, 'SoftwareProgramVersion', @software_program_version, :string) unless @software_program_version.nil? XMLHelper.add_extension(software_info, 'ApplyASHRAE140Assumptions', @apply_ashrae140_assumptions, :boolean) unless @apply_ashrae140_assumptions.nil? XMLHelper.add_extension(software_info, 'WholeSFAorMFBuildingSimulation', @whole_sfa_or_mf_building_sim, :boolean) unless @whole_sfa_or_mf_building_sim.nil? + if not @shared_boiler_operation.nil? + hvac_sizing_control = XMLHelper.create_elements_as_needed(software_info, ['extension', 'SharedHVACSizingControl']) + XMLHelper.add_element(hvac_sizing_control, 'SharedBoilerOperation', @shared_boiler_operation, :string, @shared_boiler_operation_isdefaulted) + end { 'ERICalculation' => @eri_calculation_version, 'CO2IndexCalculation' => @co2index_calculation_version, 'EnergyStarCalculation' => @energystar_calculation_version, @@ -970,6 +1020,7 @@ def from_doc(hpxml) @heat_pump_backup_heating_capacity_increment = XMLHelper.get_value(hpxml, 'SoftwareInfo/extension/SimulationControl/AdvancedResearchFeatures/HeatPumpBackupCapacityIncrement', :float) @apply_ashrae140_assumptions = XMLHelper.get_value(hpxml, 'SoftwareInfo/extension/ApplyASHRAE140Assumptions', :boolean) @whole_sfa_or_mf_building_sim = XMLHelper.get_value(hpxml, 'SoftwareInfo/extension/WholeSFAorMFBuildingSimulation', :boolean) + @shared_boiler_operation = XMLHelper.get_value(hpxml, 'SoftwareInfo/extension/SharedHVACSizingControl/SharedBoilerOperation', :string) @emissions_scenarios.from_doc(hpxml) @utility_bill_scenarios.from_doc(hpxml) @unavailable_periods.from_doc(hpxml) @@ -1714,11 +1765,10 @@ def has_fuel_access # Returns a hash with whether each fuel exists in the HPXML Building. # - # @param hpxml_doc [Oga::XML::Document] HPXML object as an XML document # @return [Hash] Map of HPXML::FuelTypeXXX => boolean - def has_fuels(hpxml_doc) + def has_fuels() # Returns a hash with whether each fuel exists in the HPXML Building - return @parent_object.has_fuels(hpxml_doc, @building_id) + return @parent_object.has_fuels(@building_id) end # Returns the predominant heating fuel type (weighted by fraction of @@ -2130,24 +2180,26 @@ def check_for_errors errors << 'More than one cooling system designated as the primary.' end - # Check for at most 1 shared heating system and 1 shared cooling system - num_htg_shared = 0 - num_clg_shared = 0 - (@heating_systems + @heat_pumps).each do |hvac_system| - next unless hvac_system.is_shared_system + if not @parent_object.header.whole_sfa_or_mf_building_sim + # Check for at most 1 shared heating system and 1 shared cooling system + num_htg_shared = 0 + num_clg_shared = 0 + (@heating_systems + @heat_pumps).each do |hvac_system| + next unless hvac_system.is_shared_system - num_htg_shared += 1 - end - (@cooling_systems + @heat_pumps).each do |hvac_system| - next unless hvac_system.is_shared_system + num_htg_shared += 1 + end + (@cooling_systems + @heat_pumps).each do |hvac_system| + next unless hvac_system.is_shared_system - num_clg_shared += 1 - end - if num_htg_shared > 1 - errors << 'More than one shared heating system found.' - end - if num_clg_shared > 1 - errors << 'More than one shared cooling system found.' + num_clg_shared += 1 + end + if num_htg_shared > 1 + errors << 'More than one shared heating system found.' + end + if num_clg_shared > 1 + errors << 'More than one shared cooling system found.' + end end return errors @@ -6380,6 +6432,7 @@ def initialize(hpxml_element, *args, **kwargs) CLASS_ATTRS = [:heating_detailed_performance_data] # [HPXML::HeatingDetailedPerformanceData] ATTRS = [:primary_system, # [Boolean] ../PrimarySystems/PrimaryHeatingSystem/@id :id, # [String] SystemIdentifier/@id + :sameas_id, # [String] SystemIdentifier/@sameas :attached_to_zone_idref, # [String] AttachedToZone/@idref :location, # [String] UnitLocation (HPXML::LocationXXX) :year_installed, # [Integer] YearInstalled @@ -6487,6 +6540,35 @@ def is_heat_pump_backup_system return !primary_heat_pump.nil? end + # Returns whether if we are modeling a whole MF building and the shared system is explicitly modeled. + # Shared systems that are modeled as equivalent in-unit systems per ANSI 301 are not included. + # + # @return [Boolean] True if modeling a whole MF building and its a shared system + def is_shared_system_serving_multiple_dwelling_units + if @parent_object.parent_object.header.whole_sfa_or_mf_building_sim + actual_system = self + if !@sameas_id.nil? + actual_system = sameas + end + + if actual_system.is_shared_system + # Currently central boilers are the only technology explicitly modeled as serving multiple dwelling units + if actual_system.is_a?(HPXML::HeatingSystem) && actual_system.heating_system_type == HPXML::HVACTypeBoiler + return true + end + end + end + + return false + end + + # Returns the shared object specified elsewhere in the HPXML. + # + # @return [HPXML::HeatingSystem] HeatingSystem object linked by sameas attribute + def sameas + return HPXML::get_sameas_obj(@parent_object.parent_object, @sameas_id) + end + # Deletes the current object from the array. # # @return [nil] @@ -6522,6 +6604,7 @@ def to_doc(building) heating_system = XMLHelper.add_element(hvac_plant, 'HeatingSystem') sys_id = XMLHelper.add_element(heating_system, 'SystemIdentifier') XMLHelper.add_attribute(sys_id, 'id', @id) + XMLHelper.add_attribute(sys_id, 'sameas', @sameas_id) unless @sameas_id.nil? if not @attached_to_zone_idref.nil? zone_attached = XMLHelper.add_element(heating_system, 'AttachedToZone') XMLHelper.add_attribute(zone_attached, 'idref', @attached_to_zone_idref) @@ -6592,6 +6675,7 @@ def from_doc(heating_system) return if heating_system.nil? @id = HPXML::get_id(heating_system) + @sameas_id = HPXML::get_sameas_id(heating_system) @attached_to_zone_idref = HPXML::get_idref(XMLHelper.get_elements(heating_system, 'AttachedToZone')[0]) @location = XMLHelper.get_value(heating_system, 'UnitLocation', :string) @year_installed = XMLHelper.get_value(heating_system, 'YearInstalled', :integer) @@ -6678,6 +6762,7 @@ def initialize(hpxml_element, *args, **kwargs) CLASS_ATTRS = [:cooling_detailed_performance_data] # [HPXML::CoolingDetailedPerformanceData] ATTRS = [:primary_system, # [Boolean] ../PrimarySystems/PrimaryCoolingSystem/@idref :id, # [String] SystemIdentifier/@id + :sameas_id, # [String] SystemIdentifier/@sameas :attached_to_zone_idref, # [String] AttachedToZone/@idref :location, # [String] UnitLocation (HPXML::LocationXXX) :year_installed, # [Integer] YearInstalled @@ -6768,6 +6853,22 @@ def has_integrated_heating return true end + # Returns whether if we are modeling a whole MF building and the shared system is explicitly modeled. + # Shared systems that are modeled as equivalent in-unit systems per ANSI 301 are not included. + # + # @return [Boolean] True if modeling a whole MF building and its a shared system + def is_shared_system_serving_multiple_dwelling_units + # Currently no shared cooling systems are explicitly modeled + return false + end + + # Returns the shared object specified elsewhere in the HPXML. + # + # @return [HPXML::CoolingSystem] CoolingSystem object linked by sameas attribute + def sameas + return HPXML::get_sameas_obj(@parent_object.parent_object, @sameas_id) + end + # Deletes the current object from the array. # # @return [nil] @@ -6803,6 +6904,7 @@ def to_doc(building) cooling_system = XMLHelper.add_element(hvac_plant, 'CoolingSystem') sys_id = XMLHelper.add_element(cooling_system, 'SystemIdentifier') XMLHelper.add_attribute(sys_id, 'id', @id) + XMLHelper.add_attribute(sys_id, 'sameas', @sameas_id) unless @sameas_id.nil? if not @attached_to_zone_idref.nil? zone_attached = XMLHelper.add_element(cooling_system, 'AttachedToZone') XMLHelper.add_attribute(zone_attached, 'idref', @attached_to_zone_idref) @@ -6883,6 +6985,7 @@ def from_doc(cooling_system) return if cooling_system.nil? @id = HPXML::get_id(cooling_system) + @sameas_id = HPXML::get_sameas_id(cooling_system) @attached_to_zone_idref = HPXML::get_idref(XMLHelper.get_elements(cooling_system, 'AttachedToZone')[0]) @location = XMLHelper.get_value(cooling_system, 'UnitLocation', :string) @year_installed = XMLHelper.get_value(cooling_system, 'YearInstalled', :integer) @@ -6976,6 +7079,7 @@ def initialize(hpxml_element, *args, **kwargs) ATTRS = [:primary_heating_system, # [Boolean] ../PrimarySystems/PrimaryHeatingSystem/@idref :primary_cooling_system, # [Boolean] ../PrimarySystems/PrimaryCoolingSystem/@idref :id, # [String] SystemIdentifier/@id + :sameas_id, # [String] SystemIdentifier/@sameas :attached_to_zone_idref, # [String] AttachedToZone/@idref :location, # [String] UnitLocation (HPXML::LocationXXX) :year_installed, # [Integer] YearInstalled @@ -7114,6 +7218,22 @@ def backup_system end end + # Returns whether if we are modeling a whole MF building and the shared system is explicitly modeled. + # Shared systems that are modeled as equivalent in-unit systems per ANSI 301 are not included. + # + # @return [Boolean] True if modeling a whole MF building and its a shared system + def is_shared_system_serving_multiple_dwelling_units + # Currently no shared heat pumps are explicitly modeled + return false + end + + # Returns the shared object specified elsewhere in the HPXML. + # + # @return [HPXML::HeatPump] HeatPump object linked by sameas attribute + def sameas + return HPXML::get_sameas_obj(@parent_object.parent_object, @sameas_id) + end + # Deletes the current object from the array. # # @return [nil] @@ -7151,6 +7271,7 @@ def to_doc(building) heat_pump = XMLHelper.add_element(hvac_plant, 'HeatPump') sys_id = XMLHelper.add_element(heat_pump, 'SystemIdentifier') XMLHelper.add_attribute(sys_id, 'id', @id) + XMLHelper.add_attribute(sys_id, 'sameas', @sameas_id) unless @sameas_id.nil? if not @attached_to_zone_idref.nil? zone_attached = XMLHelper.add_element(heat_pump, 'AttachedToZone') XMLHelper.add_attribute(zone_attached, 'idref', @attached_to_zone_idref) @@ -7274,6 +7395,7 @@ def from_doc(heat_pump) return if heat_pump.nil? @id = HPXML::get_id(heat_pump) + @sameas_id = HPXML::get_sameas_id(heat_pump) @attached_to_zone_idref = HPXML::get_idref(XMLHelper.get_elements(heat_pump, 'AttachedToZone')[0]) @location = XMLHelper.get_value(heat_pump, 'UnitLocation', :string) @year_installed = XMLHelper.get_value(heat_pump, 'YearInstalled', :integer) @@ -7697,11 +7819,14 @@ def initialize(hpxml_bldg, *args, **kwargs) :ducts, # [HPXML::Ducts] :manualj_duct_loads] # [HPXML::ManualJDuctLoads] ATTRS = [:id, # [String] SystemIdentifier/@id + :sameas_id, # [String] SystemIdentifier/@sameas :distribution_system_type, # [String] DistributionSystemType/* (HPXML::HVACDistributionTypeXXX) :number_of_return_registers, # [Integer] DistributionSystemType/AirDistribution/NumberofReturnRegisters :air_type, # [String] DistributionSystemType/AirDistribution/AirDistributionType (HPXML::AirTypeXXX) :manualj_blower_fan_heat_btuh, # [Double] DistributionSystemType/AirDistribution/extension/ManualJInputs/BlowerFanHeatBtuh (Btu/hr) :hydronic_type, # [String] DistributionSystemType/HydronicDistribution/HydronicDistributionType (HPXML::HydronicTypeXXX) + :hydronic_supply_temp, # [Double] DistributionSystemType/HydronicDistribution/SupplyTemperature (F) + :hydronic_return_temp, # [Double] DistributionSystemType/HydronicDistribution/ReturnTemperature (F) :manualj_hot_water_piping_btuh, # [Double] DistributionSystemType/HydronicDistribution/extension/ManualJInputs/HotWaterPipingBtuh (Btu/hr) :annual_heating_dse, # [Double] DistributionSystemType/Other/AnnualHeatingDistributionSystemEfficiency (frac) :annual_cooling_dse, # [Double] DistributionSystemType/Other/AnnualCoolingDistributionSystemEfficiency (frac) @@ -7736,16 +7861,25 @@ def hvac_systems end end - if num_clg > 1 - fail "Multiple cooling systems found attached to distribution system '#{@id}'." - end - if num_htg > 1 - fail "Multiple heating systems found attached to distribution system '#{@id}'." + if not @parent_object.parent_object.header.whole_sfa_or_mf_building_sim + if num_clg > 1 + fail "Multiple cooling systems found attached to distribution system '#{@id}'." + end + if num_htg > 1 + fail "Multiple heating systems found attached to distribution system '#{@id}'." + end end return list end + # Returns the shared system object elsewhere in the HPXML. + # + # @return [HPXML::HVACDistribution] HVACDistribution object linked by sameas attribute + def sameas + return HPXML::get_sameas_obj(@parent_object.parent_object, @sameas_id) + end + # Deletes the current object from the array. # # @return [nil] @@ -7787,21 +7921,23 @@ def to_doc(building) hvac_distribution = XMLHelper.add_element(hvac, 'HVACDistribution') sys_id = XMLHelper.add_element(hvac_distribution, 'SystemIdentifier') XMLHelper.add_attribute(sys_id, 'id', @id) - distribution_system_type_el = XMLHelper.add_element(hvac_distribution, 'DistributionSystemType') + XMLHelper.add_attribute(sys_id, 'sameas', @sameas_id) unless @sameas_id.nil? if [HVACDistributionTypeAir, HVACDistributionTypeHydronic].include? @distribution_system_type + distribution_system_type_el = XMLHelper.add_element(hvac_distribution, 'DistributionSystemType') XMLHelper.add_element(distribution_system_type_el, @distribution_system_type) XMLHelper.add_element(hvac_distribution, 'ConditionedFloorAreaServed', @conditioned_floor_area_served, :float) unless @conditioned_floor_area_served.nil? elsif [HVACDistributionTypeDSE].include? @distribution_system_type + distribution_system_type_el = XMLHelper.add_element(hvac_distribution, 'DistributionSystemType') XMLHelper.add_element(distribution_system_type_el, 'Other', @distribution_system_type, :string) XMLHelper.add_element(hvac_distribution, 'AnnualHeatingDistributionSystemEfficiency', @annual_heating_dse, :float) unless @annual_heating_dse.nil? XMLHelper.add_element(hvac_distribution, 'AnnualCoolingDistributionSystemEfficiency', @annual_cooling_dse, :float) unless @annual_cooling_dse.nil? - else - fail "Unexpected distribution_system_type '#{@distribution_system_type}'." end if [HPXML::HVACDistributionTypeHydronic].include? @distribution_system_type hydronic_distribution = XMLHelper.get_element(hvac_distribution, 'DistributionSystemType/HydronicDistribution') XMLHelper.add_element(hydronic_distribution, 'HydronicDistributionType', @hydronic_type, :string) unless @hydronic_type.nil? + XMLHelper.add_element(hydronic_distribution, 'SupplyTemperature', @hydronic_supply_temp, :float, @hydronic_supply_temp_isdefaulted) unless @hydronic_supply_temp.nil? + XMLHelper.add_element(hydronic_distribution, 'ReturnTemperature', @hydronic_return_temp, :float, @hydronic_return_temp_isdefaulted) unless @hydronic_return_temp.nil? if not @manualj_hot_water_piping_btuh.nil? manualj_inputs = XMLHelper.create_elements_as_needed(hydronic_distribution, ['extension', 'ManualJInputs']) XMLHelper.add_element(manualj_inputs, 'HotWaterPipingBtuh', @manualj_hot_water_piping_btuh, :float, @manualj_hot_water_piping_btuh_isdefaulted) @@ -7829,6 +7965,7 @@ def from_doc(hvac_distribution) return if hvac_distribution.nil? @id = HPXML::get_id(hvac_distribution) + @sameas_id = HPXML::get_sameas_id(hvac_distribution) @distribution_system_type = XMLHelper.get_child_name(hvac_distribution, 'DistributionSystemType') if @distribution_system_type == 'Other' @distribution_system_type = XMLHelper.get_value(XMLHelper.get_element(hvac_distribution, 'DistributionSystemType'), 'Other', :string) @@ -7842,6 +7979,8 @@ def from_doc(hvac_distribution) if not hydronic_distribution.nil? @hydronic_type = XMLHelper.get_value(hydronic_distribution, 'HydronicDistributionType', :string) + @hydronic_supply_temp = XMLHelper.get_value(hydronic_distribution, 'SupplyTemperature', :float) + @hydronic_return_temp = XMLHelper.get_value(hydronic_distribution, 'ReturnTemperature', :float) @manualj_hot_water_piping_btuh = XMLHelper.get_value(hydronic_distribution, 'extension/ManualJInputs/HotWaterPipingBtuh', :float) end if not air_distribution.nil? diff --git a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml index 68763aef0c..bf6fd48fae 100644 --- a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml +++ b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml @@ -18,6 +18,7 @@ Expected 0 or more element(s) for xpath: extension/EmissionsScenarios/EmissionsScenario Expected 0 or more element(s) for xpath: extension/UtilityBillScenarios/UtilityBillScenario Expected 0 or more element(s) for xpath: extension/UnavailablePeriods/UnavailablePeriod + Expected 0 or 1 element(s) for xpath: extension/WholeSFAorMFBuildingSimulation extension/SchedulesFilePath has been replaced by /HPXML/Building/BuildingDetails/BuildingSummary/extension/SchedulesFilePath extension/HVACSizingControl has been replaced by /HPXML/Building/BuildingDetails/BuildingSummary/extension/HVACSizingControl @@ -1030,10 +1031,10 @@ [HeatingSystem] - + Expected 0 or 1 element(s) for xpath: AttachedToZone Expected 1 element(s) for xpath: ../../HVACControl - Expected 1 element(s) for xpath: HeatingSystemType[ElectricResistance | Furnace | WallFurnace | FloorFurnace | Boiler | Stove | SpaceHeater | Fireplace] + Expected 1 element(s) for xpath: HeatingSystemType[ElectricResistance | Furnace | WallFurnace | FloorFurnace | Boiler | Stove | SpaceHeater | Fireplace] Expected 0 or 1 element(s) for xpath: extension/HeatingAutosizingFactor HeatingAutosizingFactor should be greater than 0.0 Expected 0 or 1 element(s) for xpath: extension/HeatingAutosizingLimit @@ -1144,10 +1145,17 @@ - [HeatingSystemType=SharedBoiler] - + [HeatingSystemType=SharedBoilerWholeBuilding] + + + + + + + [HeatingSystemType=SharedBoilerSingleUnit] + Expected 1 element(s) for xpath: ../../../../BuildingSummary/BuildingConstruction[ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]] - Expected 1 or more element(s) for xpath: ../../HVACDistribution/DistributionSystemType/HydronicDistribution/HydronicDistributionType[text()="radiator" or text()="baseboard" or text()="radiant floor" or text()="radiant ceiling" or text()="water loop"] | ../../HVACDistribution/DistributionSystemType/AirDistribution/AirDistributionType[text()="fan coil"] + Expected 1 or more element(s) for xpath: ../../HVACDistribution/DistributionSystemType/HydronicDistribution/HydronicDistributionType[text()="radiator" or text()="baseboard" or text()="radiant floor" or text()="radiant ceiling" or text()="water loop"] | ../../HVACDistribution/DistributionSystemType/AirDistribution/AirDistributionType[text()="fan coil"] Expected 0 or 1 element(s) for xpath: UnitLocation Expected UnitLocation to be 'conditioned space' or 'basement - unconditioned' or 'basement - conditioned' or 'attic - unvented' or 'attic - vented' or 'garage' or 'crawlspace - unvented' or 'crawlspace - vented' or 'crawlspace - conditioned' or 'other exterior' or 'other housing unit' or 'other heated space' or 'other multifamily buffer space' or 'other non-freezing space' or 'roof deck' or 'unconditioned space' or 'manufactured home belly' Expected 1 element(s) for xpath: DistributionSystem @@ -1167,7 +1175,7 @@ - [HeatingSystemType=SharedBoilerWthFanCoil] + [HeatingSystemType=SharedBoilerSingleUnitWithFanCoil] Expected 0 or 1 element(s) for xpath: ElectricAuxiliaryEnergy | extension/FanCoilWatts Expected extension/FanCoilWatts to be greater than or equal to 0 @@ -1175,7 +1183,7 @@ - [HeatingSystemType=SharedBoilerWithWLHP] + [HeatingSystemType=SharedBoilerSingleUnitWithWLHP] Expected 0 or 1 element(s) for xpath: ../HeatPump[HeatPumpType="water-loop-to-air"]/HeatingCapacity Expected 1 element(s) for xpath: ../HeatPump[HeatPumpType="water-loop-to-air"]/AnnualHeatingEfficiency[Units="COP"]/Value @@ -1837,7 +1845,7 @@ [HVACDistribution] - + Expected 1 element(s) for xpath: DistributionSystemType[AirDistribution | HydronicDistribution | Other[text()="DSE"]] diff --git a/HPXMLtoOpenStudio/resources/hvac.rb b/HPXMLtoOpenStudio/resources/hvac.rb index 6775d0a7be..a85848e65e 100644 --- a/HPXMLtoOpenStudio/resources/hvac.rb +++ b/HPXMLtoOpenStudio/resources/hvac.rb @@ -5221,13 +5221,176 @@ def self.apply_advanced_defrost(model, htg_coil, air_loop_unitary, conditioned_s end # TODO + def self.apply_shared_systems(runner, model, hpxml, hpxml_osm_map, shared_systems_map) + hvac_unavailable_periods = { htg: Schedule.get_unavailable_periods(runner, SchedulesFile::Columns[:SpaceHeating].name, hpxml.header.unavailable_periods), + clg: Schedule.get_unavailable_periods(runner, SchedulesFile::Columns[:SpaceCooling].name, hpxml.header.unavailable_periods) } + + # Create map of shared systems => (Map of hpxml_bldg => conditioned zone) + shared_systems_to_zones_map = {} + shared_systems_map.values.each do |hvac_systems| + shared_systems = hvac_systems.select { |h| h.sameas_id.nil? } + next if shared_systems.empty? + + shared_systems_to_zones_map[shared_systems] = {} + + # Populate zones + shared_system_ids = shared_systems.map { |h| h.id } + shared_systems_map.each do |hpxml_bldg, hvac_systems2| + next unless hvac_systems2.select { |h| !h.sameas_id.nil? && shared_system_ids.include?(h.sameas_id) } + + unit_model = hpxml_osm_map[hpxml_bldg] + cond_zone_name = unit_model.getThermalZones.find { |z| z.additionalProperties.getFeatureAsString('ObjectType').to_s == HPXML::LocationConditionedSpace }.name.to_s + cond_zone = model.getThermalZones.find { |z| z.name.to_s == cond_zone_name } + shared_systems_to_zones_map[shared_systems][hpxml_bldg] = cond_zone + end + end + + # Apply to model + shared_systems_to_zones_map.each do |shared_systems, cond_zones_map| + shared_boilers = shared_systems.select { |h| h.is_a?(HPXML::HeatingSystem) && h.heating_system_type == HPXML::HVACTypeBoiler } + if not shared_boilers.empty? + apply_shared_boiler(model, hpxml, shared_boilers, cond_zones_map, hvac_unavailable_periods) + else + fail 'Unexpected shared systems.' + end + end + end + + # FIXME + def self.apply_shared_boiler(model, hpxml, hpxml_boilers, control_zones_map, hvac_unavailable_periods) + obj_name = Constants::ObjectTypeBoiler + + # Get distribution system + distribution_system = hpxml_boilers[0].distribution_system + check_distribution_system(distribution_system, HPXML::HVACTypeBoiler) + supply_temp = distribution_system.hydronic_supply_temp # deg-F + return_temp = distribution_system.hydronic_return_temp # deg-F + + # Plant Loop + plant_loop = OpenStudio::Model::PlantLoop.new(model) + plant_loop.setName(obj_name + ' hydronic heat loop') + plant_loop.setFluidType('Water') + plant_loop.setMaximumLoopTemperature(100) + plant_loop.setMinimumLoopTemperature(0) + plant_loop.setMinimumLoopFlowRate(0) + plant_loop.autocalculatePlantLoopVolume() + # Set plant loop distribution scheme + if hpxml.header.shared_boiler_operation == HPXML::SharedBoilerOperationSequenced + plant_loop.setLoadDistributionScheme('SequentialLoad') + elsif hpxml.header.shared_boiler_operation == HPXML::SharedBoilerOperationSimultaneous + plant_loop.setLoadDistributionScheme('UniformLoad') + end + + loop_sizing = plant_loop.sizingPlant + loop_sizing.setLoopType('Heating') + loop_sizing.setDesignLoopExitTemperature(UnitConversions.convert(supply_temp, 'F', 'C')) + loop_sizing.setLoopDesignTemperatureDifference(UnitConversions.convert(supply_temp - return_temp, 'deltaF', 'deltaC')) + + # Pump + pump_w = 1000.0 # FIXME + pump = Model.add_pump_variable_speed( + model, + name: "#{obj_name} hydronic pump", + rated_power: pump_w + ) + pump.addToNode(plant_loop.supplyInletNode) + + # Hot Water Boilers + total_heating_capacity = 0 + hpxml_boilers.each do |heating_system| + boiler = OpenStudio::Model::BoilerHotWater.new(model) + boiler.setName(obj_name) + boiler.setFuelType(EPlus.fuel_type(heating_system.heating_system_fuel)) + boiler.setNominalThermalEfficiency(heating_system.heating_efficiency_afue) + boiler.setEfficiencyCurveTemperatureEvaluationVariable('LeavingBoiler') + boiler_eff_curve = Model.add_curve_bicubic( + model, + name: 'NonCondensingBoilerEff', + coeff: [1.111720116, 0.078614078, -0.400425756, 0.0, -0.000156783, 0.009384599, 0.234257955, 1.32927e-06, -0.004446701, -1.22498e-05], + min_x: 0.1, max_x: 1.0, min_y: 20.0, max_y: 80.0 + ) + boiler.setNormalizedBoilerEfficiencyCurve(boiler_eff_curve) + boiler.setMinimumPartLoadRatio(0.0) + boiler.setMaximumPartLoadRatio(1.0) + boiler.setBoilerFlowMode('LeavingSetpointModulated') + boiler.setOptimumPartLoadRatio(1.0) + boiler.setWaterOutletUpperTemperatureLimit(99.9) + boiler.setOnCycleParasiticElectricLoad(0) + boiler.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W')) + boiler.setOffCycleParasiticFuelLoad(UnitConversions.convert(heating_system.pilot_light_btuh.to_f, 'Btu/hr', 'W')) + plant_loop.addSupplyBranchForComponent(boiler) + boiler.additionalProperties.setFeature('HPXML_ID', heating_system.id) # Used by reporting measure + + total_heating_capacity += heating_system.heating_capacity + end + + supply_setpoint = Model.add_schedule_constant( + model, + name: "#{obj_name} hydronic heat supply setpoint", + value: UnitConversions.convert(supply_temp, 'F', 'C'), + limits: EPlus::ScheduleTypeLimitsTemperature + ) + + setpoint_manager_scheduled = OpenStudio::Model::SetpointManagerScheduled.new(model, supply_setpoint) + setpoint_manager_scheduled.setName(obj_name + ' hydronic heat loop setpoint manager') + setpoint_manager_scheduled.setControlVariable('Temperature') + setpoint_manager_scheduled.addToNode(plant_loop.supplyOutletNode) + + pipe_supply_bypass = OpenStudio::Model::PipeAdiabatic.new(model) + plant_loop.addSupplyBranchForComponent(pipe_supply_bypass) + pipe_supply_outlet = OpenStudio::Model::PipeAdiabatic.new(model) + pipe_supply_outlet.addToNode(plant_loop.supplyOutletNode) + pipe_demand_bypass = OpenStudio::Model::PipeAdiabatic.new(model) + plant_loop.addDemandBranchForComponent(pipe_demand_bypass) + pipe_demand_inlet = OpenStudio::Model::PipeAdiabatic.new(model) + pipe_demand_inlet.addToNode(plant_loop.demandInletNode) + pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model) + pipe_demand_outlet.addToNode(plant_loop.demandOutletNode) + + # FIXME: Doesn't currently respond to Heating/Cooling seasons, if defined + # FIXME: Cannot currently be mixed with in-unit HVAC systems that serve a fraction of the load + hvac_sequential_load_fracs = { htg: [1], clg: [1] } + + if distribution_system.distribution_system_type == HPXML::HVACDistributionTypeHydronic + total_heating_design_load = control_zones_map.keys.map { |hpxml_bldg| hpxml_bldg.hvac_plant.hdl_total }.sum + control_zones_map.each do |hpxml_bldg, control_zone| + # Apportion total boiler heating capacity to each zone based on the HPXML Building's heating design load + zone_heating_capacity = hpxml_bldg.hvac_plant.hdl_total / total_heating_design_load * total_heating_capacity + + bb_ua = UnitConversions.convert(zone_heating_capacity, 'Btu/hr', 'W') / UnitConversions.convert(UnitConversions.convert(loop_sizing.designLoopExitTemperature, 'C', 'F') - 10.0 - 95.0, 'deltaF', 'deltaC') * 3.0 # W/K + max_water_flow = UnitConversions.convert(zone_heating_capacity, 'Btu/hr', 'W') / loop_sizing.loopDesignTemperatureDifference / 4.186 / 998.2 / 1000.0 * 2.0 # m^3/s + + # Heating Coil + htg_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model) + htg_coil.setName(obj_name + ' htg coil') + htg_coil.setConvergenceTolerance(0.001) + htg_coil.setHeatingDesignCapacity(UnitConversions.convert(zone_heating_capacity, 'Btu/hr', 'W')) + htg_coil.setUFactorTimesAreaValue(bb_ua) + htg_coil.setMaximumWaterFlowRate(max_water_flow) + htg_coil.setHeatingDesignCapacityMethod('HeatingDesignCapacity') + plant_loop.addDemandBranchForComponent(htg_coil) + + # Baseboard + zone_hvac = OpenStudio::Model::ZoneHVACBaseboardConvectiveWater.new(model, model.alwaysOnDiscreteSchedule, htg_coil) + zone_hvac.setName(obj_name + ' baseboard') + zone_hvac.addToThermalZone(control_zone) + + set_sequential_load_fractions(model, control_zone, zone_hvac, hvac_sequential_load_fracs, hvac_unavailable_periods) + end + end + end + + # Converts shared systems to equivalent in-unit systems when modeling individual dwelling units (or, + # when modeling a whole SFA/MF building, if OS-HPXML does not yet support explicitly modeling the + # shared system we fall back to these conversions). # # @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit + # @param hpxml_header [HPXML::Header] HPXML Header object (one per HPXML file) # @return [nil] - def self.apply_shared_systems(hpxml_bldg) - applied_clg = apply_shared_cooling_systems(hpxml_bldg) - applied_htg = apply_shared_heating_systems(hpxml_bldg) - return unless (applied_clg || applied_htg) + def self.convert_shared_systems_to_in_unit_systems(hpxml_bldg, hpxml_header) + converted_clg = convert_shared_cooling_systems_to_in_unit_systems(hpxml_bldg) + converted_htg = convert_shared_heating_systems_to_in_unit_systems(hpxml_bldg, hpxml_header) + return unless (converted_clg || converted_htg) # Remove WLHP if not serving heating nor cooling hpxml_bldg.heat_pumps.each do |hp| @@ -5256,8 +5419,8 @@ def self.apply_shared_systems(hpxml_bldg) # TODO # # @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit - # @return [TODO] TODO - def self.apply_shared_cooling_systems(hpxml_bldg) + # @return [Boolean] Whether a shared cooling system was converted to an in-unit system + def self.convert_shared_cooling_systems_to_in_unit_systems(hpxml_bldg) applied = false hpxml_bldg.cooling_systems.each do |cooling_system| next unless cooling_system.is_shared_system @@ -5381,10 +5544,12 @@ def self.apply_shared_cooling_systems(hpxml_bldg) # TODO # # @param hpxml_bldg [HPXML::Building] HPXML Building object representing an individual dwelling unit - # @return [TODO] TODO - def self.apply_shared_heating_systems(hpxml_bldg) + # @param hpxml_header [HPXML::Header] HPXML Header object (one per HPXML file) + # @return [Boolean] Whether a shared heating system was converted to an in-unit system + def self.convert_shared_heating_systems_to_in_unit_systems(hpxml_bldg, hpxml_header) applied = false hpxml_bldg.heating_systems.each do |heating_system| + next if hpxml_header.whole_sfa_or_mf_building_sim # Central boilers are explicitly modeled for whole SFA/MF buildings next unless heating_system.is_shared_system applied = true diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb index 15cb8bb6d8..82c301a465 100644 --- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb +++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb @@ -139,6 +139,14 @@ def self.is_system_to_skip(hvac_heating, hvac_cooling, zone) return true end + # Don't size shared systems serving multiple dwelling units for whole MF building models + if !hvac_heating.nil? && hvac_heating.is_shared_system_serving_multiple_dwelling_units + return true + end + if !hvac_cooling.nil? && hvac_cooling.is_shared_system_serving_multiple_dwelling_units + return true + end + return false end diff --git a/HPXMLtoOpenStudio/resources/model.rb b/HPXMLtoOpenStudio/resources/model.rb index 55983fbafb..6ef7a03c3c 100644 --- a/HPXMLtoOpenStudio/resources/model.rb +++ b/HPXMLtoOpenStudio/resources/model.rb @@ -859,6 +859,8 @@ def self.reset(model, runner) # @return [nil] def self.merge_unit_models(model, hpxml_osm_map) # Map of OpenStudio IDD objects => OSM class names + # Note: ZoneCapacitanceMultiplierResearchSpecial is not actually unique, but we don't assign it to + # individual thermal zones, so we'll treat it as unique here. unique_object_map = { 'OS:ConvergenceLimits' => 'ConvergenceLimits', 'OS:Foundation:Kiva:Settings' => 'FoundationKivaSettings', 'OS:OutputControl:Files' => 'OutputControlFiles', @@ -875,7 +877,8 @@ def self.merge_unit_models(model, hpxml_osm_map) 'OS:Site:WaterMainsTemperature' => 'SiteWaterMainsTemperature', 'OS:SurfaceConvectionAlgorithm:Inside' => 'InsideSurfaceConvectionAlgorithm', 'OS:SurfaceConvectionAlgorithm:Outside' => 'OutsideSurfaceConvectionAlgorithm', - 'OS:Timestep' => 'Timestep' } + 'OS:Timestep' => 'Timestep', + 'OS:ZoneCapacitanceMultiplier:ResearchSpecial' => 'ZoneCapacitanceMultiplierResearchSpecial' } # Handle unique objects first: Grab one from the first model we find the # object on (may not be the first unit). unit_model_objects = [] diff --git a/ReportSimulationOutput/measure.rb b/ReportSimulationOutput/measure.rb index c342ba06c0..024439215b 100644 --- a/ReportSimulationOutput/measure.rb +++ b/ReportSimulationOutput/measure.rb @@ -902,7 +902,7 @@ def get_outputs(runner, args) @hpxml_bldgs.each do |hpxml_bldg| # Apply Heating/Cooling DSEs (hpxml_bldg.heating_systems + hpxml_bldg.heat_pumps).each do |htg_system| - next unless (htg_system.is_a?(HPXML::HeatingSystem) && htg_system.is_heat_pump_backup_system) || htg_system.fraction_heat_load_served > 0 + next unless (htg_system.is_a?(HPXML::HeatingSystem) && htg_system.is_heat_pump_backup_system) || htg_system.fraction_heat_load_served.to_f > 0 next if htg_system.distribution_system_idref.nil? next unless htg_system.distribution_system.distribution_system_type == HPXML::HVACDistributionTypeDSE next if htg_system.distribution_system.annual_heating_dse.nil? @@ -919,7 +919,7 @@ def get_outputs(runner, args) end end (hpxml_bldg.cooling_systems + hpxml_bldg.heat_pumps).each do |clg_system| - next unless clg_system.fraction_cool_load_served > 0 + next unless clg_system.fraction_cool_load_served.to_f > 0 next if clg_system.distribution_system_idref.nil? next unless clg_system.distribution_system.distribution_system_type == HPXML::HVACDistributionTypeDSE next if clg_system.distribution_system.annual_cooling_dse.nil? diff --git a/ReportSimulationOutput/measure.xml b/ReportSimulationOutput/measure.xml index 92e37b1986..1cba34d771 100644 --- a/ReportSimulationOutput/measure.xml +++ b/ReportSimulationOutput/measure.xml @@ -3,8 +3,8 @@ 3.1 report_simulation_output df9d170c-c21a-4130-866d-0d46b06073fd - 443dae63-bc28-4988-8cb0-5fc10c452c68 - 2024-10-13T19:48:30Z + 74cc74a0-3c16-4161-93a5-6d1272435c55 + 2024-11-26T18:31:46Z 9BF1E6AC ReportSimulationOutput HPXML Simulation Output Report @@ -1929,7 +1929,7 @@ measure.rb rb script - 45BFC7E3 + CE5011EE test_report_sim_output.rb diff --git a/ReportUtilityBills/measure.rb b/ReportUtilityBills/measure.rb index e2819c9420..68a68f6943 100644 --- a/ReportUtilityBills/measure.rb +++ b/ReportUtilityBills/measure.rb @@ -110,7 +110,7 @@ def check_for_return_type_warnings() # Require not DSE @hpxml_buildings.each do |hpxml_bldg| (hpxml_bldg.heating_systems + hpxml_bldg.heat_pumps).each do |htg_system| - next unless (htg_system.is_a?(HPXML::HeatingSystem) && htg_system.is_heat_pump_backup_system) || htg_system.fraction_heat_load_served > 0 + next unless (htg_system.is_a?(HPXML::HeatingSystem) && htg_system.is_heat_pump_backup_system) || htg_system.fraction_heat_load_served.to_f > 0 next if htg_system.distribution_system_idref.nil? next unless htg_system.distribution_system.distribution_system_type == HPXML::HVACDistributionTypeDSE next if htg_system.distribution_system.annual_heating_dse.nil? @@ -119,7 +119,7 @@ def check_for_return_type_warnings() warnings << 'DSE is not currently supported when calculating utility bills.' end (hpxml_bldg.cooling_systems + hpxml_bldg.heat_pumps).each do |clg_system| - next unless clg_system.fraction_cool_load_served > 0 + next unless clg_system.fraction_cool_load_served.to_f > 0 next if clg_system.distribution_system_idref.nil? next unless clg_system.distribution_system.distribution_system_type == HPXML::HVACDistributionTypeDSE next if clg_system.distribution_system.annual_cooling_dse.nil? @@ -199,7 +199,7 @@ def energyPlusOutputRequests(runner, user_arguments) FT::Coal => HPXML::FuelTypeCoal } # Check for presence of fuels once - has_fuel = hpxml.has_fuels(hpxml.to_doc) + has_fuel = hpxml.has_fuels() has_fuel[HPXML::FuelTypeElectricity] = true # Has production diff --git a/ReportUtilityBills/measure.xml b/ReportUtilityBills/measure.xml index 711baaf436..3400670f60 100644 --- a/ReportUtilityBills/measure.xml +++ b/ReportUtilityBills/measure.xml @@ -3,8 +3,8 @@ 3.1 report_utility_bills ca88a425-e59a-4bc4-af51-c7e7d1e960fe - 52e0de17-4854-4abc-9fa0-b754312c2eb2 - 2024-11-19T01:11:13Z + cb110d70-a630-47c6-85be-56fd13ce3603 + 2024-11-26T18:31:47Z 15BF4E57 ReportUtilityBills Utility Bills Report @@ -180,7 +180,7 @@ measure.rb rb script - 4D23174A + 4D969F72 detailed_rates/README.md @@ -360,7 +360,7 @@ test_report_utility_bills.rb rb test - 1D59A593 + 04EBD8BD diff --git a/ReportUtilityBills/tests/test_report_utility_bills.rb b/ReportUtilityBills/tests/test_report_utility_bills.rb index b95a848dd5..80e90e10b0 100644 --- a/ReportUtilityBills/tests/test_report_utility_bills.rb +++ b/ReportUtilityBills/tests/test_report_utility_bills.rb @@ -79,7 +79,7 @@ def setup fuel_oil_marginal_rate: 3.495346153846154) # Check for presence of fuels once - has_fuel = @hpxml_bldg.has_fuels(@hpxml.to_doc) + has_fuel = @hpxml_bldg.has_fuels() Defaults.apply_header(@hpxml_header, @hpxml_bldg, nil) Defaults.apply_utility_bill_scenarios(nil, @hpxml_header, @hpxml_bldg, has_fuel) From 7c1759bdbddc7bc3579e41b36d4f29698a9fb6bd Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Tue, 26 Nov 2024 11:47:22 -0700 Subject: [PATCH 2/5] Bugfix, cleanup. --- HPXMLtoOpenStudio/measure.xml | 6 +++--- HPXMLtoOpenStudio/resources/hpxml.rb | 26 +++++++++++++------------- ReportUtilityBills/measure.rb | 1 - ReportUtilityBills/measure.xml | 6 +++--- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml index 1cdbbc6658..6e361d5e58 100644 --- a/HPXMLtoOpenStudio/measure.xml +++ b/HPXMLtoOpenStudio/measure.xml @@ -3,8 +3,8 @@ 3.1 hpxm_lto_openstudio b1543b30-9465-45ff-ba04-1d1f85e763bc - 05d1c691-8e2f-4b24-ac72-37ed91ce927f - 2024-11-26T18:31:43Z + 292ac47f-8279-4f3c-bf8c-1381bebc8724 + 2024-11-26T18:46:54Z D8922A73 HPXMLtoOpenStudio HPXML to OpenStudio Translator @@ -357,7 +357,7 @@ hpxml.rb rb resource - 68D7F8FA + 490E065F hpxml_schema/HPXML.xsd diff --git a/HPXMLtoOpenStudio/resources/hpxml.rb b/HPXMLtoOpenStudio/resources/hpxml.rb index cf27dd46eb..b555f3c5e1 100644 --- a/HPXMLtoOpenStudio/resources/hpxml.rb +++ b/HPXMLtoOpenStudio/resources/hpxml.rb @@ -665,30 +665,31 @@ def set_unique_hpxml_ids(hpxml_doc, last_building_only = false) # @param building_id [String] If provided, only search the single HPXML Building with the given ID # @return [Hash] Map of HPXML::FuelTypeXXX => boolean def has_fuels(building_id = nil) - has_fuels = {} + has_fuel = {} + has_fuel[HPXML::FuelTypeElectricity] = true HPXML::fossil_fuels.each do |fuel| - has_fuels[fuel] = false + has_fuel[fuel] = false buildings.each do |hpxml_bldg| - next if (not building_id.nil? && hpxml_bldg.building_id != building_id) + next if (not building_id.nil?) && (hpxml_bldg.building_id != building_id) # Check HVAC systems hpxml_bldg.hvac_systems.each do |hvac_system| if hvac_system.respond_to?(:heating_system_fuel) && hvac_system.heating_system_fuel == fuel - has_fuels[fuel] = true + has_fuel[fuel] = true end if hvac_system.respond_to?(:cooling_system_fuel) && hvac_system.cooling_system_fuel == fuel - has_fuels[fuel] = true + has_fuel[fuel] = true end if hvac_system.respond_to?(:heat_pump_fuel) && hvac_system.heat_pump_fuel == fuel - has_fuels[fuel] = true + has_fuel[fuel] = true end if hvac_system.respond_to?(:backup_heating_fuel) && hvac_system.backup_heating_fuel == fuel - has_fuels[fuel] = true + has_fuel[fuel] = true end if hvac_system.respond_to?(:integrated_heating_system_fuel) && hvac_system.integrated_heating_system_fuel == fuel - has_fuels[fuel] = true + has_fuel[fuel] = true end end @@ -699,7 +700,7 @@ def has_fuels(building_id = nil) hpxml_bldg.cooking_ranges + hpxml_bldg.fuel_loads).each do |appliance| if appliance.fuel_type == fuel - has_fuels[fuel] = true + has_fuel[fuel] = true end end @@ -707,16 +708,16 @@ def has_fuels(building_id = nil) if fuel == HPXML::FuelTypeNaturalGas (hpxml_bldg.pools + hpxml_bldg.permanent_spas).each do |pool_or_spa| if pool_or_spa.heater_type == HPXML::HeaterTypeGas - has_fuels[fuel] = true + has_fuel[fuel] = true end end end - break if has_fuels[fuel] + break if has_fuel[fuel] end end - return has_fuels + return has_fuel end # Delete any shared HVAC systems that are actually modeled as systems serving multiple dwelling units. @@ -1767,7 +1768,6 @@ def has_fuel_access # # @return [Hash] Map of HPXML::FuelTypeXXX => boolean def has_fuels() - # Returns a hash with whether each fuel exists in the HPXML Building return @parent_object.has_fuels(@building_id) end diff --git a/ReportUtilityBills/measure.rb b/ReportUtilityBills/measure.rb index 68a68f6943..ef094cbae8 100644 --- a/ReportUtilityBills/measure.rb +++ b/ReportUtilityBills/measure.rb @@ -200,7 +200,6 @@ def energyPlusOutputRequests(runner, user_arguments) # Check for presence of fuels once has_fuel = hpxml.has_fuels() - has_fuel[HPXML::FuelTypeElectricity] = true # Has production has_pv = @hpxml_buildings.count { |hpxml_bldg| !hpxml_bldg.pv_systems.empty? } > 0 diff --git a/ReportUtilityBills/measure.xml b/ReportUtilityBills/measure.xml index 3400670f60..32666e4942 100644 --- a/ReportUtilityBills/measure.xml +++ b/ReportUtilityBills/measure.xml @@ -3,8 +3,8 @@ 3.1 report_utility_bills ca88a425-e59a-4bc4-af51-c7e7d1e960fe - cb110d70-a630-47c6-85be-56fd13ce3603 - 2024-11-26T18:31:47Z + b93dbb48-5955-47f6-a379-b56ac2c3b1d2 + 2024-11-26T18:46:57Z 15BF4E57 ReportUtilityBills Utility Bills Report @@ -180,7 +180,7 @@ measure.rb rb script - 4D969F72 + 209AE1AD detailed_rates/README.md From af6bcbf3efbd06a28a655d2f19e5d2cc16c212fc Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Wed, 27 Nov 2024 12:29:45 -0700 Subject: [PATCH 3/5] Add a couple sample files. --- tasks.rb | 66 +- workflow/hpxml_inputs.json | 6 + ...hole-building-shared-boilers-sequenced.xml | 2724 +++++++++++++++++ ...e-building-shared-boilers-simultaneous.xml | 2724 +++++++++++++++++ 4 files changed, 5505 insertions(+), 15 deletions(-) create mode 100644 workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml create mode 100644 workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml diff --git a/tasks.rb b/tasks.rb index e8b436045f..e7527d6ae9 100644 --- a/tasks.rb +++ b/tasks.rb @@ -55,24 +55,19 @@ def create_hpxmls model = OpenStudio::Model::Model.new runner = OpenStudio::Measure::OSRunner.new(OpenStudio::WorkflowJSON.new) - num_apply_measures = 1 - if hpxml_path.include?('whole-building.xml') - num_apply_measures = 6 - elsif hpxml_path.include?('whole-building-common-spaces.xml') - num_apply_measures = 8 + num_mf_units = 1 + if hpxml_path.include? 'whole-building-common-spaces' + num_mf_units = 8 + elsif hpxml_path.include? 'whole-building' + num_mf_units = 6 end - for i in 1..num_apply_measures + for i in 1..num_mf_units build_residential_hpxml = measures['BuildResidentialHPXML'][0] build_residential_hpxml['existing_hpxml_path'] = hpxml_path if i > 1 - if hpxml_path.include?('base-bldgtype-mf-whole-building.xml') - suffix = "_#{i}" if i > 1 - build_residential_hpxml['schedules_filepaths'] = "../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic#{suffix}.csv" - build_residential_hpxml['geometry_foundation_type'] = (i <= 2 ? 'UnconditionedBasement' : 'AboveApartment') - build_residential_hpxml['geometry_attic_type'] = (i >= 5 ? 'VentedAttic' : 'BelowApartment') - build_residential_hpxml['geometry_unit_height_above_grade'] = { 1 => 0.0, 2 => 0.0, 3 => 10.0, 4 => 10.0, 5 => 20.0, 6 => 20.0 }[i] - elsif hpxml_path.include?('base-bldgtype-mf-whole-building-common-spaces.xml') - suffix = "_#{i}" if i > 1 + suffix = "_#{i}" if i > 1 + + if hpxml_path.include?('whole-building-common-spaces') build_residential_hpxml['schedules_filepaths'] = (i >= 7 ? nil : "../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic#{suffix}.csv") build_residential_hpxml['geometry_foundation_type'] = (i <= 2 ? 'UnconditionedBasement' : 'AboveApartment') build_residential_hpxml['geometry_attic_type'] = (i >= 7 ? 'VentedAttic' : 'BelowApartment') @@ -83,6 +78,11 @@ def create_hpxmls # Partially conditioned basement + one unconditioned hallway each floor + unconditioned attic build_residential_hpxml['heating_system_type'] = { 1 => 'ElectricResistance', 2 => 'none', 3 => 'none', 4 => 'ElectricResistance', 5 => 'none', 6 => 'ElectricResistance', 7 => 'none', 8 => 'none' }[i] build_residential_hpxml['cooling_system_type'] = { 1 => 'room air conditioner', 2 => 'none', 3 => 'none', 4 => 'room air conditioner', 5 => 'none', 6 => 'room air conditioner', 7 => 'none', 8 => 'none' }[i] + elsif hpxml_path.include?('whole-building') + build_residential_hpxml['schedules_filepaths'] = "../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic#{suffix}.csv" + build_residential_hpxml['geometry_foundation_type'] = (i <= 2 ? 'UnconditionedBasement' : 'AboveApartment') + build_residential_hpxml['geometry_attic_type'] = (i >= 5 ? 'VentedAttic' : 'BelowApartment') + build_residential_hpxml['geometry_unit_height_above_grade'] = { 1 => 0.0, 2 => 0.0, 3 => 10.0, 4 => 10.0, 5 => 20.0, 6 => 20.0 }[i] end # Re-generate stochastic schedule CSV? @@ -1598,7 +1598,7 @@ def apply_hpxml_modification_sample_files(hpxml_path, hpxml) hpxml_bldg.heat_pumps[0].number_of_units_served = 6 hpxml_bldg.heat_pumps[0].pump_watts_per_ton = 0.0 end - if !hpxml_file.include? 'eae' + if !hpxml_file.include?('eae') && !hpxml_file.include?('whole-building') if hpxml_file.include? 'shared-boiler' hpxml_bldg.heating_systems[0].shared_loop_watts = 600 end @@ -2627,6 +2627,42 @@ def apply_hpxml_modification_sample_files(hpxml_path, hpxml) plug_load.delete end end + elsif ['base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml', + 'base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml'].include? hpxml_file + if hpxml_file.include? 'sequenced' + hpxml.header.shared_boiler_operation = HPXML::SharedBoilerOperationSequenced + elsif hpxml_file.include? 'simultaneous' + hpxml.header.shared_boiler_operation = HPXML::SharedBoilerOperationSimultaneous + end + # Add two shared boilers to building1 + hpxml.buildings[0].heating_systems.clear + for j in 1..2 + hpxml.buildings[0].heating_systems.add(id: "HeatingSystem#{j}", + is_shared_system: true, + distribution_system_idref: 'HVACDistribution1', + heating_system_type: HPXML::HVACTypeBoiler, + heating_system_fuel: HPXML::FuelTypeNaturalGas, + heating_capacity: 30000, + heating_efficiency_afue: 0.8) + end + hpxml.buildings[0].hvac_distributions.clear + hpxml.buildings[0].hvac_distributions.add(id: 'HVACDistribution1', + distribution_system_type: HPXML::HVACDistributionTypeHydronic, + hydronic_type: HPXML::HydronicTypeBaseboard, + hydronic_supply_temp: 160, + hydronic_return_temp: 120) + # Reference the shared boilers from all other buildings + for i in 1..hpxml.buildings.size - 1 + hpxml.buildings[i].heating_systems.clear + for j in 1..2 + hpxml.buildings[i].heating_systems.add(id: "HeatingSystem#{j}_#{i}", + distribution_system_idref: "HVACDistribution1_#{i}", + sameas_id: "HeatingSystem#{j}") + end + hpxml.buildings[i].hvac_distributions.clear + hpxml.buildings[i].hvac_distributions.add(id: "HVACDistribution1_#{i}", + sameas_id: 'HVACDistribution1') + end end end diff --git a/workflow/hpxml_inputs.json b/workflow/hpxml_inputs.json index 827d299976..64dff4c977 100644 --- a/workflow/hpxml_inputs.json +++ b/workflow/hpxml_inputs.json @@ -3611,6 +3611,12 @@ "parent_hpxml": "sample_files/base-bldgtype-mf-whole-building.xml", "heating_system_heating_capacity": 24000 }, + "sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml": { + "parent_hpxml": "sample_files/base-bldgtype-mf-whole-building.xml" + }, + "sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml": { + "parent_hpxml": "sample_files/base-bldgtype-mf-whole-building.xml" + }, "sample_files/base-pv.xml": { "parent_hpxml": "sample_files/base.xml", "pv_system_present": true, diff --git a/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml new file mode 100644 index 0000000000..72f7afed8b --- /dev/null +++ b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml @@ -0,0 +1,2724 @@ + + + + HPXML + tasks.rb + 2000-01-01T00:00:00-07:00 + create + + + + true + + sequenced + + + 60 + + + + Bills + + + + + + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above + 180 + + electricity + natural gas + + + + apartment unit + 0.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + outside + basement - unconditioned + 77.1 + wood siding + 0.7 + 0.92 + + + 23.0 + + + + + basement - unconditioned + basement - unconditioned + 30.8 + 0.7 + 0.92 + + + 4.0 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + ground + basement - unconditioned + 8.0 + 800.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 8.9 + 0.0 + 8.0 + + + continuous - interior + 0.0 + + + + + + basement - unconditioned + basement - unconditioned + 8.0 + 320.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 0.0 + + + continuous - interior + 0.0 + + + + + + + + basement - unconditioned + conditioned space + floor + + + + 1200.0 + + + 22.84 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + basement - unconditioned + 1200.0 + 4.0 + 100.0 + + + + 0.0 + 0.0 + + + + + + 0.0 + 0.0 + + + + 0.0 + 0.0 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + true + + + + natural gas + 30000.0 + + AFUE + 0.8 + + + + + + true + + + + natural gas + 30000.0 + + AFUE + 0.8 + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + baseboard + 160.0 + 120.0 + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above + 180 + + electricity + natural gas + + + + apartment unit + 0.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_2.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + outside + basement - unconditioned + 77.1 + wood siding + 0.7 + 0.92 + + + 23.0 + + + + + basement - unconditioned + basement - unconditioned + 30.8 + 0.7 + 0.92 + + + 4.0 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + ground + basement - unconditioned + 8.0 + 800.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 8.9 + 0.0 + 8.0 + + + continuous - interior + 0.0 + + + + + + basement - unconditioned + basement - unconditioned + 8.0 + 320.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 0.0 + + + continuous - interior + 0.0 + + + + + + + + basement - unconditioned + conditioned space + floor + + + + 1200.0 + + + 22.84 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + basement - unconditioned + 1200.0 + 4.0 + 100.0 + + + + 0.0 + 0.0 + + + + + + 0.0 + 0.0 + + + + 0.0 + 0.0 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above and below + 180 + + electricity + natural gas + + + + apartment unit + 10.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_3.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above and below + 180 + + electricity + natural gas + + + + apartment unit + 10.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_4.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit below + 180 + + electricity + natural gas + + + + apartment unit + 20.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_5.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + true + + + + SLA + 0.003 + + + + + + + + + + + + + + + + + + + attic - vented + 1341.6 + asphalt or fiberglass shingles + 0.7 + 0.92 + 6.0 + + + 2.3 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + outside + attic - vented + gable + + + + 200.0 + wood siding + 0.7 + 0.92 + + + 4.0 + + + + + attic - vented + attic - vented + + + + 200.0 + 0.7 + 0.92 + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + attic - vented + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 39.3 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit below + 180 + + electricity + natural gas + + + + apartment unit + 20.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_6.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + true + + + + SLA + 0.003 + + + + + + + + + + + + + + + + + + + attic - vented + 1341.6 + asphalt or fiberglass shingles + 0.7 + 0.92 + 6.0 + + + 2.3 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + outside + attic - vented + gable + + + + 200.0 + wood siding + 0.7 + 0.92 + + + 4.0 + + + + + attic - vented + attic - vented + + + + 200.0 + 0.7 + 0.92 + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + attic - vented + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 39.3 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+
\ No newline at end of file diff --git a/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml new file mode 100644 index 0000000000..381bf6aeba --- /dev/null +++ b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml @@ -0,0 +1,2724 @@ + + + + HPXML + tasks.rb + 2000-01-01T00:00:00-07:00 + create + + + + true + + simultaneous + + + 60 + + + + Bills + + + + + + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above + 180 + + electricity + natural gas + + + + apartment unit + 0.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + outside + basement - unconditioned + 77.1 + wood siding + 0.7 + 0.92 + + + 23.0 + + + + + basement - unconditioned + basement - unconditioned + 30.8 + 0.7 + 0.92 + + + 4.0 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + ground + basement - unconditioned + 8.0 + 800.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 8.9 + 0.0 + 8.0 + + + continuous - interior + 0.0 + + + + + + basement - unconditioned + basement - unconditioned + 8.0 + 320.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 0.0 + + + continuous - interior + 0.0 + + + + + + + + basement - unconditioned + conditioned space + floor + + + + 1200.0 + + + 22.84 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + basement - unconditioned + 1200.0 + 4.0 + 100.0 + + + + 0.0 + 0.0 + + + + + + 0.0 + 0.0 + + + + 0.0 + 0.0 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + true + + + + natural gas + 30000.0 + + AFUE + 0.8 + + + + + + true + + + + natural gas + 30000.0 + + AFUE + 0.8 + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + baseboard + 160.0 + 120.0 + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above + 180 + + electricity + natural gas + + + + apartment unit + 0.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_2.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + outside + basement - unconditioned + 77.1 + wood siding + 0.7 + 0.92 + + + 23.0 + + + + + basement - unconditioned + basement - unconditioned + 30.8 + 0.7 + 0.92 + + + 4.0 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + ground + basement - unconditioned + 8.0 + 800.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 8.9 + 0.0 + 8.0 + + + continuous - interior + 0.0 + + + + + + basement - unconditioned + basement - unconditioned + 8.0 + 320.0 + 8.0 + 7.0 + + none + + + + + continuous - exterior + 0.0 + + + continuous - interior + 0.0 + + + + + + + + basement - unconditioned + conditioned space + floor + + + + 1200.0 + + + 22.84 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + basement - unconditioned + 1200.0 + 4.0 + 100.0 + + + + 0.0 + 0.0 + + + + + + 0.0 + 0.0 + + + + 0.0 + 0.0 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above and below + 180 + + electricity + natural gas + + + + apartment unit + 10.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_3.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit above and below + 180 + + electricity + natural gas + + + + apartment unit + 10.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_4.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + + + + + + + + + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + other housing unit + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 2.1 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit below + 180 + + electricity + natural gas + + + + apartment unit + 20.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_5.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + true + + + + SLA + 0.003 + + + + + + + + + + + + + + + + + + + attic - vented + 1341.6 + asphalt or fiberglass shingles + 0.7 + 0.92 + 6.0 + + + 2.3 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + outside + attic - vented + gable + + + + 200.0 + wood siding + 0.7 + 0.92 + + + 4.0 + + + + + attic - vented + attic - vented + + + + 200.0 + 0.7 + 0.92 + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + attic - vented + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 39.3 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+ + + + +
+ CO +
+
+ + proposed workscope + + + + + suburban + attached on one side + unit below + 180 + + electricity + natural gas + + + + apartment unit + 20.0 + 6 + 1.0 + 1.0 + 8.0 + 3 + 2 + 1200.0 + 9600.0 + + + ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic_6.csv + + + + + 2006 + 5B + + + + USA_CO_Denver.Intl.AP.725650_TMY3 + + USA_CO_Denver.Intl.AP.725650_TMY3.epw + + + + + + + + unit exterior only + + ACHnatural + 0.375 + + 9600.0 + + + + + + + + true + + + + SLA + 0.003 + + + + + + + + + + + + + + + + + + + attic - vented + 1341.6 + asphalt or fiberglass shingles + 0.7 + 0.92 + 6.0 + + + 2.3 + + + + + + + outside + conditioned space + + + + 800.0 + wood siding + 0.7 + 0.92 + + gypsum board + + + + 23.0 + + + + + other housing unit + conditioned space + + + + 320.0 + 0.7 + 0.92 + + gypsum board + + + + 4.0 + + + + + outside + attic - vented + gable + + + + 200.0 + wood siding + 0.7 + 0.92 + + + 4.0 + + + + + attic - vented + attic - vented + + + + 200.0 + 0.7 + 0.92 + + + 4.0 + + + + + + + other housing unit + conditioned space + floor + + + + 1200.0 + + + 2.1 + + + + + attic - vented + conditioned space + ceiling + + + + 1200.0 + + gypsum board + + + + 39.3 + + + + + + + 43.2 + 0 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 43.2 + 180 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + 57.6 + 270 + 0.33 + 0.45 + + + 0.7 + 0.85 + + 0.67 + + + + + + + + 20.0 + 180 + 4.4 + + + + + + + + + + + + + + + + + + + + room air conditioner + electricity + 12000.0 + 1.0 + + EER + 8.5 + + 0.73 + + + + + 68.0 + 78.0 + + + + + + + + + electricity + storage water heater + conditioned space + 40.0 + 1.0 + 18767.0 + 0.95 + 125.0 + + + + + + 50.0 + + + + 0.0 + + + + + shower head + true + + + + faucet + false + + + + + + + conditioned space + 1.21 + 380.0 + 0.12 + 1.09 + 27.0 + 6.0 + 3.2 + + + + conditioned space + 307.0 + 12 + 0.12 + 1.09 + 22.32 + 4.0 + + + + conditioned space + 650.0 + + + + conditioned space + electricity + false + + + + false + + + + + + interior + 0.4 + + + + + + + interior + 0.1 + + + + + + + interior + 0.25 + + + + + + + exterior + 0.4 + + + + + + + exterior + 0.1 + + + + + + + exterior + 0.25 + + + + + + + + + TV other + + kWh/year + 620.0 + + + + + other + + kWh/year + 2457.0 + + + 0.855 + 0.045 + + + + +
+
\ No newline at end of file From 025a7bf6cd282e8b47580e41ac71ae0519a3fc43 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Wed, 27 Nov 2024 17:00:14 -0700 Subject: [PATCH 4/5] Some more progress. --- HPXMLtoOpenStudio/measure.xml | 16 ++++---- HPXMLtoOpenStudio/resources/defaults.rb | 8 ++++ HPXMLtoOpenStudio/resources/hpxml.rb | 9 +++++ .../hpxml_schematron/EPvalidator.xml | 16 +++++++- HPXMLtoOpenStudio/resources/hvac.rb | 37 ++++++++++++------- HPXMLtoOpenStudio/resources/model.rb | 22 ++++++++++- HPXMLtoOpenStudio/resources/waterheater.rb | 12 ++---- tasks.rb | 3 +- ...hole-building-shared-boilers-sequenced.xml | 3 ++ ...e-building-shared-boilers-simultaneous.xml | 3 ++ 10 files changed, 96 insertions(+), 33 deletions(-) diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml index 28a615eb51..6f56c5af03 100644 --- a/HPXMLtoOpenStudio/measure.xml +++ b/HPXMLtoOpenStudio/measure.xml @@ -3,8 +3,8 @@ 3.1 hpxm_lto_openstudio b1543b30-9465-45ff-ba04-1d1f85e763bc - 7454fa05-feb7-4bcf-9ebd-6079a0670b17 - 2024-11-27T18:12:59Z + d4c275a9-8ec8-4ac1-8b41-c6e7acee61bb + 2024-11-27T23:57:31Z D8922A73 HPXMLtoOpenStudio HPXML to OpenStudio Translator @@ -327,7 +327,7 @@ defaults.rb rb resource - 6CBBF7DE + 9E53CA52
energyplus.rb @@ -357,7 +357,7 @@ hpxml.rb rb resource - BA88642A + D2164BF2 hpxml_schema/HPXML.xsd @@ -375,7 +375,7 @@ hpxml_schematron/EPvalidator.xml xml resource - 3F51B0F0 + 171A79BF hpxml_schematron/iso-schematron.xsd @@ -387,7 +387,7 @@ hvac.rb rb resource - 8FDEDD43 + 16573C00 hvac_sizing.rb @@ -447,7 +447,7 @@ model.rb rb resource - 8CBF7564 + 20EF0A5D output.rb @@ -627,7 +627,7 @@ waterheater.rb rb resource - 6D8EEB7D + FE4A4EF1 weather.rb diff --git a/HPXMLtoOpenStudio/resources/defaults.rb b/HPXMLtoOpenStudio/resources/defaults.rb index 15513ff2d9..ea85a4b525 100644 --- a/HPXMLtoOpenStudio/resources/defaults.rb +++ b/HPXMLtoOpenStudio/resources/defaults.rb @@ -2532,6 +2532,14 @@ def self.apply_hvac_distribution(hpxml_bldg) hvac_distribution.hydronic_return_temp = hvac_distribution.hydronic_supply_temp - default_delta_t # deg-F hvac_distribution.hydronic_return_temp_isdefaulted = true end + if hvac_distribution.hydronic_trvs.nil? + hvac_distribution.hydronic_trvs = true + hvac_distribution.hydronic_trvs_isdefaulted = true + end + if hvac_distribution.hydronic_variable_speed_pump.nil? + hvac_distribution.hydronic_variable_speed_pump = false + hvac_distribution.hydronic_variable_speed_pump_isdefaulted = true + end end # Air distribution diff --git a/HPXMLtoOpenStudio/resources/hpxml.rb b/HPXMLtoOpenStudio/resources/hpxml.rb index 9bf8b34969..0855d4246c 100644 --- a/HPXMLtoOpenStudio/resources/hpxml.rb +++ b/HPXMLtoOpenStudio/resources/hpxml.rb @@ -7829,6 +7829,8 @@ def initialize(hpxml_bldg, *args, **kwargs) :hydronic_type, # [String] DistributionSystemType/HydronicDistribution/HydronicDistributionType (HPXML::HydronicTypeXXX) :hydronic_supply_temp, # [Double] DistributionSystemType/HydronicDistribution/SupplyTemperature (F) :hydronic_return_temp, # [Double] DistributionSystemType/HydronicDistribution/ReturnTemperature (F) + :hydronic_trvs, # [Boolean] DistributionSystemType/HydronicDistribution/PumpandZoneValve/ThermostaticRadiatorValves + :hydronic_variable_speed_pump, # [Boolean] DistributionSystemType/HydronicDistribution/PumpandZoneValve/VariableSpeedPump :manualj_hot_water_piping_btuh, # [Double] DistributionSystemType/HydronicDistribution/extension/ManualJInputs/HotWaterPipingBtuh (Btu/hr) :annual_heating_dse, # [Double] DistributionSystemType/Other/AnnualHeatingDistributionSystemEfficiency (frac) :annual_cooling_dse, # [Double] DistributionSystemType/Other/AnnualCoolingDistributionSystemEfficiency (frac) @@ -7940,6 +7942,11 @@ def to_doc(building) XMLHelper.add_element(hydronic_distribution, 'HydronicDistributionType', @hydronic_type, :string) unless @hydronic_type.nil? XMLHelper.add_element(hydronic_distribution, 'SupplyTemperature', @hydronic_supply_temp, :float, @hydronic_supply_temp_isdefaulted) unless @hydronic_supply_temp.nil? XMLHelper.add_element(hydronic_distribution, 'ReturnTemperature', @hydronic_return_temp, :float, @hydronic_return_temp_isdefaulted) unless @hydronic_return_temp.nil? + if (not @hydronic_trvs.nil?) || (not @hydronic_variable_speed_pump.nil?) + pump_and_zone_valve = XMLHelper.add_element(hydronic_distribution, 'PumpandZoneValve') + XMLHelper.add_element(pump_and_zone_valve, 'ThermostaticRadiatorValves', @hydronic_trvs, :boolean, @hydronic_trvs_isdefaulted) unless @hydronic_trvs.nil? + XMLHelper.add_element(pump_and_zone_valve, 'VariableSpeedPump', @hydronic_variable_speed_pump, :boolean, @hydronic_variable_speed_pump_isdefaulted) unless @hydronic_variable_speed_pump.nil? + end if not @manualj_hot_water_piping_btuh.nil? manualj_inputs = XMLHelper.create_elements_as_needed(hydronic_distribution, ['extension', 'ManualJInputs']) XMLHelper.add_element(manualj_inputs, 'HotWaterPipingBtuh', @manualj_hot_water_piping_btuh, :float, @manualj_hot_water_piping_btuh_isdefaulted) @@ -7983,6 +7990,8 @@ def from_doc(hvac_distribution) @hydronic_type = XMLHelper.get_value(hydronic_distribution, 'HydronicDistributionType', :string) @hydronic_supply_temp = XMLHelper.get_value(hydronic_distribution, 'SupplyTemperature', :float) @hydronic_return_temp = XMLHelper.get_value(hydronic_distribution, 'ReturnTemperature', :float) + @hydronic_trvs = XMLHelper.get_value(hydronic_distribution, 'PumpandZoneValve/ThermostaticRadiatorValves', :boolean) + @hydronic_variable_speed_pump = XMLHelper.get_value(hydronic_distribution, 'PumpandZoneValve/VariableSpeedPump', :boolean) @manualj_hot_water_piping_btuh = XMLHelper.get_value(hydronic_distribution, 'extension/ManualJInputs/HotWaterPipingBtuh', :float) end if not air_distribution.nil? diff --git a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml index bf6fd48fae..64dfe8a553 100644 --- a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml +++ b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml @@ -1147,7 +1147,17 @@ [HeatingSystemType=SharedBoilerWholeBuilding] - + Expected 1 element(s) for xpath: ../../../../BuildingSummary/BuildingConstruction[ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]] + Expected 1 or more element(s) for xpath: ../../HVACDistribution/DistributionSystemType/HydronicDistribution/HydronicDistributionType[text()="baseboard"] + Expected 1 element(s) for xpath: DistributionSystem + Expected 0 or 1 element(s) for xpath: HeatingSystemType/Boiler/PilotLight + Expected 1 element(s) for xpath: HeatingSystemFuel + Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets' + Expected 1 element(s) for xpath: HeatingCapacity + Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value + Expected AnnualHeatingEfficiency[Units="AFUE"]/Value to be less than or equal to 1 + + AFUE should typically be greater than or equal to 0.5. @@ -1920,6 +1930,10 @@ Expected 1 element(s) for xpath: HydronicDistributionType Expected HydronicDistributionType to be 'radiator' or 'baseboard' or 'radiant floor' or 'radiant ceiling' or 'water loop' + Expected 0 or 1 element(s) for xpath: SupplyTemperature + Expected 0 or 1 element(s) for xpath: ReturnTemperature + Expected 0 or 1 element(s) for xpath: PumpandZoneValve/ThermostaticRadiatorValves + Expected 0 or 1 element(s) for xpath: PumpandZoneValve/VariableSpeedPump Expected 0 or 1 element(s) for xpath: extension/ManualJInputs/HotWaterPipingBtuh Expected extension/ManualJInputs/HotWaterPipingBtuh to be greater than or equal to 0 diff --git a/HPXMLtoOpenStudio/resources/hvac.rb b/HPXMLtoOpenStudio/resources/hvac.rb index 34d00e4764..611f352816 100644 --- a/HPXMLtoOpenStudio/resources/hvac.rb +++ b/HPXMLtoOpenStudio/resources/hvac.rb @@ -829,7 +829,8 @@ def self.apply_boiler(model, runner, heating_system, hvac_sequential_load_fracs, oat_low = nil oat_hwst_high = nil oat_hwst_low = nil - design_temp = 180.0 # F + supply_temp = heating_system.distribution_system.hydronic_supply_temp + return_temp = heating_system.distribution_system.hydronic_return_temp if oat_reset_enabled if oat_high.nil? || oat_low.nil? || oat_hwst_low.nil? || oat_hwst_high.nil? @@ -849,8 +850,8 @@ def self.apply_boiler(model, runner, heating_system, hvac_sequential_load_fracs, loop_sizing = plant_loop.sizingPlant loop_sizing.setLoopType('Heating') - loop_sizing.setDesignLoopExitTemperature(UnitConversions.convert(design_temp, 'F', 'C')) - loop_sizing.setLoopDesignTemperatureDifference(UnitConversions.convert(20.0, 'deltaF', 'deltaC')) + loop_sizing.setDesignLoopExitTemperature(UnitConversions.convert(supply_temp, 'F', 'C')) + loop_sizing.setLoopDesignTemperatureDifference(UnitConversions.convert(supply_temp - return_temp, 'deltaF', 'deltaC')) # Pump pump_w = heating_system.electric_auxiliary_energy / 2.08 @@ -871,7 +872,7 @@ def self.apply_boiler(model, runner, heating_system, hvac_sequential_load_fracs, boiler_RatedHWRT = UnitConversions.convert(80.0, 'F', 'C') plr_Rated = 1.0 plr_Design = 1.0 - boiler_DesignHWRT = UnitConversions.convert(design_temp - 20.0, 'F', 'C') + boiler_DesignHWRT = UnitConversions.convert(return_temp, 'F', 'C') # Efficiency curves are normalized using 80F return water temperature, at 0.254PLR condBlr_TE_Coeff = [1.058343061, 0.052650153, 0.0087272, 0.001742217, 0.00000333715, 0.000513723] boilerEff_Norm = heating_system.heating_efficiency_afue / (condBlr_TE_Coeff[0] - condBlr_TE_Coeff[1] * plr_Rated - condBlr_TE_Coeff[2] * plr_Rated**2 - condBlr_TE_Coeff[3] * boiler_RatedHWRT + condBlr_TE_Coeff[4] * boiler_RatedHWRT**2 + condBlr_TE_Coeff[5] * boiler_RatedHWRT * plr_Rated) @@ -922,7 +923,7 @@ def self.apply_boiler(model, runner, heating_system, hvac_sequential_load_fracs, supply_setpoint = Model.add_schedule_constant( model, name: "#{obj_name} hydronic heat supply setpoint", - value: UnitConversions.convert(design_temp, 'F', 'C'), + value: UnitConversions.convert(supply_temp, 'F', 'C'), limits: EPlus::ScheduleTypeLimitsTemperature ) @@ -943,11 +944,11 @@ def self.apply_boiler(model, runner, heating_system, hvac_sequential_load_fracs, pipe_demand_outlet.addToNode(plant_loop.demandOutletNode) bb_ua = UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W') / UnitConversions.convert(UnitConversions.convert(loop_sizing.designLoopExitTemperature, 'C', 'F') - 10.0 - 95.0, 'deltaF', 'deltaC') * 3.0 # W/K - max_water_flow = UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W') / UnitConversions.convert(20.0, 'deltaF', 'deltaC') / 4.186 / 998.2 / 1000.0 * 2.0 # m^3/s - fan_cfm = 400.0 * UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'ton') # CFM; assumes 400 cfm/ton + max_water_flow = UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W') / loop_sizing.loopDesignTemperatureDifference / 4.186 / 998.2 / 1000.0 * 2.0 # m^3/s if heating_system.distribution_system.air_type.to_s == HPXML::AirTypeFanCoil # Fan + fan_cfm = 400.0 * UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'ton') # CFM; assumes 400 cfm/ton fan = create_supply_fan(model, obj_name, 0.0, [fan_cfm]) # fan energy included in above pump via Electric Auxiliary Energy (EAE) # Heating Coil @@ -5285,12 +5286,22 @@ def self.apply_shared_boiler(model, hpxml, hpxml_boilers, control_zones_map, hva loop_sizing.setLoopDesignTemperatureDifference(UnitConversions.convert(supply_temp - return_temp, 'deltaF', 'deltaC')) # Pump - pump_w = 1000.0 # FIXME - pump = Model.add_pump_variable_speed( - model, - name: "#{obj_name} hydronic pump", - rated_power: pump_w - ) + # FIXME + if distribution_system.hydronic_variable_speed_pump + pump_w = 1000.0 + pump = Model.add_pump_variable_speed( + model, + name: "#{obj_name} hydronic pump", + rated_power: pump_w + ) + else + pump = Model.add_pump_constant_speed( + model, + name: "#{obj_name} hydronic pump", + rated_power: 0, + rated_flow_rate: 0 + ) + end pump.addToNode(plant_loop.supplyInletNode) # Hot Water Boilers diff --git a/HPXMLtoOpenStudio/resources/model.rb b/HPXMLtoOpenStudio/resources/model.rb index 5909b67a62..85c5a81440 100644 --- a/HPXMLtoOpenStudio/resources/model.rb +++ b/HPXMLtoOpenStudio/resources/model.rb @@ -353,6 +353,24 @@ def self.add_fan_system_model(model, name:, end_use:, power_per_flow:, max_flow_ return fan end + # Adds a PumpConstantSpeed object to the OpenStudio model. + # + # @param model [OpenStudio::Model::Model] OpenStudio Model object + # @param name [String] Name for the OpenStudio object + # @param rated_power [Double] Design power consumption (W) + # @param rated_flow_rate [Double] Design flow rate (m^3/s) + # @return [OpenStudio::Model::PumpConstantSpeed] The model object + def self.add_pump_constant_speed(model, name:, rated_power:, rated_flow_rate:) + pump = OpenStudio::Model::PumpConstantSpeed.new(model) + pump.setName(name) + pump.setMotorEfficiency(0.3) + pump.setRatedPowerConsumption(rated_power) + pump.setRatedPumpHead(90000) + pump.setRatedFlowRate(rated_flow_rate) + pump.setFractionofMotorInefficienciestoFluidStream(0.2) + pump.setPumpControlType('Intermittent') + end + # Adds a PumpVariableSpeed object to the OpenStudio model. # # @param model [OpenStudio::Model::Model] OpenStudio Model object @@ -367,8 +385,8 @@ def self.add_pump_variable_speed(model, name:, rated_power:) pump_eff = 0.75 # Overall efficiency of the pump if rated_power > 0 pump.setRatedPumpHead(20000) - flow_rate = pump_eff * rated_power / pump.ratedPumpHead - pump.setRatedFlowRate([flow_rate, 0.00001].max) + rated_flow_rate = pump_eff * rated_power / pump.ratedPumpHead + pump.setRatedFlowRate([rated_flow_rate, 0.00001].max) else pump.setRatedPumpHead(1) pump.setRatedFlowRate(0.01) diff --git a/HPXMLtoOpenStudio/resources/waterheater.rb b/HPXMLtoOpenStudio/resources/waterheater.rb index 32c094ce64..e069c8151a 100644 --- a/HPXMLtoOpenStudio/resources/waterheater.rb +++ b/HPXMLtoOpenStudio/resources/waterheater.rb @@ -706,14 +706,10 @@ def self.apply_solar_thermal(model, spaces, hpxml_bldg, plantloop_map) setpoint_manager.setName(obj_name + ' setpoint mgr') setpoint_manager.setControlVariable('Temperature') - pump = OpenStudio::Model::PumpConstantSpeed.new(model) - pump.setName(obj_name + ' pump') - pump.setRatedPumpHead(90000) - pump.setRatedPowerConsumption(pump_power) - pump.setMotorEfficiency(0.3) - pump.setFractionofMotorInefficienciestoFluidStream(0.2) - pump.setPumpControlType('Intermittent') - pump.setRatedFlowRate(UnitConversions.convert(coll_flow, 'cfm', 'm^3/s')) + pump = Model.add_pump_constant_speed(model, + name: "#{obj_name} pump", + rated_power: pump_power, + rated_flow_rate: UnitConversions.convert(coll_flow, 'cfm', 'm^3/s')) pump.addToNode(plant_loop.supplyInletNode) pump.additionalProperties.setFeature('HPXML_ID', solar_thermal_system.water_heating_system.id) # Used by reporting measure pump.additionalProperties.setFeature('ObjectType', Constants::ObjectTypeSolarHotWater) # Used by reporting measure diff --git a/tasks.rb b/tasks.rb index e7527d6ae9..ce2f7f00b0 100644 --- a/tasks.rb +++ b/tasks.rb @@ -2650,7 +2650,8 @@ def apply_hpxml_modification_sample_files(hpxml_path, hpxml) distribution_system_type: HPXML::HVACDistributionTypeHydronic, hydronic_type: HPXML::HydronicTypeBaseboard, hydronic_supply_temp: 160, - hydronic_return_temp: 120) + hydronic_return_temp: 120, + hydronic_variable_speed_pump: true) # Reference the shared boilers from all other buildings for i in 1..hpxml.buildings.size - 1 hpxml.buildings[i].heating_systems.clear diff --git a/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml index 72f7afed8b..8220df485d 100644 --- a/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml +++ b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-sequenced.xml @@ -399,6 +399,9 @@ baseboard 160.0 120.0 + + true + diff --git a/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml index 381bf6aeba..9cdc6bb1d2 100644 --- a/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml +++ b/workflow/sample_files/base-bldgtype-mf-whole-building-shared-boilers-simultaneous.xml @@ -399,6 +399,9 @@ baseboard 160.0 120.0 + + true + From f14984743766cfa9478b6a393176d2317f302da8 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Wed, 27 Nov 2024 17:44:13 -0700 Subject: [PATCH 5/5] Bugfix. --- HPXMLtoOpenStudio/resources/model.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/HPXMLtoOpenStudio/resources/model.rb b/HPXMLtoOpenStudio/resources/model.rb index 85c5a81440..3313b25093 100644 --- a/HPXMLtoOpenStudio/resources/model.rb +++ b/HPXMLtoOpenStudio/resources/model.rb @@ -369,6 +369,7 @@ def self.add_pump_constant_speed(model, name:, rated_power:, rated_flow_rate:) pump.setRatedFlowRate(rated_flow_rate) pump.setFractionofMotorInefficienciestoFluidStream(0.2) pump.setPumpControlType('Intermittent') + return pump end # Adds a PumpVariableSpeed object to the OpenStudio model.