Skip to content

Commit 62b24ec

Browse files
authored
Merge pull request #1391 from NREL/geothermal_loop
Geothermal loop & soil properties
2 parents 64e6acc + 7347e1e commit 62b24ec

35 files changed

+8954
-519
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1015,3 +1015,4 @@
10151015
/ReportUtilityBills/resources/detailed_rates/*.json
10161016
!/ReportUtilityBills/resources/detailed_rates/Sample*.json
10171017
/ReportUtilityBills/tests/results_bills.csv
1018+
/HPXMLtoOpenStudio/resources/data/g_functions/g-function_library_1.0

BuildResidentialHPXML/README.md

+157-1
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,22 @@ Presence of nearby buildings, trees, obstructions for infiltration model. If not
197197

198198
<br/>
199199

200+
**Site: Soil and Moisture Type**
201+
202+
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.
203+
204+
- **Name:** ``site_soil_and_moisture_type``
205+
- **Type:** ``Choice``
206+
207+
- **Required:** ``false``
208+
209+
- **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`
210+
211+
<br/>
212+
200213
**Site: Ground Conductivity**
201214

202-
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.
215+
Conductivity of the ground soil. If provided, overrides the previous site and moisture type input.
203216

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

211224
<br/>
212225

226+
**Site: Ground Diffusivity**
227+
228+
Diffusivity of the ground soil. If provided, overrides the previous site and moisture type input.
229+
230+
- **Name:** ``site_ground_diffusivity``
231+
- **Type:** ``Double``
232+
233+
- **Units:** ``ft^2/hr``
234+
235+
- **Required:** ``false``
236+
237+
<br/>
238+
213239
**Site: Zip Code**
214240

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

22512277
<br/>
22522278

2279+
**Geothermal Loop: Configuration**
2280+
2281+
Configuration of the geothermal loop. Only applies to ground-to-air heat pump type.
2282+
2283+
- **Name:** ``geothermal_loop_configuration``
2284+
- **Type:** ``Choice``
2285+
2286+
- **Required:** ``true``
2287+
2288+
- **Choices:** `none`, `vertical`
2289+
2290+
<br/>
2291+
2292+
**Geothermal Loop: Borefield Configuration**
2293+
2294+
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.
2295+
2296+
- **Name:** ``geothermal_loop_borefield_configuration``
2297+
- **Type:** ``Choice``
2298+
2299+
- **Required:** ``false``
2300+
2301+
- **Choices:** `Rectangle`, `Open Rectangle`, `C`, `L`, `U`, `Lopsided U`
2302+
2303+
<br/>
2304+
2305+
**Geothermal Loop: Loop Flow**
2306+
2307+
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.
2308+
2309+
- **Name:** ``geothermal_loop_loop_flow``
2310+
- **Type:** ``Double``
2311+
2312+
- **Units:** ``gpm``
2313+
2314+
- **Required:** ``false``
2315+
2316+
<br/>
2317+
2318+
**Geothermal Loop: Boreholes Count**
2319+
2320+
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.
2321+
2322+
- **Name:** ``geothermal_loop_boreholes_count``
2323+
- **Type:** ``Integer``
2324+
2325+
- **Units:** ``#``
2326+
2327+
- **Required:** ``false``
2328+
2329+
<br/>
2330+
2331+
**Geothermal Loop: Boreholes Length**
2332+
2333+
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.
2334+
2335+
- **Name:** ``geothermal_loop_boreholes_length``
2336+
- **Type:** ``Double``
2337+
2338+
- **Units:** ``ft``
2339+
2340+
- **Required:** ``false``
2341+
2342+
<br/>
2343+
2344+
**Geothermal Loop: Boreholes Spacing**
2345+
2346+
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.
2347+
2348+
- **Name:** ``geothermal_loop_boreholes_spacing``
2349+
- **Type:** ``Double``
2350+
2351+
- **Units:** ``ft``
2352+
2353+
- **Required:** ``false``
2354+
2355+
<br/>
2356+
2357+
**Geothermal Loop: Boreholes Diameter**
2358+
2359+
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.
2360+
2361+
- **Name:** ``geothermal_loop_boreholes_diameter``
2362+
- **Type:** ``Double``
2363+
2364+
- **Units:** ``in``
2365+
2366+
- **Required:** ``false``
2367+
2368+
<br/>
2369+
2370+
**Geothermal Loop: Grout Type**
2371+
2372+
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.
2373+
2374+
- **Name:** ``geothermal_loop_grout_type``
2375+
- **Type:** ``Choice``
2376+
2377+
- **Required:** ``false``
2378+
2379+
- **Choices:** `standard`, `thermally enhanced`
2380+
2381+
<br/>
2382+
2383+
**Geothermal Loop: Pipe Type**
2384+
2385+
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.
2386+
2387+
- **Name:** ``geothermal_loop_pipe_type``
2388+
- **Type:** ``Choice``
2389+
2390+
- **Required:** ``false``
2391+
2392+
- **Choices:** `standard`, `thermally enhanced`
2393+
2394+
<br/>
2395+
2396+
**Geothermal Loop: Pipe Diameter**
2397+
2398+
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.
2399+
2400+
- **Name:** ``geothermal_loop_pipe_diameter``
2401+
- **Type:** ``Choice``
2402+
2403+
- **Required:** ``false``
2404+
2405+
- **Choices:** `3/4" pipe`, `1" pipe`, `1-1/4" pipe`
2406+
2407+
<br/>
2408+
22532409
**Heating System 2: Type**
22542410

22552411
The type of the second heating system.

BuildResidentialHPXML/measure.rb

+171-1
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,30 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
136136
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.")
137137
args << arg
138138

139+
site_soil_and_moisture_type_choices = OpenStudio::StringVector.new
140+
Constants.SoilTypes.each do |soil_type|
141+
Constants.MoistureTypes.each do |moisture_type|
142+
site_soil_and_moisture_type_choices << "#{soil_type}, #{moisture_type}"
143+
end
144+
end
145+
146+
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('site_soil_and_moisture_type', site_soil_and_moisture_type_choices, false)
147+
arg.setDisplayName('Site: Soil and Moisture Type')
148+
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.")
149+
args << arg
150+
139151
arg = OpenStudio::Measure::OSArgument.makeDoubleArgument('site_ground_conductivity', false)
140152
arg.setDisplayName('Site: Ground Conductivity')
141-
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.")
153+
arg.setDescription('Conductivity of the ground soil. If provided, overrides the previous site and moisture type input.')
142154
arg.setUnits('Btu/hr-ft-F')
143155
args << arg
144156

157+
arg = OpenStudio::Measure::OSArgument.makeDoubleArgument('site_ground_diffusivity', false)
158+
arg.setDisplayName('Site: Ground Diffusivity')
159+
arg.setDescription('Diffusivity of the ground soil. If provided, overrides the previous site and moisture type input.')
160+
arg.setUnits('ft^2/hr')
161+
args << arg
162+
145163
arg = OpenStudio::Measure::OSArgument.makeStringArgument('site_zip_code', false)
146164
arg.setDisplayName('Site: Zip Code')
147165
arg.setDescription('Zip code of the home address.')
@@ -1359,6 +1377,85 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
13591377
arg.setUnits('W')
13601378
args << arg
13611379

1380+
geothermal_loop_configuration_choices = OpenStudio::StringVector.new
1381+
geothermal_loop_configuration_choices << 'none'
1382+
# geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationDiagonal
1383+
# geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationHorizontal
1384+
# geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationOther
1385+
geothermal_loop_configuration_choices << HPXML::GeothermalLoopLoopConfigurationVertical
1386+
1387+
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_configuration', geothermal_loop_configuration_choices, true)
1388+
arg.setDisplayName('Geothermal Loop: Configuration')
1389+
arg.setDescription("Configuration of the geothermal loop. Only applies to #{HPXML::HVACTypeHeatPumpGroundToAir} heat pump type.")
1390+
arg.setDefaultValue('none')
1391+
args << arg
1392+
1393+
geothermal_loop_borefield_configuration_choices = OpenStudio::StringVector.new
1394+
valid_bore_configs = HVACSizing.valid_bore_configs
1395+
valid_bore_configs.keys.each do |valid_bore_config|
1396+
geothermal_loop_borefield_configuration_choices << valid_bore_config
1397+
end
1398+
1399+
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_borefield_configuration', geothermal_loop_borefield_configuration_choices, false)
1400+
arg.setDisplayName('Geothermal Loop: Borefield Configuration')
1401+
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.")
1402+
args << arg
1403+
1404+
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_loop_flow', false)
1405+
arg.setDisplayName('Geothermal Loop: Loop Flow')
1406+
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.")
1407+
arg.setUnits('gpm')
1408+
args << arg
1409+
1410+
arg = OpenStudio::Measure::OSArgument::makeIntegerArgument('geothermal_loop_boreholes_count', false)
1411+
arg.setDisplayName('Geothermal Loop: Boreholes Count')
1412+
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.")
1413+
arg.setUnits('#')
1414+
args << arg
1415+
1416+
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_length', false)
1417+
arg.setDisplayName('Geothermal Loop: Boreholes Length')
1418+
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.")
1419+
arg.setUnits('ft')
1420+
args << arg
1421+
1422+
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_spacing', false)
1423+
arg.setDisplayName('Geothermal Loop: Boreholes Spacing')
1424+
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.")
1425+
arg.setUnits('ft')
1426+
args << arg
1427+
1428+
arg = OpenStudio::Measure::OSArgument::makeDoubleArgument('geothermal_loop_boreholes_diameter', false)
1429+
arg.setDisplayName('Geothermal Loop: Boreholes Diameter')
1430+
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.")
1431+
arg.setUnits('in')
1432+
args << arg
1433+
1434+
geothermal_loop_grout_or_pipe_type_choices = OpenStudio::StringVector.new
1435+
geothermal_loop_grout_or_pipe_type_choices << HPXML::GeothermalLoopGroutOrPipeTypeStandard
1436+
geothermal_loop_grout_or_pipe_type_choices << HPXML::GeothermalLoopGroutOrPipeTypeThermallyEnhanced
1437+
1438+
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_grout_type', geothermal_loop_grout_or_pipe_type_choices, false)
1439+
arg.setDisplayName('Geothermal Loop: Grout Type')
1440+
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.")
1441+
args << arg
1442+
1443+
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_pipe_type', geothermal_loop_grout_or_pipe_type_choices, false)
1444+
arg.setDisplayName('Geothermal Loop: Pipe Type')
1445+
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.")
1446+
args << arg
1447+
1448+
geothermal_loop_pipe_diameter_choices = OpenStudio::StringVector.new
1449+
geothermal_loop_pipe_diameter_choices << '3/4" pipe'
1450+
geothermal_loop_pipe_diameter_choices << '1" pipe'
1451+
geothermal_loop_pipe_diameter_choices << '1-1/4" pipe'
1452+
1453+
arg = OpenStudio::Measure::OSArgument::makeChoiceArgument('geothermal_loop_pipe_diameter', geothermal_loop_pipe_diameter_choices, false)
1454+
arg.setDisplayName('Geothermal Loop: Pipe Diameter')
1455+
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.")
1456+
arg.setUnits('in')
1457+
args << arg
1458+
13621459
heating_system_2_type_choices = OpenStudio::StringVector.new
13631460
heating_system_2_type_choices << 'none'
13641461
heating_system_2_type_choices << HPXML::HVACTypeFurnace
@@ -3424,6 +3521,7 @@ def self.create(runner, model, args, epw_path, hpxml_path, existing_hpxml_path)
34243521
set_heating_systems(hpxml_bldg, args)
34253522
set_cooling_systems(hpxml_bldg, args)
34263523
set_heat_pumps(hpxml_bldg, args)
3524+
set_geothermal_loop(hpxml_bldg, args)
34273525
set_secondary_heating_systems(hpxml_bldg, args)
34283526
set_hvac_distribution(hpxml_bldg, args)
34293527
set_hvac_control(hpxml, hpxml_bldg, args, epw_file, weather)
@@ -4019,6 +4117,16 @@ def self.set_site(hpxml_bldg, args)
40194117
hpxml_bldg.site.ground_conductivity = args[:site_ground_conductivity].get
40204118
end
40214119

4120+
if args[:site_ground_diffusivity].is_initialized
4121+
hpxml_bldg.site.ground_diffusivity = args[:site_ground_diffusivity].get
4122+
end
4123+
4124+
if args[:site_soil_and_moisture_type].is_initialized
4125+
soil_type, moisture_type = args[:site_soil_and_moisture_type].get.split(', ')
4126+
hpxml_bldg.site.soil_type = soil_type
4127+
hpxml_bldg.site.moisture_type = moisture_type
4128+
end
4129+
40224130
if args[:site_type].is_initialized
40234131
hpxml_bldg.site.site_type = args[:site_type].get
40244132
end
@@ -5117,6 +5225,68 @@ def self.set_heat_pumps(hpxml_bldg, args)
51175225
primary_cooling_system: primary_cooling_system)
51185226
end
51195227

5228+
def self.set_geothermal_loop(hpxml_bldg, args)
5229+
loop_configuration = args[:geothermal_loop_configuration]
5230+
5231+
return if loop_configuration == 'none'
5232+
5233+
if args[:geothermal_loop_borefield_configuration].is_initialized
5234+
bore_config = args[:geothermal_loop_borefield_configuration].get
5235+
end
5236+
5237+
if args[:geothermal_loop_loop_flow].is_initialized
5238+
loop_flow = args[:geothermal_loop_loop_flow].get
5239+
end
5240+
5241+
if args[:geothermal_loop_boreholes_count].is_initialized
5242+
num_bore_holes = args[:geothermal_loop_boreholes_count].get
5243+
end
5244+
5245+
if args[:geothermal_loop_boreholes_length].is_initialized
5246+
bore_length = args[:geothermal_loop_boreholes_length].get
5247+
end
5248+
5249+
if args[:geothermal_loop_boreholes_spacing].is_initialized
5250+
bore_spacing = args[:geothermal_loop_boreholes_spacing].get
5251+
end
5252+
5253+
if args[:geothermal_loop_boreholes_diameter].is_initialized
5254+
bore_diameter = args[:geothermal_loop_boreholes_diameter].get
5255+
end
5256+
5257+
if args[:geothermal_loop_grout_type].is_initialized
5258+
grout_type = args[:geothermal_loop_grout_type].get
5259+
end
5260+
5261+
if args[:geothermal_loop_pipe_type].is_initialized
5262+
pipe_type = args[:geothermal_loop_pipe_type].get
5263+
end
5264+
5265+
if args[:geothermal_loop_pipe_diameter].is_initialized
5266+
pipe_diameter = args[:geothermal_loop_pipe_diameter].get
5267+
if pipe_diameter == '3/4" pipe'
5268+
pipe_diameter = 0.75
5269+
elsif pipe_diameter == '1" pipe'
5270+
pipe_diameter = 1.0
5271+
elsif pipe_diameter == '1-1/4" pipe'
5272+
pipe_diameter = 1.25
5273+
end
5274+
end
5275+
5276+
hpxml_bldg.geothermal_loops.add(id: "GeothermalLoop#{hpxml_bldg.geothermal_loops.size + 1}",
5277+
loop_configuration: loop_configuration,
5278+
loop_flow: loop_flow,
5279+
bore_config: bore_config,
5280+
num_bore_holes: num_bore_holes,
5281+
bore_length: bore_length,
5282+
bore_spacing: bore_spacing,
5283+
bore_diameter: bore_diameter,
5284+
grout_type: grout_type,
5285+
pipe_type: pipe_type,
5286+
pipe_diameter: pipe_diameter)
5287+
hpxml_bldg.heat_pumps[-1].geothermal_loop_idref = hpxml_bldg.geothermal_loops[-1].id
5288+
end
5289+
51205290
def self.set_secondary_heating_systems(hpxml_bldg, args)
51215291
heating_system_type = args[:heating_system_2_type]
51225292
heating_system_is_heatpump_backup = (args[:heat_pump_type] != 'none' && args[:heat_pump_backup_type] == HPXML::HeatPumpBackupTypeSeparate)

0 commit comments

Comments
 (0)