Skip to content

Commit

Permalink
Merge branch 'bump-om' into mblv11
Browse files Browse the repository at this point in the history
  • Loading branch information
vtnate committed Oct 8, 2024
2 parents c9a1625 + dbc76ec commit 4caaa59
Show file tree
Hide file tree
Showing 137 changed files with 233,604 additions and 1,036 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.10", "3.12.1"]
python-version: ["3.10", "3.12"]
test_env: [python, docs, mypy]
mbl_tag: [v11.0.0]
exclude:
Expand All @@ -41,7 +41,7 @@ jobs:
docker --version
docker compose version
- name: Install Poetry
uses: Gr1N/setup-poetry@v8 # optionally set specific poetry version. Defaults to latest
uses: Gr1N/setup-poetry@v9 # optionally set specific poetry version. Defaults to latest
- name: Install dependencies with Poetry
# poetry setuptools workaround sourced from https://github.com/python-poetry/poetry/issues/7611#issuecomment-1711443539
run: |
Expand Down Expand Up @@ -89,6 +89,7 @@ jobs:
if: matrix.test_env == 'docs'
run: |
cd docs
pip install setuptools
poetry run make html
- name: Coveralls
env:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,9 @@ tests/modelica/data/packages/*/*.txt
tests/modelica/data/packages/*/*.c
tests/modelica/data/packages/*/dymosim
tests/management/data/sdk_project_scraps/run/baseline_scenario/system_parameter.json
tests/management/data/sdk_project_scraps/run/baseline_scenario/DEU_Stuttgart.107380_IWEC*
geojson_modelica_translator/modelica/buildingslibrary/
not/
tests/geojson_modelica_translator/data/modelica_5/modelica_5.Districts.DistrictEnergySystem_results/modelica_5.Districts.DistrictEnergySystem_result.csv
tests/geojson_modelica_translator/data/modelica_model
tests/geojson_modelica_translator/data/modelica_multiple/modelica_multiple.Districts.DistrictEnergySystem_results/modelica_multiple.Districts.DistrictEnergySystem_result.csv
6 changes: 2 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ exclude: |
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: check-ast
- id: check-added-large-files
Expand Down Expand Up @@ -44,12 +44,10 @@ repos:
pass_filenames: false
# https://docs.astral.sh/ruff/integrations/#pre-commit
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.0
rev: v0.6.4
hooks:
# Run the linter
- id: ruff
args: [--fix, --exit-non-zero-on-fix, --output-format=full]
types_or: [python, pyi, jupyter]
# Run the formatter
- id: ruff-format
types_or: [python, pyi, jupyter]
7 changes: 5 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@
'sphinx.ext.coverage',
'sphinx.ext.napoleon',
'sphinx-jsonschema',
'm2r2',
'myst_parser',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

# The suffix of source filenames.
source_suffix = ".rst"
source_suffix = {
'.rst': 'restructuredtext',
'.md': 'markdown',
}

# The encoding of source files.
# source_encoding = 'utf-8-sig'
Expand Down
16 changes: 16 additions & 0 deletions geojson_modelica_translator/external_package_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import json
from pathlib import Path


def load_loop_order(system_parameters_file: Path) -> list:
"""Loads the loop order from a JSON file
loop_order file is always saved next to the system parameters file
:param system_parameters_file: Path to the system parameters file
:return: list of building & ghe ids in loop order
"""
loop_order_path = Path(system_parameters_file).parent / "_loop_order.json"
if not loop_order_path.is_file():
raise FileNotFoundError(f"Loop order file not found at {loop_order_path}")
return json.loads(loop_order_path.read_text())
4 changes: 2 additions & 2 deletions geojson_modelica_translator/geojson/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md

import json
import os
from pathlib import Path

from jsonschema.validators import Draft202012Validator as LatestValidator

Expand All @@ -24,7 +24,7 @@ def __init__(self):
}

for s in self.schemas:
path = os.path.join(os.path.dirname(__file__), "data/schemas/%s_properties.json" % s)
path = Path(__file__).parent / "data" / "schemas" / f"{s}_properties.json"
with open(path) as f:
self.schemas[s] = json.load(f)

Expand Down
72 changes: 52 additions & 20 deletions geojson_modelica_translator/geojson_modelica_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
import logging
from pathlib import Path

from geojson_modelica_translator.external_package_utils import load_loop_order
from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson
from geojson_modelica_translator.model_connectors.couplings import Coupling, CouplingGraph
from geojson_modelica_translator.model_connectors.districts import District
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.design_data_series import DesignDataSeries
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.networks.unidirectional_series import UnidirectionalSeries
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 @@ -30,13 +33,13 @@
}


def _parse_couplings(geojson, sys_params, district_type=None):
def _parse_couplings(geojson, sys_params, sys_param_district_type):
"""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"]
:param sys_param_district_type: str - type of district ["fourth_generation", "fifth_generation"]
:return: list[Coupling], list of couplings to be passed to CouplingGraph
"""
# 4G implementation assumes that all generated district energy system models will have:
Expand All @@ -48,7 +51,7 @@ def _parse_couplings(geojson, sys_params, district_type=None):
# NOTE: loads can be of any type/combination
all_couplings = []

if district_type is None or district_type == "4G":
if sys_param_district_type == "fourth_generation":
# create the plants and networks
cooling_network = Network2Pipe(sys_params)
cooling_plant = CoolingPlant(sys_params)
Expand All @@ -58,33 +61,64 @@ def _parse_couplings(geojson, sys_params, district_type=None):
Coupling(cooling_plant, cooling_network),
Coupling(heating_plant, heating_network),
]
elif district_type == "5G":
elif sys_param_district_type == "fifth_generation":
# create ambient water stub
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 district data
design_data = DesignDataSeries(sys_params)
# import loo order
loop_order = load_loop_order(sys_params.filename)

if sys_params.get_param("$.district_system.fifth_generation.ghe_parameters"):
# create ground coupling
ground_coupling = GroundCoupling(sys_params)
for loop in loop_order:
ghe_id = loop["list_ghe_ids_in_group"][0]
for ghe in sys_params.get_param(
"$.district_system.fifth_generation.ghe_parameters.ghe_specific_params"
):
if ghe_id == ghe["ghe_id"]:
borefield = Borefield(sys_params, ghe)
distribution = UnidirectionalSeries(sys_params)
for bldg_id in loop["list_bldg_ids_in_group"]:
for geojson_load in geojson.buildings:
if bldg_id == geojson_load.id:
# create the building time series load
time_series_load = TimeSeries(sys_params, geojson_load)
# couple each time series load to distribution
all_couplings.append(
Coupling(time_series_load, distribution, district_type="fifth_generation")
)
all_couplings.append(
Coupling(time_series_load, ambient_water_stub, district_type="fifth_generation")
)
all_couplings.append(
Coupling(time_series_load, design_data, district_type="fifth_generation")
)
# couple each borefield and distribution
all_couplings.append(Coupling(distribution, borefield, district_type="fifth_generation"))
# couple distribution and ground coupling
all_couplings.append(Coupling(distribution, ground_coupling, district_type="fifth_generation"))
# empty couple between borefield and ground
all_couplings.append(Coupling(ground_coupling, borefield, district_type="fifth_generation"))
all_couplings.append(Coupling(ambient_water_stub, ambient_water_stub, district_type="fifth_generation"))
else:
pass # Create waste heat components & couplings

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

if district_type is None or district_type == "4G":
if sys_param_district_type is None or sys_param_district_type == "fourth_generation":
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))
elif district_type == "5G":
all_couplings.append(Coupling(load, ambient_water_stub, district_type))

return all_couplings

Expand Down Expand Up @@ -137,16 +171,14 @@ 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)
# The first key of district_system is always the district system type
sys_param_district_type = next(iter(self._system_parameters.get_param("district_system")))
self._couplings = _parse_couplings(self._geojson, self._system_parameters, sys_param_district_type)

self._root_dir = root_dir
self._project_name = project_name
self._coupling_graph = CouplingGraph(self._couplings)
if "fifth_generation" in district_type:
if sys_param_district_type == "fifth_generation":
self._district = District(
self._root_dir, self._project_name, self._system_parameters, self._coupling_graph, self._geojson
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
// No components for ground coupling and borefield coupling
// No components for borefield and ground coupling
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
// 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 %}
// Borefield and ground coupling connections
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Borefield ambient coupling connections
connect(supHeaWat_1.ports[1], {{ coupling.plant.id }}.port_a)
{% raw %}annotation (Line(points={{-70,10},{-10,10}}, color={0,127,255}));
{% endraw %}connect({{ coupling.plant.id }}.port_b, sinHeaWat.ports[1])
{% raw %}annotation (Line(points={{10,10},{60,10}}, color={0,127,255}));
{% endraw %}
{% for group_num in range(sys_params.district_system.fifth_generation.ghe_parameters.ghe_specific_params|length) %}
{% if graph.get_ghe_id(coupling.id) == sys_params.district_system.fifth_generation.ghe_parameters.ghe_specific_params[group_num].ghe_id %}
connect(supHeaWat_1.ports[{{ group_num+1 }}], {{ coupling.plant.id }}.port_a)
{% raw %}annotation (Line(points={{-70,10},{-10,10}}, color={0,127,255}));
{% endraw %}connect({{ coupling.plant.id }}.port_b, sinHeaWat.ports[{{ group_num+1 }}])
{% raw %}annotation (Line(points={{10,10},{60,10}}, color={0,127,255}));
{% endraw %}
{% endif %}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
// No components for borefield and ambient loop coupling
// No components for network distribution pump and borefield coupling
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
// Borefield ambient coupling connections
connect(pumDis.port_b, {{ coupling.plant.id }}.port_a)
{% raw %}annotation (Line(points={{-44,-50},{-44,-10},{-20,-10}},color={0,127,255}));
{% endraw %}connect({{ coupling.plant.id }}.port_b, TOut.port_a)
{% raw %}annotation (Line(points={{-10,10},{6,10}}, color={0,127,255}));
{% endraw %}
// Network distribution pump and borefield connections
Original file line number Diff line number Diff line change
@@ -1,25 +1,3 @@
inner parameter
Buildings.DHC.Examples.Combined.BaseClasses.DesignDataSeries
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*
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 }},
{% endif %}
mPipDis_flow_nominal=datDes.mPumDis_flow_nominal,
dp_length_nominal=250,
final mCon_flow_nominal={
{% 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},
lDis={{ globals["lDis"] }},
lEnd={{ globals["lEnd"] }})
"Design data"
{% raw %}annotation (Placement(transformation(extent={{-140,100},{-120,120}})));
parameter Boolean allowFlowReversalSer = true
"Set to true to allow flow reversal in the service lines"
annotation(Dialog(tab="Assumptions"), Evaluate=true);
{% endraw %}
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
// Connections for sub-components
{% raw %}connect(dis.port_bDisSup, TIn.port_a)
annotation (Line(points={{90,10},{110,10},{110,-20}}, color={0,127,255}));
connect(TIn.port_b, pumDis.port_a)
annotation (Line(points={{110,-40},{110,-80},{-44,-80},{-44,-70}}, color={0,127,255}));
connect(expVes.ports[1], pumDis.port_a)
{% raw %}connect(expVes.ports[1], pumDis.port_a)
annotation (Line(points={{-20,-100},{-20,-80},{-44,-80},{-44,-70}}, color={0,127,255}));
connect(conPum.y, gai.u)
annotation (Line(points={{-98,-90},{-82,-90}}, color={0,0,127}));
connect(gai.y, pumDis.m_flow_in)
annotation (Line(points={{-58,-90},{-26,-90},{-26,-60},{-32,-60}}, color={0,0,127}));
connect(dis.TOut, conPum.TMix)
annotation (Line(points={{92,4},{128,4},{128,-112},{-134,-112},{-134,-84},{-122,-84}}, color={0,0,127}));
connect(TIn.T, conPum.TSouIn[1])
annotation (Line(points={{121,-30},{128,-30},{128,-112},{-130,-112},{-130,-90},{-122,-90}}, color={0,0,127}));
connect(TOut.port_b, dis.port_aDisSup)
annotation (Line(points={{26,10},{50,10}}, color={0,127,255}));
connect(TOut.T, conPum.TSouOut[1])
annotation (Line(points={{16,-1},{16,-112},{-126,-112},{-126,-96},{-122,-96}},color={0,0,127}));
{% endraw %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// No components for time series and design data coupling
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// No connections for time series and design data coupling
Original file line number Diff line number Diff line change
@@ -1,16 +1 @@
Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupMaxSet_{{ coupling.id }}(k=38 +
273.15) "Heating water supply temperature set point - Maximum value"
{% raw %}annotation (Placement(transformation(extent={{-120,40},{-100,60}})));
{% endraw %}Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet_{{ coupling.id }}(k=18 + 273.15)
"Chilled water supply temperature set point"
{% raw %}annotation (Placement(transformation(extent={{-120,10},{-100,30}})));
{% endraw %}Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupMinSet_{{ coupling.id }}(k=28
+ 273.15) "Heating water supply temperature set point - Minimum value"
{% raw %}annotation (Placement(transformation(extent={{-120,70},{-100,90}})));
{% endraw %}Buildings.Controls.OBC.CDL.Reals.Sources.Constant THotWatSupSet_{{ coupling.id }}(k=63 + 273.15)
"Hot water supply temperature set point"
{% raw %}annotation (Placement(transformation(extent={{-120,-20},{-100,0}})));
{% endraw %}Buildings.Controls.OBC.CDL.Reals.Sources.Constant TColWat_{{ coupling.id }}(k=15 + 273.15)
"Cold water temperature"
{% raw %}annotation (Placement(transformation(extent={{-120,-50},{-100,-30}})));
{% endraw %}
// No components for time series and network coupling
Original file line number Diff line number Diff line change
@@ -1,16 +1 @@
// Timeseries load and network coupling connections
connect(dis.ports_bCon[{{ sys_params.load_num }}], {{ coupling.load.id }}.port_aSerAmb)
{% raw %}annotation (Line(points={{58,0},{58,6},{46,6},{46,30},{60,30}}, color={0,127,255}));
{% endraw %}connect({{ coupling.load.id }}.port_bSerAmb, dis.ports_aCon[{{ sys_params.load_num }}])
{% raw %}annotation (Line(points={{80,30},{92,30},{92,6},{82,6},{82,0}}, color={0,127,255}));
{% endraw %}connect(THeaWatSupMinSet_{{ coupling.id }}.y, {{ coupling.load.id }}.THeaWatSupMinSet)
{% raw %}annotation (Line(points={{-98,80},{-80,80},{-80,100},{26,100},{26,39},{58,39}}, color={0,0,127}));
{% endraw %}connect(THeaWatSupMaxSet_{{ coupling.id }}.y, {{ coupling.load.id }}.THeaWatSupMaxSet)
{% raw %}annotation (Line(points={{-98,50},{34,50},{34,37},{58,37}}, color={0,0,127}));
{% endraw %}connect(TChiWatSupSet_{{ coupling.id }}.y, {{ coupling.load.id }}.TChiWatSupSet)
{% raw %}annotation (Line(points={{-98,20},{42,20},{42,35},{58,35}}, color={0,0,127}));
{% endraw %}connect(THotWatSupSet_{{ coupling.id }}.y, {{ coupling.load.id }}.THotWatSupSet)
{% raw %}annotation (Line(points={{-98,-10},{-66,-10},{-66,16},{52,16},{52,33},{58,33}}, color={0,0,127}));
{% endraw %}connect(TColWat_{{ coupling.id }}.y, {{ coupling.load.id }}.TColWat)
{% raw %}annotation (Line(points={{-98,-40},{-62,-40},{-62,4},{62,4},{62,18}}, color={0,0,127}));
{% endraw %}
Loading

0 comments on commit 4caaa59

Please sign in to comment.