Skip to content

Commit

Permalink
Merge branch 'master' into gh-pages-custom
Browse files Browse the repository at this point in the history
  • Loading branch information
dhblum committed Aug 28, 2024
2 parents 65bfb8a + 1e37f71 commit dee8f7e
Show file tree
Hide file tree
Showing 265 changed files with 475,254 additions and 379 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ jobs:
- python: 3.9
install: pip install --upgrade pip && pip install pandas==1.2.5 numpy==1.20.2 requests==2.25.1
script: cd testing && make build_jm_image && make test_twozone_apartment_hydronic
- python: 3.9
install: pip install --upgrade pip && pip install pandas==1.2.5 numpy==1.20.2 requests==2.25.1
script: cd testing && travis_wait 90 make test_multizone_office_simple_hydronic_no_compile
- python: 3.9
install: pip install --upgrade pip && pip install pandas==1.2.5 numpy==1.20.2 requests==2.25.1
script: cd testing && make build_jm_image && travis_wait 90 make test_multizone_office_simple_air ARG="-s test_peak_heat_day,test_typical_heat_day"
Expand Down
3 changes: 3 additions & 0 deletions contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Thank you to all who have provided guidance on the development of this software.
- Dave Biagioni, National Renewable Energy Laboratory
- David Blum, Lawrence Berkeley National Laboratory
- Yan Chen, Pacific Northwest National Laboratory
- Roel De Coninck, dnergy
- Iago Cupeiro Figueroa, Cupeiro Sinte, dnergy
- Konstantin Filonenko, University of Southern Denmark
- Gauthier-Clerc Francois, Pure Control
- Valentin Gavan, ENGIE
Expand All @@ -18,6 +20,7 @@ Thank you to all who have provided guidance on the development of this software.
- Nicholas Long, National Renewable Energy Laboratory
- Xing Lu, Pacific Northwest National Laboratory
- Robert Lutes, Pacific Northwest National Laboratory
- Bart Merema, dnergy
- Kefei Mo, Pacific Northwest National Laboratory
- Erik Paulson, Independent
- Matt Robinson, University of Colorado - Boulder
Expand Down
50 changes: 38 additions & 12 deletions data/find_days.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
import pandas as pd
import os
import numpy as np
from matplotlib import pyplot as plt

