Skip to content

Commit

Permalink
merge branch bump-om
Browse files Browse the repository at this point in the history
  • Loading branch information
JingWang-CUB committed Nov 11, 2024
2 parents f7f8003 + 76ba8d3 commit aec5cc4
Show file tree
Hide file tree
Showing 16 changed files with 290 additions and 246 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"version": "0.2",
"language": "en",
"words": [
"armhf",
"autoload",
"borefield",
"buildingspy",
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Change Log

## Version 0.8.0

### Exciting New Features 🎉
* Add default cop values for 5G district heat pump efficiencies by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/640
* Support international weather locations by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/654
* Support multiple GHEs in a single district by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/644
* Adds method to process modelica results by @tanushree04 in https://github.com/urbanopt/geojson-modelica-translator/pull/646
* Simplify sys params to closer match reality by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/659
* Templates and tests for horizontal piping modeling by @JingWang-CUB in https://github.com/urbanopt/geojson-modelica-translator/pull/627
* Support single building DES templates by @nllong in https://github.com/urbanopt/geojson-modelica-translator/pull/670

### Other Changes
* Improve cli typing & validation by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/662
* Add detail to Docker setup docs for Windows users by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/643
* Use the correct ETS heat pump COP by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/642
* Use feature ids in load names instead of simple_uuid by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/652
* Remove alfalfa from conftest.py by @nllong in https://github.com/urbanopt/geojson-modelica-translator/pull/665
* Update version of Jinja by @nllong in https://github.com/urbanopt/geojson-modelica-translator/pull/667
* Clean up sys-param code that reads parameters by @vtnate in https://github.com/urbanopt/geojson-modelica-translator/pull/668

**Full Changelog**: https://github.com/urbanopt/geojson-modelica-translator/compare/v0.7.0...v0.8.0

## Version 0.7.0

### Exciting New Features 🎉
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ The building loads can be defined multiple ways depending on the fidelity of the

## Release Instructions

1. Create a branch named `prep-0.x.y Release`
1. Create a branch named `Release 0.x.`
1. Update version in pyproject.toml
2. Update CHANGELOG using GitHub's "Autogenerate Change Log" feature
3. After tests pass, merge branch into develop
4. Create new PR from develop into main named `Release 0.x.y`
5. Using GitHub squash-merge into main
6. From local repo, immediately merge main into develop (as a merge commit) and push. This can only be done with users that have bypass privileges on GitHub.
4. From command line, merge develop into main with: `git checkout main; git pull; git merge --ff-only origin develop; git push`
5. In GitHub, tag the release against main. Copy and paste the changelog entry into the notes. Verify the release is posted to PyPI.
2 changes: 1 addition & 1 deletion geojson_modelica_translator/geojson_modelica_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def __init__(

self._system_parameters = SystemParameters(sys_params_filepath)

geojson_ids = self._system_parameters.get_default("$.buildings.[*].geojson_id", [])
geojson_ids = self._system_parameters.get_param("$.buildings.[*].geojson_id")
self._geojson = UrbanOptGeoJson(geojson_filepath, geojson_ids)

# Use different couplings for each district system type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def add_building(self, urbanopt_building, mapper=None):
# TODO: Abstract out the GeoJSON functionality
if mapper is None:
if self.system_parameters:
for building in self.system_parameters.get_default("$.buildings", []):
for building in self.system_parameters.get_param("$.buildings"):
# Only look at buildings in the sys-param file, not necessarily the entire feature file
if urbanopt_building.feature.properties["id"] == building["geojson_id"]:
try:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,15 +265,17 @@ def post_process(self, scaffold, keep_original_models=False):
],
)

fraction_latent_person = self.system_parameters.get_param(
"buildings.load_model_parameters.rc.fraction_latent_person", default=1.25
)
fraction_latent_person = (
self.system_parameters.get_param("buildings.load_model_parameters.rc.fraction_latent_person") or 1.25
) # Fraction latent of sensible persons load = 0.8 for home, 1.25 for office.

use_moisture_balance = self.system_parameters.get_param(
"buildings.load_model_parameters.rc.use_moisture_balance", default="false"
)
use_moisture_balance = (
self.system_parameters.get_param("buildings.load_model_parameters.rc.use_moisture_balance") or "false"
) # If true, input connector QLat_flow is enabled and room air computes moisture balance.

