Skip to content

Commit

Permalink
Templates and tests for horizontal piping modeling (#627)
Browse files Browse the repository at this point in the history
* Add customized mo files

* Add kIns and use each

* Introduce a new template for ground coupling

* Supplemental table for calculating soil temperature

* Placeholder python file for ground coupling

* Pass more pipe material parameters

* Add example sys_pamas file for tests

* Modified ground coupling template

* Ground coupling instance

* Update package names

* Modify dis to take more inputs

* Update py file, not final yet

* Update ground_coupling.py

* add method to read a feature from a geojson file by id

* method to read a geojson feature from a jsonpath

* code to read from geojson to templtate

* add test line to attempt injecting from geojson into template

* test for ground_coupling

* empty ground_coupling coupling templates - WIP

* update dependencies

* Add equations for calculating wall thickness

* Add function for searching for weather station

* finalize py file

* get pipe lengths in datDes

* build new coupling

* move dis instance to new coupling

* Access data of sys_params

* Move things in coupling

* Fix typo

* Change pipe length list to be global

* Modify test to instantiate ground coupling

* Reading geojson in district.py, might cause problem to other district tests

* New geojson with thermal connectors for testing

* Modify parameter paths

* Update geojson file name in test

* Rearrange couplings

* Update coupling list in test

* Fix within statements

* Update some parameters

* Update access to borefield id

* Update access to num_buildings in template

* Add TODO

* Change pump input type

* Change how lDis and lEnd are populated

* Replace sqaure brackets

* Convert ft to meter

* Pre-commit changes

* skip a lint check in district.py. A different PR refactors this, so ignore for now

* format modelica code via pre-commit

* Avoid using excel reader

* Add horizontal pipe properties (#632)

* Add horizontal pipe properties

* add horizontal piping to 5th gen

---------

Co-authored-by: Nathan Moore <nathan.moore@nrel.gov>

* Add horizontal piping parameters to template

* Remove test no longer needed

* Update test to include ground coupling

* Not passing lDis or lEnd for non-5G districts

* Pre-commit changes

* Fix typo

* fix commas and `}` in sys-param schema

---------

Co-authored-by: Nathan Moore <nathan.moore@nrel.gov>
Co-authored-by: tanushree04 <47833030+tanushree04@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 2, 2024
1 parent 4393327 commit de32dcc
Show file tree
Hide file tree
Showing 23 changed files with 6,592 additions and 20 deletions.
40 changes: 40 additions & 0 deletions geojson_modelica_translator/geojson/urbanopt_geojson.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pathlib import Path

import geojson
from jsonpath_ng.ext import parse

from geojson_modelica_translator.geojson.schemas import Schemas

Expand Down Expand Up @@ -81,3 +82,42 @@ def __init__(self, filename, building_ids=None):

if not self.buildings:
raise GeoJsonValidationError(f"No valid buildings found in GeoJSON file: {filename}")

def get_feature_by_id(self, feature_id=None):
"""return geojson data for a specific feature (building, pipe, wire, junction, district system, etc).
:param feature_id: string, id of the object to look up in the geojson file
:return: dict, full feature data for the object with the given id
"""

if feature_id is None:
raise SystemExit("No id submitted. Please retry and include the appropriate id")

for feature in self.data.features:
if feature["properties"]["id"] == str(feature_id):
return feature

def get_feature(self, jsonpath):
"""Return the parameter(s) from a jsonpath.
:param path: string, period delimited path of the data to retrieve
:return: dict, full feature data for the object with the given id
"""

if jsonpath is None or jsonpath == "":
return None

matches = parse(jsonpath).find(self.data)

results = []
for match in matches:
results.append(match.value)

if len(results) == 1:
# If only one value, then return that value and not a list of values
results = results[0]
elif len(results) == 0:
return print(f"No matches found for jsonpath {jsonpath}")

# otherwise return the list of values
return results
11 changes: 10 additions & 1 deletion geojson_modelica_translator/geojson_modelica_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from geojson_modelica_translator.model_connectors.energy_transfer_systems import CoolingIndirect, HeatingIndirect
from geojson_modelica_translator.model_connectors.load_connectors import Spawn, Teaser, TimeSeries, TimeSeriesMFT
from geojson_modelica_translator.model_connectors.networks import Network2Pipe
from geojson_modelica_translator.model_connectors.networks.ground_coupling import GroundCoupling
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
Expand Down Expand Up @@ -62,8 +63,11 @@ def _parse_couplings(geojson, sys_params, district_type=None):
ambient_water_stub = NetworkDistributionPump(sys_params)
# create borefield
borefield = Borefield(sys_params)
# create ground coupling
ground_coupling = GroundCoupling(sys_params)
all_couplings.append(Coupling(borefield, ambient_water_stub, district_type))
all_couplings.append(Coupling(ambient_water_stub, ambient_water_stub, district_type))
all_couplings.append(Coupling(ground_coupling, borefield, district_type="5G"))

# create the loads and their ETSes
for building in geojson.buildings:
Expand Down Expand Up @@ -142,7 +146,12 @@ def __init__(
self._root_dir = root_dir
self._project_name = project_name
self._coupling_graph = CouplingGraph(self._couplings)
self._district = District(self._root_dir, self._project_name, self._system_parameters, self._coupling_graph)
if "fifth_generation" in district_type:
self._district = District(
self._root_dir, self._project_name, self._system_parameters, self._coupling_graph, self._geojson
)
else:
self._district = District(self._root_dir, self._project_name, self._system_parameters, self._coupling_graph)
self._package_created = False

def to_modelica(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// No components for ground coupling and borefield coupling
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Connections between ground coupling and distribution
connect(dis.heatPortGro,{{ coupling.network.id }}.ports[1, :])
{% raw %}annotation (Line(points={{70,-20},{70,-36},{104,-36},{104,28},{150,28},{150,40}},color={191,0,0}));
{% endraw %}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
{% for building in range( sys_params.num_buildings-1 ) %}
{{ graph.couplings_by_type(coupling.network.id).load_couplings[building].load.id }}.ets.mSerWat_flow_nominal,
{% endfor %}
{{ graph.couplings_by_type(coupling.network.id).load_couplings[sys_params.num_buildings-1].load.id }}.ets.mSerWat_flow_nominal})
{{ graph.couplings_by_type(coupling.network.id).load_couplings[sys_params.num_buildings-1].load.id }}.ets.mSerWat_flow_nominal},
lDis={{ globals["lDis"] }},
lEnd={{ globals["lEnd"] }})
"Design data"
{% raw %}annotation (Placement(transformation(extent={{-140,100},{-120,120}})));
parameter Boolean allowFlowReversalSer = true
Expand Down
24 changes: 19 additions & 5 deletions geojson_modelica_translator/model_connectors/districts/district.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from geojson_modelica_translator.model_connectors.couplings.diagram import Diagram
from geojson_modelica_translator.model_connectors.load_connectors.load_base import LoadBase
from geojson_modelica_translator.scaffold import Scaffold
from geojson_modelica_translator.utils import mbl_version
from geojson_modelica_translator.utils import convert_ft_to_m, mbl_version