def find_days(heat, cool, data='simulate', img_name='boptest_bestest_air',
plot = False, peak_cool_restriction_hour=None):
plot=False, cooling_negative=False, peak_cool_restriction_hour=None,
cool_day_low_limit=14, cool_day_high_limit=358,
heat_day_low_limit=14, heat_day_high_limit=358):
'''Find the start and final times for the test case scenarios.
Parameters
Expand All @@ -34,17 +37,38 @@ def find_days(heat, cool, data='simulate', img_name='boptest_bestest_air',
to generate the data.
`path_to_data.csv` indicates path to .csv file with the yearly
simulation data.
Default is `simulate`.
img_name: string
Image name of the container where the simulation is to be
performed.
plot: boolean
Set to True to show an overview of the days found
performed. Used only if data=`simulate`.
plot: boolean, optional
Set to True to show an overview of the days found.
Default is False
cooling_negative: boolean, optional
Set to True if cooling heat flow data is negative in simulation or data file.
Default is False.
peak_cool_restriction_hour: integer, optional
Hour if want peak cooling loads to only be considered equal to or after the hour
each day. This can be useful to avoid including hours with peak
cooling loads due to morning start up, which may lead to the
same peak load for many different days. None will have no restrictions.
Default is None.
cool_day_low_limit: integer, optional
Day below which should not be considered for cooling.
Must be >= 14.
Default = 14.
cool_day_high_limit: integer, optional
Day below which should not be considered for cooling.
Must be <= 358.
Default = 358.
heat_day_low_limit: integer, optional
Day below which should not be considered for heating.
Must be >= 14.
Default = 14.
heat_day_high_limit: integer, optional
Day below which should not be considered for heating.
Must be <= 358.
Default = 358.
Returns
-------
Expand Down Expand Up @@ -89,18 +113,20 @@ def find_days(heat, cool, data='simulate', img_name='boptest_bestest_air',

# Load data
df_raw.index = pd.TimedeltaIndex(df_raw.index.values, unit='s')
if cooling_negative:
df_raw[cool] = -df_raw[cool]
df = df_raw.resample('15T').mean()
df.dropna(axis=0, inplace=True)
# Since assume two-week test period with one-week warmup,
# edges of year are not available to choose from
df_available = df.loc[pd.Timedelta(days=14):pd.Timedelta(days=365-7)]
df_available_cool = df[cool].loc[pd.Timedelta(days=14):pd.Timedelta(days=365-7)]
df_available_cool = df[cool].loc[pd.Timedelta(days=cool_day_low_limit):pd.Timedelta(days=cool_day_high_limit)]
df_cool = df[cool]
if peak_cool_restriction_hour is not None:
# Limit available cooling hours to those after restriction
df_available_cool = df_available_cool[df_available_cool.index.seconds/3600>=peak_cool_restriction_hour]
df_cool = df_cool[df_cool.index.seconds/3600>=peak_cool_restriction_hour]
df_available_heat = df[heat].loc[pd.Timedelta(days=14):pd.Timedelta(days=365-7)]
df_available_heat = df[heat].loc[pd.Timedelta(days=heat_day_low_limit):pd.Timedelta(days=heat_day_high_limit)]
df_heat = df[heat]


Expand Down Expand Up @@ -153,28 +179,28 @@ def find_days(heat, cool, data='simulate', img_name='boptest_bestest_air',
if heat is not None:
plt.figure()
plt.title('Heating load')
plt.plot(time_days, df[heat])
plt.plot(time_days, df_heat)
plt.xlabel('Day of the year')
plt.ylabel('[W]')
plt.axvline(x=peak_heat_day, color='r', label='Peak')
plt.axhline(y=df[heat].max(), color='r', label='_nolegend_')
plt.axhline(y=df_available_heat.max(), color='r', label='_nolegend_')
plt.axvline(x=typical_heat_day, color='r', linestyle='--', label='Typical')
plt.axhline(y=median_heat, color='r', linestyle='--', label='_nolegend_')
plt.legend()
plt.show()

if cool is not None:
plt.figure()
plt.title('Cooling load')
plt.plot(time_days, df[cool])
plt.plot(time_days, df_cool)
plt.xlabel('Day of the year')
plt.ylabel('[W]')
plt.axvline(x=peak_cool_day, color='r', label='Peak')
plt.axhline(y=df[cool].max(), color='r', label='_nolegend_')
plt.axhline(y=df_available_cool.max(), color='r', label='_nolegend_')
plt.axvline(x=typical_cool_day, color='r', linestyle='--', label='Typical')
plt.axhline(y=median_cool, color='r', linestyle='--', label='_nolegend_')
plt.legend()
plt.show()

plt.show()

return days

Expand Down
45 changes: 37 additions & 8 deletions parsing/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
from data.data_manager import Data_Manager
import warnings

def parse_instances(model_path, file_name):
if 'MODELICAPATH' in os.environ:
modelicapath=os.environ['MODELICAPATH']
else:
modelicapath=os.path.abspath('.')

def parse_instances(model_path, file_name, tool='JModelica'):
'''Parse the signal exchange block class instances using fmu xml.
Parameters
Expand All @@ -29,6 +34,9 @@ def parse_instances(model_path, file_name):
file_name : list
Path(s) to modelica file and required libraries not on MODELICAPATH.
Passed to file_name parameter of pymodelica.compile_fmu() in JModelica.
tool : str, optional
FMU compilation tool. "JModelica" or "OCT" supported.
Default is "JModelica".
Returns
-------
Expand All @@ -42,7 +50,12 @@ def parse_instances(model_path, file_name):
'''

# Compile fmu
fmu_path = compile_fmu(model_path, file_name, jvm_args="-Xmx8g", target='cs')
if tool == 'JModelica':
fmu_path = compile_fmu(model_path, file_name, jvm_args="-Xmx8g", target='cs')
elif tool == 'OCT':
fmu_path = compile_fmu(model_path, file_name, modelicapath=modelicapath, jvm_args="-Xmx8g", target='cs')
else:
raise ValueError('Tool {0} unknown.'.format(tool))
# Load fmu
fmu = load_fmu(fmu_path)
# Check version
Expand Down Expand Up @@ -105,7 +118,7 @@ def parse_instances(model_path, file_name):

return instances, signals

def write_wrapper(model_path, file_name, instances):
def write_wrapper(model_path, file_name, instances, tool='JModelica'):
'''Write the wrapper modelica model and export as fmu
Parameters
Expand All @@ -118,6 +131,9 @@ def write_wrapper(model_path, file_name, instances):
instances : dict
Dictionary of overwrite and read block class instance lists.
{'Overwrite': [str], 'Read': [str]}
tool : str, optional
FMU compilation tool. "JModelica" or "OCT" supported.
Default is "JModelica".
Returns
-------
Expand Down Expand Up @@ -179,18 +195,28 @@ def write_wrapper(model_path, file_name, instances):
# End file -- with hard line ending
f.write('end wrapped;\n')
# Export as fmu
fmu_path = compile_fmu('wrapped', [wrapped_path]+file_name, jvm_args="-Xmx8g", target='cs')
if tool == 'JModelica':
fmu_path = compile_fmu('wrapped', [wrapped_path]+file_name, jvm_args="-Xmx8g", target='cs')
elif tool == 'OCT':
fmu_path = compile_fmu('wrapped', [wrapped_path]+file_name, modelicapath=modelicapath, jvm_args="-Xmx8g", target='cs')
else:
raise ValueError('Tool {0} unknown.'.format(tool))
# If there are not, write and export wrapper model
else:
# Warn user
warnings.warn('No signal exchange block instances found in model. Exporting model as is.')
# Compile fmu
fmu_path = compile_fmu(model_path, file_name, jvm_args="-Xmx8g", target='cs')
if tool == 'JModelica':
fmu_path = compile_fmu(model_path, file_name, jvm_args="-Xmx8g", target='cs')
elif tool == 'OCT':
fmu_path = compile_fmu(model_path, file_name, modelicapath=modelicapath, jvm_args="-Xmx8g", target='cs')
else:
raise ValueError('Tool {0} unknown.'.format(tool))
wrapped_path = None

