Skip to content

Commit

Permalink
Add GHE Properties to System Parameter File (#570)
Browse files Browse the repository at this point in the history
* add ghe to create system parameter function

* Add design method for borehole

* update create sys param and system_parameter.py

* update tests

* update district system type property

* reduce unnecessary indenting

* add negative sign to heat_flow to designate as cooling

* clean up test setup now that we have at least python 3.8

* update district_system_type property in system_parameters.py

* redo the un-indenting I accidentally committed

* update dependencies with poetry

* remove generated test sys-param file

* gitignore generated test sys-param file

* add sys param argument

* fix typo that prevented sys-param creation via cli

* remove nonsensical 5G district parameters

* clean up uo_des test comments a bit, and add intermediate assertions

* remove outdated spawn compilation instructions

* enable 5G models with the CLI

* add borehole length to template

* add gfunction csv file to cli test for ghe district tests

* more updates to gmt class to handle 5g districts from cli

* choose generations more explicitly in district.py

* use correct sys-param parameter name in borefield.py

* add start/stop/step times for model simulation to cli options

* add 5g cli integration test, update calls to simulate during the summer

* Quick fix to enlarge loop flow rate

* change borehole length in test sys-param files to match schema

* make pytest skip reason comment more explicit

* don't skip distribution simulation test

* clarify pytest skip reason comment

---------

Co-authored-by: Nathan Moore <[email protected]>
Co-authored-by: Jing Wang <[email protected]>
  • Loading branch information
3 people authored Jul 28, 2023
1 parent 88c0748 commit eac0cd9
Show file tree
Hide file tree
Showing 26 changed files with 19,582 additions and 449 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ tests/output
tests/*/microgrid_output
tests/output_ets
tests/*/output
tests/management/data/sdk_project_scraps/run/baseline_scenario/system_parameter.json
/geojson_modelica_translator/modelica/buildingslibrary/
not/a/real/**
# TODO: this file shoud not be writtent out, but it is... fix this eventually
Expand Down
14 changes: 0 additions & 14 deletions compiling_with_spawn.md

This file was deleted.

60 changes: 42 additions & 18 deletions geojson_modelica_translator/geojson_modelica_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@
TimeSeriesMFT
)
from geojson_modelica_translator.model_connectors.networks import Network2Pipe
from geojson_modelica_translator.model_connectors.networks.network_distribution_pump import (
NetworkDistributionPump
)
from geojson_modelica_translator.model_connectors.plants import CoolingPlant
from geojson_modelica_translator.model_connectors.plants.borefield import (
Borefield
)
from geojson_modelica_translator.model_connectors.plants.chp import (
HeatingPlantWithOptionalCHP
)
Expand All @@ -44,15 +50,16 @@
}


def _parse_couplings(geojson, sys_params):
def _parse_couplings(geojson, sys_params, district_type=None):
"""Given config files, construct the necessary models and their couplings which
can then be passed to CouplingGraph.
:param geojson: UrbanOptGeoJson
:param sys_params: SystemParameters
:param district_type: str - type of district [None, "4G", "5G"]
:return: list[Coupling], list of couplings to be passed to CouplingGraph
"""
# Current implementation assumes that all generated district energy system models will have:
# 4G implementation assumes that all generated district energy system models will have:
# - one heating plant
# - one cooling plant
# - one heating distribution network
Expand All @@ -61,29 +68,40 @@ def _parse_couplings(geojson, sys_params):
# NOTE: loads can be of any type/combination
all_couplings = []

# create the plants and networks
cooling_network = Network2Pipe(sys_params)
cooling_plant = CoolingPlant(sys_params)
heating_network = Network2Pipe(sys_params)
heating_plant = HeatingPlantWithOptionalCHP(sys_params)
all_couplings += [
Coupling(cooling_plant, cooling_network),
Coupling(heating_plant, heating_network),
]
if district_type is None or district_type == "4G":
# create the plants and networks
cooling_network = Network2Pipe(sys_params)
cooling_plant = CoolingPlant(sys_params)
heating_network = Network2Pipe(sys_params)
heating_plant = HeatingPlantWithOptionalCHP(sys_params)
all_couplings += [
Coupling(cooling_plant, cooling_network),
Coupling(heating_plant, heating_network),
]
elif district_type == "5G":
# create ambient water stub
ambient_water_stub = NetworkDistributionPump(sys_params)
# create borefield
borefield = Borefield(sys_params)
all_couplings.append(Coupling(borefield, ambient_water_stub, district_type))
all_couplings.append(Coupling(ambient_water_stub, ambient_water_stub, district_type))

# create the loads and their ETSes
for building in geojson.buildings:
load_model_type = sys_params.get_param_by_building_id(building.id, "load_model")
load_class = LOAD_MODEL_TO_CLASS[load_model_type]
load = load_class(sys_params, building)

cooling_indirect = CoolingIndirect(sys_params, building.id)
all_couplings.append(Coupling(load, cooling_indirect))
all_couplings.append(Coupling(cooling_indirect, cooling_network))
if district_type is None or district_type == "4G":
cooling_indirect = CoolingIndirect(sys_params, building.id)
all_couplings.append(Coupling(load, cooling_indirect))
all_couplings.append(Coupling(cooling_indirect, cooling_network))

heating_indirect = HeatingIndirect(sys_params, building.id)
all_couplings.append(Coupling(load, heating_indirect))
all_couplings.append(Coupling(heating_indirect, heating_network))
heating_indirect = HeatingIndirect(sys_params, building.id)
all_couplings.append(Coupling(load, heating_indirect))
all_couplings.append(Coupling(heating_indirect, heating_network))
elif district_type == "5G":
all_couplings.append(Coupling(load, ambient_water_stub, district_type))

return all_couplings

Expand Down Expand Up @@ -142,9 +160,15 @@ def __init__(
)
self._geojson = UrbanOptGeoJson(geojson_filepath, geojson_ids)

# Use different couplings for each district system type
district_type = self._system_parameters.get_param("district_system")
if 'fifth_generation' in district_type:
self._couplings = _parse_couplings(self._geojson, self._system_parameters, district_type='5G')
elif 'fourth_generation' in district_type:
self._couplings = _parse_couplings(self._geojson, self._system_parameters)

self._root_dir = root_dir
self._project_name = project_name
self._couplings = _parse_couplings(self._geojson, self._system_parameters)
self._coupling_graph = CouplingGraph(self._couplings)
self._district = District(
self._root_dir,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
datDes(
nBui={{ sys_params.num_buildings }},
{% if sys_params.district_system.fifth_generation.ghe_parameters.design.flow_type == 'borehole' %}
mPumDis_flow_nominal={{ sys_params.district_system.fifth_generation.ghe_parameters.design.flow_rate*
mPumDis_flow_nominal={{ 10*sys_params.district_system.fifth_generation.ghe_parameters.design.flow_rate*
sys_params.district_system.fifth_generation.ghe_parameters.ghe_specific_params[0].borehole.number_of_boreholes }},
{% else %}
mPumDis_flow_nominal={{ sys_params.district_system.fifth_generation.ghe_parameters.design.flow_rate }},
mPumDis_flow_nominal={{ 10*sys_params.district_system.fifth_generation.ghe_parameters.design.flow_rate }},
{% endif %}
mPipDis_flow_nominal=datDes.mPumDis_flow_nominal,
dp_length_nominal=250,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def to_modelica(self):
# render the full district file
if 'fifth_generation' in common_template_params['sys_params']['district_system']:
final_result = render_template('DistrictEnergySystem5G.mot', district_template_params)
else:
elif 'fourth_generation' in common_template_params['sys_params']['district_system']:
final_result = render_template('DistrictEnergySystem.mot', district_template_params)
with open(self.district_model_filepath, 'w') as f:
f.write(final_result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ model {{ model_filename }}
annotation (Dialog(group="Heat exchanger"));
parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal(
final min=0,
{% endraw %}start={{ ets_data["heat_flow_nominal"] }})
{% endraw %}start=-{{ ets_data["heat_flow_nominal"] }})
{% raw %} "Nominal heat transfer"
annotation (Dialog(group="Heat exchanger"));
parameter Modelica.Units.SI.Temperature T_a1_nominal(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def to_modelica(self, scaffold):
"$.district_system.fifth_generation.ghe_parameters.design.flow_type"
),
"borehole_height": self.system_parameters.get_param(
"$.district_system.fifth_generation.ghe_parameters.ghe_specific_params[0].borehole.length"
"$.district_system.fifth_generation.ghe_parameters.ghe_specific_params[0].borehole.length_of_boreholes"
),
"borehole_diameter": self.system_parameters.get_param(
"$.district_system.fifth_generation.ghe_parameters.ghe_specific_params[0].borehole.diameter"
Expand Down
19 changes: 10 additions & 9 deletions geojson_modelica_translator/system_parameters/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1225,15 +1225,6 @@
"properties": {
"fifth_generation": {
"properties": {
"central_cooling_plant_parameters": {
"$ref": "#/definitions/central_cooling_plant_parameters"
},
"central_heating_plant_parameters": {
"$ref": "#/definitions/central_heating_plant_parameters"
},
"combined_heat_and_power_parameters": {
"$ref": "#/definitions/combined_heat_and_power_parameters"
},
"ghe_parameters": {
"$ref": "#/definitions/ghe_parameters"
},
Expand Down Expand Up @@ -1599,6 +1590,15 @@
"description": "Design parameters used for GHE sizing.",
"type": "object",
"properties": {
"method": {
"description": "Building load distribution method for Ground Heat Exchanger sizing",
"type": "string",
"enum": [
"AREAPROPORTIONAL",
"UPSTREAM"
],
"default": "AREAPROPORTIONAL"
},
"flow_rate": {
"description": "Nominal design mass flow rate. Depending on whether the flow_type attribute is set to 'borehole' or 'system', this will be the nominal flow rate for either each borehole or the entire ground heat exchanger.",
"type": "number",
Expand Down Expand Up @@ -1626,6 +1626,7 @@
}
},
"required": [
"method",
"flow_rate",
"flow_type",
"max_eft",
Expand Down
77 changes: 70 additions & 7 deletions geojson_modelica_translator/system_parameters/system_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import json
import logging
import math
import os
from copy import deepcopy
from pathlib import Path
Expand Down Expand Up @@ -674,11 +675,24 @@ def process_microgrid_inputs(self, scenario_dir: Path):
# Power Converters
# TODO: not handled in UO / OpenDSS

def calculate_dimensions(self, area, perimeter):

discriminant = perimeter ** 2 - 16 * area

if discriminant < 0:
raise ValueError("No valid rectangle dimensions exist for the given area and perimeter.")

length = (perimeter + math.sqrt(discriminant)) / 4
width = (perimeter - 2 * length) / 2

return length, width

def csv_to_sys_param(self,
model_type: str,
scenario_dir: Path,
feature_file: Path,
sys_param_filename: Path,
ghe=False,
overwrite=True,
microgrid=False) -> None:
"""
Expand All @@ -689,6 +703,7 @@ def csv_to_sys_param(self,
:param feature_file: Path, location/name of uo_sdk input file
:param sys_param_filename: Path, location/name of system parameter file to be created
:param overwrite: Boolean, whether to overwrite existing sys-param file
:param ghe: Boolean, flag to add Ground Heat Exchanger properties to System Parameter File
:param microgrid: Boolean, Optional. If set to true, also process microgrid fields
:return None, file created and saved to user-specified location
"""
Expand Down Expand Up @@ -731,16 +746,15 @@ def csv_to_sys_param(self,
measure_list.append(Path(item) / "modelica.mos") # space heating/cooling & water heating
measure_list.append(Path(item) / "building_loads.csv") # used for max electricity load

# Get each feature id from the SDK FeatureFile
# Get each building feature id from the SDK FeatureFile
building_ids = []
with open(feature_file) as json_file:
sdk_input = json.load(json_file)
weather_filename = sdk_input['project']['weather_filename']
weather_path = self.sys_param_filename.parent / weather_filename
for feature in sdk_input['features']:
# KAF change: this should only gather features of type 'Building'
if feature['properties']['type'] == 'Building':
building_ids.append(feature['properties']['id'])
weather_filename = sdk_input['project']['weather_filename']
weather_path = self.sys_param_filename.parent / weather_filename
for feature in sdk_input['features']:
if feature['properties']['type'] == 'Building':
building_ids.append(feature['properties']['id'])

# Check if the EPW weatherfile exists, if not, try to download
if not weather_path.exists():
Expand Down Expand Up @@ -825,6 +839,55 @@ def csv_to_sys_param(self,
raise SystemExit(f"\nError: No scenario_optimization.json file found in {scenario_dir}\n"
"Perhaps you haven't run REopt post-processing step in the UO sdk?")

# Update ground heat exchanger properties if true
if ghe:

ghe_ids = []
# add properties from the feature file
with open(feature_file) as json_file:
sdk_input = json.load(json_file)
for feature in sdk_input['features']:
if feature['properties']['type'] == 'District System':
try:
district_system_type = feature['properties']['district_system_type']
except KeyError:
pass
if district_system_type == 'Ground Heat Exchanger':
length, width = self.calculate_dimensions(feature['properties']['footprint_area'], feature['properties']['footprint_perimeter'])
ghe_ids.append({'ghe_id': feature['properties']['id'],
'length_of_ghe': length,
'width_of_ghe': width})

ghe_sys_param = self.param_template['district_system']['fifth_generation']['ghe_parameters']
# Make sys_param template entries for GHE specific properties
ghe_list = []
for ghe in ghe_ids:
# update GHE specific properties
ghe_info = deepcopy(ghe_sys_param['ghe_specific_params'][0])
# Update GHE ID
ghe_info['ghe_id'] = str(ghe['ghe_id'])
# Add ghe geometric properties
ghe_info['ghe_geometric_params']['length_of_ghe'] = ghe['length_of_ghe']
ghe_info['ghe_geometric_params']['width_of_ghe'] = ghe['width_of_ghe']
ghe_list.append(ghe_info)

# Add all GHE specific properties to sys-param file
ghe_sys_param['ghe_specific_params'] = ghe_list

# Update ghe_dir
ghe_dir = scenario_dir / 'ghe_dir'
ghe_sys_param['ghe_dir'] = str(ghe_dir)

# remove fourth generation district system type
del self.param_template['district_system']['fourth_generation']

else:
# remove fifth generation district system type if it exists in template and ghe is not true
try:
del self.param_template['district_system']['fifth_generation']
except KeyError:
pass

# save the file to disk
self.save()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,68 @@
"pressure_drop_hhw_valve_nominal": 6001,
"chp_installed": false
}
},
"fifth_generation": {
"ghe_parameters": {
"version": "1.0",
"ghe_dir": "tests/system_parameters/data",
"fluid": {
"fluid_name": "Water",
"concentration_percent": 0.0,
"temperature": 20
},
"grout": {
"conductivity": 1.0,
"rho_cp": 3901000
},
"soil": {
"conductivity": 2.0,
"rho_cp": 2343493,
"undisturbed_temp": 18.3
},
"pipe": {
"inner_diameter": 0.0216,
"outer_diameter": 0.0266,
"shank_spacing": 0.0323,
"roughness": 1e-06,
"conductivity": 0.4,
"rho_cp": 1542000,
"arrangement": "singleutube"
},
"simulation": {
"num_months": 240
},
"geometric_constraints": {
"b_min": 3.0,
"b_max": 10.0,
"max_height": 135.0,
"min_height": 60.0,
"method": "rectangle"
},
"design": {
"method": "AREAPROPORTIONAL",
"flow_rate": 0.2,
"flow_type": "borehole",
"max_eft": 35.0,
"min_eft": 5.0
},
"ghe_specific_params": [
{
"ghe_id": "c432cb11-4813-40df-8dd4-e88f5de40033",
"ghe_geometric_params": {
"length_of_ghe": 100,
"width_of_ghe": 100
},
"borehole": {
"buried_depth": 2.0,
"diameter": 0.15,
"length_of_boreholes": 1.0,
"number_of_boreholes": 5
},
"ground_loads": []
}
]
}
}
},
"weather": "../../data_shared/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"
Expand Down
Loading

0 comments on commit eac0cd9

Please sign in to comment.