n_ports = self.system_parameters.get_param("buildings.load_model_parameters.rc.nPorts", default=0)
# TODO: Determine why we are looking for these values in the sys-param file.
# Is this just an allowance for future flexibility?
n_ports = self.system_parameters.get_param("buildings.load_model_parameters.rc.nPorts") or 1

# create a new parameter for fraction latent person
mofile.add_parameter(
Expand Down Expand Up @@ -542,7 +544,6 @@ def post_process(self, scaffold, keep_original_models=False):
self.building_id, "load_model_parameters.rc.temp_setpoint_cooling"
)
),
# FIXME: pick up default value from schema if not specified in system_parameters,
# FYI: Modelica insists on booleans being lowercase, so we need to explicitly set "true" and "false"
"has_liquid_heating": "true"
if self.system_parameters.get_param_by_id(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ within {{ project_name }}.Loads.{{ model_name }};
T_bChiWat_nominal=ets.TChiWatRet_nominal,
facMulHea=10*QHea_flow_nominal/(1.7E5),
facMulCoo=40*QCoo_flow_nominal/(-1.5E5)),
redeclare
Buildings.DHC.ETS.Combined.HeatPumpHeatExchanger
ets(
redeclare Buildings.DHC.ETS.Combined.HeatPumpHeatExchanger ets(
final dT_nominal=dT_nominal,
final TDisWatMin=TDisWatMin,
final TDisWatMax=TDisWatMax,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ model Connection1PipePlugFlow_v
"Model for connecting an agent to the DHC system"
extends Buildings.DHC.Networks.BaseClasses.PartialConnection1Pipe(
tau=5*60,
redeclare replaceable model Model_pipDis =
Buildings.Fluid.FixedResistances.PlugFlowPipe (
redeclare replaceable model Model_pipDis=Buildings.Fluid.FixedResistances.PlugFlowPipe(
final length=lDis,
final dIns=dIns,
final kIns=kIns,
Expand All @@ -15,9 +14,7 @@ model Connection1PipePlugFlow_v
cPip=cPip,
rhoPip=rhoPip,
thickness=thickness),
redeclare replaceable model Model_pipCon =
Buildings.Fluid.FixedResistances.LosslessPipe);

redeclare replaceable model Model_pipCon=Buildings.Fluid.FixedResistances.LosslessPipe);
parameter Modelica.Units.SI.Length dIns
"Thickness of pipe insulation, used to compute R"
annotation (Dialog(group="Pipe"));
Expand All @@ -36,16 +33,17 @@ model Connection1PipePlugFlow_v
"Specific heat of pipe wall material. 2300 for PE, 500 for steel";
parameter Modelica.Units.SI.Density rhoPip=930
"Density of pipe wall material. 930 for PE, 8000 for steel";
parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness";
parameter Modelica.Units.SI.Length thickness=0.0035
"Pipe wall thickness";
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPortDis
"Heat transfer to and from the distribution pipe" annotation (Placement(
transformation(extent={{-110,70},{-90,90}}), iconTransformation(extent={{-60,16},
{-40,36}})));

"Heat transfer to and from the distribution pipe"
annotation (Placement(transformation(extent={{-110,70},{-90,90}}),iconTransformation(extent={{-60,16},{-40,36}})));
equation
connect(pipDis.heatPort, heatPortDis)
connect(pipDis.heatPort,heatPortDis)
annotation (Line(points={{-70,-30},{-70,80},{-100,80}},color={191,0,0}));
annotation (Documentation(revisions="<html>
annotation (
Documentation(
revisions="<html>
<ul>
<li>
March 15, 2024, by David Blum:<br/>
Expand All @@ -58,7 +56,8 @@ December 10, 2023, by Ettore Zanetti:<br/>
First implementation.
</li>
</ul>
</html>", info="<html>
</html>",
info="<html>
<p>
This model represents the supply and return lines to connect an
agent (e.g. an energy transfer station) to a one-pipe main distribution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ def build_from_template(self, output_dir: Path, project_name: str) -> None:
files_to_copy = []

# 1: grab all of the time series files and place them in the proper location
for building in self.system_parameters.get_param("$.buildings[?load_model=time_series]"):
time_series = self.system_parameters.get_param("$.buildings[?load_model=time_series]")
# If this is a dict, then there is only one building
if isinstance(time_series, dict):
time_series = [time_series]

for building in time_series:
building_load_file = Path(building["load_model_parameters"]["time_series"]["filepath"])
files_to_copy.append(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ def build_from_template(self, output_dir: Path, project_name: str) -> None:
files_to_copy = []

# 1: grab all of the time series files and place them in the proper location
for building in self.system_parameters.get_param("$.buildings[?load_model=time_series]"):
# If this is a dict, then there is only one building
time_series = self.system_parameters.get_param("$.buildings[?load_model=time_series]")
if isinstance(time_series, dict):
time_series = [time_series]

for building in time_series:
building_load_file = Path(building["load_model_parameters"]["time_series"]["filepath"])
files_to_copy.append(
{
Expand Down
5 changes: 2 additions & 3 deletions geojson_modelica_translator/modelica/lib/runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ In GMT Runner Version 2.0.0 we detached the OM version from the GMT Runner versi
| GTM Runner Version | OM Version | MSL Version | MBL Version |
| ------------------ | ---------- | ----------- | ----------- |
| 3.0.0 | 1.24.0 | 4.0.0 | 11.0.0 |
| 2.1.0 | 1.24.0 | 4.0.0 | 10.0.0 |
| 2.0.1 | 1.22.1 | 4.0.0 | 10.0.0 |
| 2.0.0 | 1.22.1 | 4.0.0 | 10.0.0 |
| 1.22.1 | 1.22.1 | 4.0.0 | 9.1.1 |
Expand All @@ -42,8 +41,8 @@ In GMT Runner Version 2.0.0 we detached the OM version from the GMT Runner versi
Releasing is only available to individuals with write access to the NREL org. Unfortunately, the NREL org is still
under a free plan resulting in a maximum of 3 users for the entire org, which have already been allocated.

Building for release is a bit different than development since you will need to handle multiple platforms (only supporting
ARM64 and AMD64 as openmodelica does not support 32-bit [only armhf]). See
Building for release is a bit different than development since you will need to handle multiple platforms (that is adding support for armhf to
support OpenModelica as well as AMD64). See
[docker's multi-platform images documentation](https://docs.docker.com/build/building/multi-platform/) on how to configure.

```bash
Expand Down
42 changes: 7 additions & 35 deletions geojson_modelica_translator/system_parameters/system_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,62 +90,34 @@ def resolve_paths(self):
new_path = Path(filepath) / match.value
parse(str(match.full_path)).update(self.param_template, new_path.as_posix())

# def resolve_defaults(self):
# """This method will expand the default data blocks into all the subsequent custom sections. If the value is
# specificed in the custom block then that will be used, otherwise the default value will be replaced"""
# pass

def get_default(self, jsonpath, default=None):
"""Return either the default in the system parameter file, or the specified default.
:param jsonpath: string, raw jsonpath to what parameter was being requested
:param default: variant, default value
:return: value
"""
schema_default = self.get_param(jsonpath, impute_default=False)
return schema_default or default

def get_param(self, jsonpath, data=None, default=None, impute_default=True):
"""Return the parameter(s) from a jsonpath. If the default is not specified, then will attempt to read the
default from the "default" section of the file. If there is no default there, then it will use the value
specified as the argument. It is not recommended to use the argument default as those values will not be
configurable. Argument-based defaults should be used sparingly.
def get_param(self, jsonpath, data=None):
"""Return the parameter(s) from a jsonpath.
:param path: string, period delimited path of the data to retrieve
:param data: dict, (optional) the data to parse
:param default: variant, (optional) value to return if can't find the result
:return: variant, the value from the data
"""
if jsonpath is None or jsonpath == "":
return None

# If this is the first entry into the method, then set the data to the
data = data or self.param_template
matches = parse(jsonpath).find(data)

default_value = default
if impute_default:
default_value = self.get_default(jsonpath, default)

results = []
for index, match in enumerate(matches):
# print(f"Index {index} to update match {match.path} | {match.value} | {match.context}")
if match.value is None:
results.append(default_value)
else:
results.append(match.value)
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
# If only one value, then return that value and not a list of values.
results = results[0]
elif len(results) == 0:
return default_value
return None

# otherwise return the list of values
return results

def get_param_by_id(self, param_id, jsonpath):
"""Return a parameter for a specific id. This is similar to get_param but allows the user
"""Return a parameter for a specific id. This wrapper to get_param allows the user
to constrain the data based on the id.
:param param_id: string, id of the object to look up in the system parameters file
Expand Down
Loading

0 comments on commit aec5cc4

Please sign in to comment.