return fmu_path, wrapped_path

def export_fmu(model_path, file_name):
def export_fmu(model_path, file_name, tool='JModelica'):
'''Parse signal exchange blocks and export boptest fmu and kpi json.
Parameters
Expand All @@ -200,6 +226,9 @@ def export_fmu(model_path, file_name):
file_name : list
Path(s) to modelica file and required libraries not on MODELICAPATH.
Passed to file_name parameter of pymodelica.compile_fmu() in JModelica.
tool : str, optional
FMU compilation tool. "JModelica" or "OCT" supported.
Default is "JModelica".
Returns
-------
Expand All @@ -211,9 +240,9 @@ def export_fmu(model_path, file_name):
'''

# Get signal exchange instances and kpi signals
instances, signals = parse_instances(model_path, file_name)
instances, signals = parse_instances(model_path, file_name, tool)
# Write wrapper and export as fmu
fmu_path, _ = write_wrapper(model_path, file_name, instances)
fmu_path, _ = write_wrapper(model_path, file_name, instances, tool)
# Write kpi json
kpi_path = os.path.join(os.getcwd(), 'kpis.json')
with open(kpi_path, 'w') as f:
Expand Down
10 changes: 10 additions & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ Released on xx/xx/xxxx.
- Specify version of scipy to 1.13.0 in test case Dockerfile. This is for [#657](https://github.com/ibpsa/project1-boptest/issues/657).
- Remove javascript controller example. This is for [#664](https://github.com/ibpsa/project1-boptest/issues/664).
- Add a new directory ``/baselines``, containing baseline testing scripts and associated KPI results for the baseline controllers of all the testcases. This is for [#495](https://github.com/ibpsa/project1-boptest/issues/495).
- Add support to ``parsing/parser.py`` for test case compilation using [Modelon's OPTIMICA Compiler Toolkit (OCT)](https://help.modelon.com/latest/reference/oct/). The parser can take arguments ``'JModelica'`` or ``'OCT'``, with ``'JModelica'`` as default. A user still requires access to an OCT license and software on their set up. This is for [#675](https://github.com/ibpsa/project1-boptest/issues/675).

**The following new test cases have been added:**

- ``multizone_office_simple_hydronic``, a 2-zone typical office building in Brussels, Belgium, served by fan-coil units for space heating and cooling, air handling units for space ventilation, an air-source heat pump for hot water production, and an air-cooled chiller for chilled water production. FMU compiled by [OCT](https://help.modelon.com/latest/reference/oct/). This is for [#465](https://github.com/ibpsa/project1-boptest/issues/465).


**The following changes are backwards-compatible, but might change benchmark results:**

- Fix calculation of computational time ratio (``time_rat``) in the case of a test where the test case was initialized after a test or simulation (use of ``/advance``) had already been done using the same test case deployment (i.e. the docker container had not been shutdown first and newly deployed). The wait time between the last ``/advance`` before the new initialization and first ``/advance`` of the new initialization was incorrectly incorporated into the calculation as a control step and has been fixed, resulting in a lower computational time ratio. The extent of impact depends on wait time between tests and control step and number of steps taken in the new test. This is for [#673](https://github.com/ibpsa/project1-boptest/issues/673).

## BOPTEST v0.6.0

Expand Down
3 changes: 3 additions & 0 deletions testcase.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,10 @@ def initialize(self, start_time, warmup_period, end_time=np.inf):
self.fmu.reset()
# Reset simulation data storage
self.__initilize_data()
# Reset computational time ratio timer
self.elapsed_control_time_ratio = np.array([])
if hasattr(self, 'tic_time'):
delattr(self,'tic_time')
# Check if the inputs are valid
try:
start_time = float(start_time)
Expand Down
7 changes: 4 additions & 3 deletions testcases/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ This directory contains test cases for BOPTEST. A summary of available test cas
| ``bestest_air``| BESTEST Case 900 room model with idealized fan coil unit.|**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**:<br />``'peak_heat_day'``, <br />``'typical_heat_day'``, <br />``'peak_cool_day'``, <br />``'typical_cool_day'``, <br />``'mix_day'``|
| ``bestest_hydronic``| BESTEST Case 900 room model with gas boiler and radiator.|**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**: <br />``'peak_heat_day'``, <br />``'typical_heat_day'``|
| ``bestest_hydronic_heat_pump``| BESTEST Case 900 room model, scaled by four in floor area, that uses a heat pump as heating production system and floor heating as heating emission system.|**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**: <br />``'peak_heat_day'``, <br />``'typical_heat_day'``|
| ``twozone_apartment_hydronic``| Low energy consumption two room aparment in Milan. Only heating is considered. The generation system is a heat pump and the emission system is floor heating. |**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**: <br />``'peak_heat_day'``, <br />``'typical_heat_day'``|
| ``multizone_residential_hydronic``| Multi-zone residential hydronic model with gas boiler, radiators, and ideal cooling system. |**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**: <br />``'peak_heat_day'``, <br />``'typical_heat_day'``|
| ``twozone_apartment_hydronic``| Low energy consumption 2 zone apartment in Milan. Only heating is considered. The generation system is a heat pump and the emission system is floor heating. |**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**: <br />``'peak_heat_day'``, <br />``'typical_heat_day'``|
| ``multizone_residential_hydronic``| Multi-zone (8 zones) residential hydronic model with gas boiler, radiators, and ideal cooling system. |**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**: <br />``'peak_heat_day'``, <br />``'typical_heat_day'``|
| ``singlezone_commercial_hydronic``| Single-zone commercial building model representing a university building with district heating source, zone radiator, occupancy based on real data, and air handling unit providing fresh air with CO2 control and heat recovery. |**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**: <br />``'peak_heat_day'``, <br />``'typical_heat_day'``|
| ``multizone_office_simple_air`` | Multi-zone commercial building model based on U.S. DOE medium office building with single-duct VAV with terminal reheat, air-cooled chiller, and air-to-water heat pump.|**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**:<br />``'peak_heat_day'``, <br />``'typical_heat_day'``, <br />``'peak_cool_day'``, <br />``'typical_cool_day'``, <br />``'mix_day'``|
| ``multizone_office_simple_hydronic`` | Multi-zone (2 zones) commercial office building model with fan coil units for space heating and cooling, air handling units for ventilation, with air-to-water heat pump and air-cooled chilled.|**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**:<br />``'peak_heat_day'``, <br />``'typical_heat_day'``, <br />``'peak_cool_day'``, <br />``'typical_cool_day'``, <br />``'mix_day'``|
| ``multizone_office_simple_air`` | Multi-zone (5 zones) commercial building model based on U.S. DOE medium office building with single-duct VAV with terminal reheat, air-cooled chiller, and air-to-water heat pump.|**Electricity Prices**: <br />``'constant'``, <br />``'dynamic'``, <br />``'highly_dynamic'``<br />**Time Periods**:<br />``'peak_heat_day'``, <br />``'typical_heat_day'``, <br />``'peak_cool_day'``, <br />``'typical_cool_day'``, <br />``'mix_day'``|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit dee8f7e

Please sign in to comment.