Skip to content

Commit

Permalink
Merge pull request #1391 from NREL/geothermal_loop
Browse files Browse the repository at this point in the history
Geothermal loop & soil properties
  • Loading branch information
shorowit authored Dec 11, 2023
2 parents 64e6acc + 7347e1e commit 62b24ec
Show file tree
Hide file tree
Showing 35 changed files with 8,954 additions and 519 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -1015,3 +1015,4 @@
/ReportUtilityBills/resources/detailed_rates/*.json
!/ReportUtilityBills/resources/detailed_rates/Sample*.json
/ReportUtilityBills/tests/results_bills.csv
/HPXMLtoOpenStudio/resources/data/g_functions/g-function_library_1.0
158 changes: 157 additions & 1 deletion BuildResidentialHPXML/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,22 @@ Presence of nearby buildings, trees, obstructions for infiltration model. If not

<br/>

**Site: Soil and Moisture Type**

Type of soil and moisture. This is used to inform ground conductivity and diffusivity. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-site'>HPXML Site</a>) is used.

- **Name:** ``site_soil_and_moisture_type``
- **Type:** ``Choice``

- **Required:** ``false``

- **Choices:** `clay, dry`, `clay, mixed`, `clay, wet`, `gravel, dry`, `gravel, mixed`, `gravel, wet`, `loam, dry`, `loam, mixed`, `loam, wet`, `sand, dry`, `sand, mixed`, `sand, wet`, `silt, dry`, `silt, mixed`, `silt, wet`, `unknown, dry`, `unknown, mixed`, `unknown, wet`

<br/>

**Site: Ground Conductivity**

Conductivity of the ground soil. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-site'>HPXML Site</a>) is used.
Conductivity of the ground soil. If provided, overrides the previous site and moisture type input.

- **Name:** ``site_ground_conductivity``
- **Type:** ``Double``
Expand All @@ -210,6 +223,19 @@ Conductivity of the ground soil. If not provided, the OS-HPXML default (see <a h

<br/>

**Site: Ground Diffusivity**

Diffusivity of the ground soil. If provided, overrides the previous site and moisture type input.

- **Name:** ``site_ground_diffusivity``
- **Type:** ``Double``

- **Units:** ``ft^2/hr``

- **Required:** ``false``

<br/>

**Site: Zip Code**

Zip code of the home address.
Expand Down Expand Up @@ -2250,6 +2276,136 @@ Heat Pump crankcase heater power consumption in Watts. Applies only to air-to-ai

<br/>

**Geothermal Loop: Configuration**

Configuration of the geothermal loop. Only applies to ground-to-air heat pump type.

- **Name:** ``geothermal_loop_configuration``
- **Type:** ``Choice``

- **Required:** ``true``

- **Choices:** `none`, `vertical`

<br/>

**Geothermal Loop: Borefield Configuration**

Borefield configuration of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_borefield_configuration``
- **Type:** ``Choice``

- **Required:** ``false``

- **Choices:** `Rectangle`, `Open Rectangle`, `C`, `L`, `U`, `Lopsided U`

<br/>

**Geothermal Loop: Loop Flow**

Water flow rate through the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_loop_flow``
- **Type:** ``Double``

- **Units:** ``gpm``

- **Required:** ``false``

<br/>

**Geothermal Loop: Boreholes Count**

Number of boreholes. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_boreholes_count``
- **Type:** ``Integer``

- **Units:** ``#``

- **Required:** ``false``

<br/>

**Geothermal Loop: Boreholes Length**

Average length of each borehole (vertical). Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML autosized default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_boreholes_length``
- **Type:** ``Double``

- **Units:** ``ft``

- **Required:** ``false``

<br/>

**Geothermal Loop: Boreholes Spacing**

Distance between bores. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_boreholes_spacing``
- **Type:** ``Double``

- **Units:** ``ft``

- **Required:** ``false``

<br/>

**Geothermal Loop: Boreholes Diameter**

Diameter of bores. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_boreholes_diameter``
- **Type:** ``Double``

- **Units:** ``in``

- **Required:** ``false``

<br/>

**Geothermal Loop: Grout Type**

Grout type of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_grout_type``
- **Type:** ``Choice``

- **Required:** ``false``

- **Choices:** `standard`, `thermally enhanced`

<br/>

**Geothermal Loop: Pipe Type**

Pipe type of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_pipe_type``
- **Type:** ``Choice``

- **Required:** ``false``

- **Choices:** `standard`, `thermally enhanced`

<br/>

**Geothermal Loop: Pipe Diameter**

Pipe diameter of the geothermal loop. Only applies to ground-to-air heat pump type. If not provided, the OS-HPXML default (see <a href='https://openstudio-hpxml.readthedocs.io/en/v1.7.0/workflow_inputs.html#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.

- **Name:** ``geothermal_loop_pipe_diameter``
- **Type:** ``Choice``

- **Required:** ``false``

- **Choices:** `3/4" pipe`, `1" pipe`, `1-1/4" pipe`

<br/>

**Heating System 2: Type**

The type of the second heating system.
Expand Down
172 changes: 171 additions & 1 deletion BuildResidentialHPXML/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,30 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg.setDescription("Presence of nearby buildings, trees, obstructions for infiltration model. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-site'>HPXML Site</a>) is used.")
args << arg

site_soil_and_moisture_type_choices = OpenStudio::StringVector.new
Constants.SoilTypes.each do |soil_type|
Constants.MoistureTypes.each do |moisture_type|
site_soil_and_moisture_type_choices << "#{soil_type}, #{moisture_type}"
end
end

arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('site_soil_and_moisture_type', site_soil_and_moisture_type_choices, false)
arg.setDisplayName('Site: Soil and Moisture Type')
arg.setDescription("Type of soil and moisture. This is used to inform ground conductivity and diffusivity. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-site'>HPXML Site</a>) is used.")
args << arg

arg = OpenStudio::Measure::OSArgument.makeDoubleArgument('site_ground_conductivity', false)
arg.setDisplayName('Site: Ground Conductivity')
arg.setDescription("Conductivity of the ground soil. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-site'>HPXML Site</a>) is used.")
arg.setDescription('Conductivity of the ground soil. If provided, overrides the previous site and moisture type input.')
arg.setUnits('Btu/hr-ft-F')
args << arg

arg = OpenStudio::Measure::OSArgument.makeDoubleArgument('site_ground_diffusivity', false)
arg.setDisplayName('Site: Ground Diffusivity')
arg.setDescription('Diffusivity of the ground soil. If provided, overrides the previous site and moisture type input.')
arg.setUnits('ft^2/hr')
args << arg

arg = OpenStudio::Measure::OSArgument.makeStringArgument('site_zip_code', false)
arg.setDisplayName('Site: Zip Code')
arg.setDescription('Zip code of the home address.')
Expand Down Expand Up @@ -1359,6 +1377,85 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg.setUnits('W')
args << arg

geothermal_loop_configuration_choices = OpenStudio::StringVector.new
geothermal_loop_configuration_choices << 'none'
# geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationDiagonal
# geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationHorizontal
# geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationOther
geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationVertical

arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_configuration', geothermal_loop_configuration_choices, true)
arg.setDisplayName('Geothermal Loop: Configuration')
arg.setDescription("Configuration of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type.")
arg.setDefaultValue('none')
args << arg

geothermal_loop_borefield_configuration_choices = OpenStudio::StringVector.new
valid_bore_configs = HVACSizing.valid_bore_configs
valid_bore_configs.keys.each do |valid_bore_config|
geothermal_loop_borefield_configuration_choices << valid_bore_config
end

arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_borefield_configuration', geothermal_loop_borefield_configuration_choices, false)
arg.setDisplayName('Geothermal Loop: Borefield Configuration')
arg.setDescription("Borefield configuration of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
args << arg

arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_loop_flow', false)
arg.setDisplayName('Geothermal Loop: Loop Flow')
arg.setDescription("Water flow rate through the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML autosized default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
arg.setUnits('gpm')
args << arg

arg = OpenStudio::Measure::OSArgument::makeIntegerArgument('geothermal_loop_boreholes_count', false)
arg.setDisplayName('Geothermal Loop: Boreholes Count')
arg.setDescription("Number of boreholes. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML autosized default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
arg.setUnits('#')
args << arg

arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_length', false)
arg.setDisplayName('Geothermal Loop: Boreholes Length')
arg.setDescription("Average length of each borehole (vertical). Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML autosized default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
arg.setUnits('ft')
args << arg

arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_spacing', false)
arg.setDisplayName('Geothermal Loop: Boreholes Spacing')
arg.setDescription("Distance between bores. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
arg.setUnits('ft')
args << arg

arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_diameter', false)
arg.setDisplayName('Geothermal Loop: Boreholes Diameter')
arg.setDescription("Diameter of bores. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
arg.setUnits('in')
args << arg

geothermal_loop_grout_or_pipe_type_choices = OpenStudio::StringVector.new
geothermal_loop_grout_or_pipe_type_choices << HPXML::GeothermalLoopGroutOrPipeTypeStandard
geothermal_loop_grout_or_pipe_type_choices << HPXML::GeothermalLoopGroutOrPipeTypeThermallyEnhanced

arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_grout_type', geothermal_loop_grout_or_pipe_type_choices, false)
arg.setDisplayName('Geothermal Loop: Grout Type')
arg.setDescription("Grout type of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
args << arg

arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_pipe_type', geothermal_loop_grout_or_pipe_type_choices, false)
arg.setDisplayName('Geothermal Loop: Pipe Type')
arg.setDescription("Pipe type of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
args << arg

geothermal_loop_pipe_diameter_choices = OpenStudio::StringVector.new
geothermal_loop_pipe_diameter_choices << '3/4" pipe'
geothermal_loop_pipe_diameter_choices << '1" pipe'
geothermal_loop_pipe_diameter_choices << '1-1/4" pipe'

arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_pipe_diameter', geothermal_loop_pipe_diameter_choices, false)
arg.setDisplayName('Geothermal Loop: Pipe Diameter')
arg.setDescription("Pipe diameter of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type. If not provided, the OS-HPXML default (see <a href='#{docs_base_url}#hpxml-geothermal-loops'>HPXML Geothermal Loops</a>) is used.")
arg.setUnits('in')
args << arg

heating_system_2_type_choices = OpenStudio::StringVector.new
heating_system_2_type_choices << 'none'
heating_system_2_type_choices << HPXML::HVACTypeFurnace
Expand Down Expand Up @@ -3424,6 +3521,7 @@ def self.create(runner, model, args, epw_path, hpxml_path, existing_hpxml_path)
set_heating_systems(hpxml_bldg, args)
set_cooling_systems(hpxml_bldg, args)
set_heat_pumps(hpxml_bldg, args)
set_geothermal_loop(hpxml_bldg, args)
set_secondary_heating_systems(hpxml_bldg, args)
set_hvac_distribution(hpxml_bldg, args)
set_hvac_control(hpxml, hpxml_bldg, args, epw_file, weather)
Expand Down Expand Up @@ -4019,6 +4117,16 @@ def self.set_site(hpxml_bldg, args)
hpxml_bldg.site.ground_conductivity = args[:site_ground_conductivity].get
end

if args[:site_ground_diffusivity].is_initialized
hpxml_bldg.site.ground_diffusivity = args[:site_ground_diffusivity].get
end

if args[:site_soil_and_moisture_type].is_initialized
soil_type, moisture_type = args[:site_soil_and_moisture_type].get.split(', ')
hpxml_bldg.site.soil_type = soil_type
hpxml_bldg.site.moisture_type = moisture_type
end

if args[:site_type].is_initialized
hpxml_bldg.site.site_type = args[:site_type].get
end
Expand Down Expand Up @@ -5117,6 +5225,68 @@ def self.set_heat_pumps(hpxml_bldg, args)
primary_cooling_system: primary_cooling_system)
end

def self.set_geothermal_loop(hpxml_bldg, args)
loop_configuration = args[:geothermal_loop_configuration]

return if loop_configuration == 'none'

if args[:geothermal_loop_borefield_configuration].is_initialized
bore_config = args[:geothermal_loop_borefield_configuration].get
end

if args[:geothermal_loop_loop_flow].is_initialized
loop_flow = args[:geothermal_loop_loop_flow].get
end

if args[:geothermal_loop_boreholes_count].is_initialized
num_bore_holes = args[:geothermal_loop_boreholes_count].get
end

if args[:geothermal_loop_boreholes_length].is_initialized
bore_length = args[:geothermal_loop_boreholes_length].get
end

if args[:geothermal_loop_boreholes_spacing].is_initialized
bore_spacing = args[:geothermal_loop_boreholes_spacing].get
end

if args[:geothermal_loop_boreholes_diameter].is_initialized
bore_diameter = args[:geothermal_loop_boreholes_diameter].get
end

if args[:geothermal_loop_grout_type].is_initialized
grout_type = args[:geothermal_loop_grout_type].get
end

if args[:geothermal_loop_pipe_type].is_initialized
pipe_type = args[:geothermal_loop_pipe_type].get
end

if args[:geothermal_loop_pipe_diameter].is_initialized
pipe_diameter = args[:geothermal_loop_pipe_diameter].get
if pipe_diameter == '3/4" pipe'
pipe_diameter = 0.75
elsif pipe_diameter == '1" pipe'
pipe_diameter = 1.0
elsif pipe_diameter == '1-1/4" pipe'
pipe_diameter = 1.25
end
end

hpxml_bldg.geothermal_loops.add(id: "GeothermalLoop#{hpxml_bldg.geothermal_loops.size + 1}",
loop_configuration: loop_configuration,
loop_flow: loop_flow,
bore_config: bore_config,
num_bore_holes: num_bore_holes,
bore_length: bore_length,
bore_spacing: bore_spacing,
bore_diameter: bore_diameter,
grout_type: grout_type,
pipe_type: pipe_type,
pipe_diameter: pipe_diameter)
hpxml_bldg.heat_pumps[-1].geothermal_loop_idref = hpxml_bldg.geothermal_loops[-1].id
end

def self.set_secondary_heating_systems(hpxml_bldg, args)
heating_system_type = args[:heating_system_2_type]
heating_system_is_heatpump_backup = (args[:heat_pump_type] != 'none' && args[:heat_pump_backup_type] == HPXML::HeatPumpBackupTypeSeparate)
Expand Down
Loading

0 comments on commit 62b24ec

Please sign in to comment.