Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GHE Properties to System Parameter File #570

Merged
merged 34 commits into from Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5c528d4
add ghe to create system parameter function
tanushree04 Jul 6, 2023
051822f
Add design method for borehole
tanushree04 Jul 12, 2023
8e1abca
update create sys param and system_parameter.py
tanushree04 Jul 14, 2023
e3daa50
update tests
tanushree04 Jul 17, 2023
3332b83
update district system type property
tanushree04 Jul 19, 2023
8b3a564
reduce unnecessary indenting
vtnate Jul 19, 2023
82025ab
add negative sign to heat_flow to designate as cooling
vtnate Jul 19, 2023
53119ad
clean up test setup now that we have at least python 3.8
vtnate Jul 19, 2023
66b8a74
update district_system_type property in system_parameters.py
tanushree04 Jul 19, 2023
df37a30
Merge branch 'ghe_modify' of github.com:urbanopt/geojson-modelica-tra…
vtnate Jul 19, 2023
4ac499c
redo the un-indenting I accidentally committed
vtnate Jul 19, 2023
7c5fd69
update dependencies with poetry
vtnate Jul 20, 2023
1d61309
remove generated test sys-param file
vtnate Jul 20, 2023
836cca8
gitignore generated test sys-param file
vtnate Jul 20, 2023
3ca86b6
add sys param argument
tanushree04 Jul 26, 2023
d0d58e2
fix typo that prevented sys-param creation via cli
vtnate Jul 26, 2023
1662b82
remove nonsensical 5G district parameters
vtnate Jul 27, 2023
1616023
clean up uo_des test comments a bit, and add intermediate assertions
vtnate Jul 27, 2023
bf3f983
remove outdated spawn compilation instructions
vtnate Jul 27, 2023
f600deb
enable 5G models with the CLI
vtnate Jul 27, 2023
60a43ca
Merge branch 'gmt-with-5g' into ghe_modify
vtnate Jul 27, 2023
b743d6e
add borehole length to template
tanushree04 Jul 27, 2023
377241c
Merge branch 'ghe_modify' of github.com:urbanopt/geojson-modelica-tra…
vtnate Jul 27, 2023
5a3da8c
add gfunction csv file to cli test for ghe district tests
vtnate Jul 27, 2023
1b66d1b
more updates to gmt class to handle 5g districts from cli
vtnate Jul 27, 2023
ac85feb
choose generations more explicitly in district.py
vtnate Jul 27, 2023
1f6adbc
use correct sys-param parameter name in borefield.py
vtnate Jul 27, 2023
56fa91d
add start/stop/step times for model simulation to cli options
vtnate Jul 27, 2023
98701bd
add 5g cli integration test, update calls to simulate during the summer
vtnate Jul 27, 2023
2963d54
Quick fix to enlarge loop flow rate
JingWang-CUB Jul 27, 2023
6644106
change borehole length in test sys-param files to match schema
vtnate Jul 27, 2023
174b6b9
make pytest skip reason comment more explicit
vtnate Jul 27, 2023
217f045
don't skip distribution simulation test
vtnate Jul 27, 2023
0a11c46
clarify pytest skip reason comment
vtnate Jul 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
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
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
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*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pump wasn't moving enough water to satisfy the district, so this was increased.

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
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
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"] }})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Negative sign to denote cooling rather than heating

{% raw %} "Nominal heat transfer"
annotation (Dialog(group="Heat exchanger"));
parameter Modelica.Units.SI.Temperature T_a1_nominal(
Expand Down
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
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
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
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