logger = logging.getLogger(__name__)

Expand All @@ -34,9 +34,10 @@ def render_template(template_name, template_params):
class District:
"""Class for modeling entire district energy systems"""

def __init__(self, root_dir, project_name, system_parameters, coupling_graph):
def __init__(self, root_dir, project_name, system_parameters, coupling_graph, geojson_file=None):
self._scaffold = Scaffold(root_dir, project_name)
self.system_parameters = system_parameters
self.gj = geojson_file
self._coupling_graph = coupling_graph
self.district_model_filepath = None
# Modelica can't handle spaces in project name or path
Expand All @@ -48,9 +49,8 @@ def __init__(self, root_dir, project_name, system_parameters, coupling_graph):
)

def to_modelica(self):
"""Generate modelica files for the models as well as the modelica file for
the entire district system.
"""
"""Generate modelica files for the models as well as the modelica file for the entire district system."""

# scaffold the project
self._scaffold.create()
self.district_model_filepath = Path(self._scaffold.districts_path.files_dir) / "DistrictEnergySystem.mo"
Expand Down Expand Up @@ -78,6 +78,7 @@ def to_modelica(self):
"models": [],
"is_ghe_district": self.system_parameters.get_param("$.district_system.fifth_generation.ghe_parameters"),
}

common_template_params = {
"globals": {
"medium_w": "MediumW",
Expand All @@ -94,6 +95,19 @@ def to_modelica(self):
},
}

if self.gj:
# get horizontal pipe lengths from geojson, starting from the outlet of the (first) ghe
# TODO: only check for total_length if type==ThermalConnector
# I thought this was the right syntax, but not quite: .properties[?type=ThermalConnector].total_length
# TODO: make sure the list of lengths is starting from the outlet of the ghe
list_of_pipe_lengths = self.gj.get_feature("$.features.[*].properties.total_length")
for i in range(len(list_of_pipe_lengths)):
list_of_pipe_lengths[i] = convert_ft_to_m(list_of_pipe_lengths[i])
common_template_params["globals"]["lDis"] = (
str(list_of_pipe_lengths[:-1]).replace("[", "{").replace("]", "}")
)
common_template_params["globals"]["lEnd"] = list_of_pipe_lengths[-1]

# render each coupling
load_num = 1
for coupling in self._coupling_graph.couplings:
Expand Down
Loading

0 comments on commit de32dcc

Please sign in to comment.