From 54fc12a7df2336c406e7c760286fda0370541c27 Mon Sep 17 00:00:00 2001 From: Nathan Moore Date: Fri, 21 Feb 2025 15:55:29 -0700 Subject: [PATCH] Revert "comment non-single-ghe tests" This reverts commit afd256e44cfc6ae44713fb4a42ec327e123298b9. --- tests/GMT_Lib/test_gmt_lib.py | 1198 ++++++++--------- tests/GMT_Lib/test_gmt_lib_des.py | 344 ++--- tests/geojson/test_geojson.py | 320 ++--- tests/geojson/test_schemas.py | 98 +- .../test_results_ghp.py | 138 +- .../test_scaffold.py | 52 +- .../test_translator.py | 82 +- .../geojson_modelica_translator/test_utils.py | 34 +- .../management/test_format_modelica_files.py | 58 +- tests/management/test_uo_des.py | 736 +++++----- .../test_chilled_water_plant.py | 118 +- tests/model_connectors/test_chp_system.py | 122 +- .../model_connectors/test_cooling_indirect.py | 82 +- tests/model_connectors/test_diagram_graph.py | 374 ++--- tests/model_connectors/test_district_5g.py | 92 +- .../test_district_cooling_system.py | 114 +- ...st_district_heating_and_cooling_systems.py | 328 ++--- .../test_district_heating_system.py | 116 +- .../test_district_multi_ghe.py | 218 +-- .../model_connectors/test_district_system.py | 114 +- .../test_heated_water_plant.py | 116 +- .../model_connectors/test_heating_indirect.py | 84 +- tests/model_connectors/test_mixed_loads.py | 202 +-- tests/model_connectors/test_spawn.py | 104 +- tests/model_connectors/test_spawn_cooling.py | 118 +- ...wn_district_heating_and_cooling_systems.py | 252 ++-- tests/model_connectors/test_spawn_heating.py | 118 +- tests/model_connectors/test_teaser.py | 102 +- tests/model_connectors/test_teaser_cooling.py | 118 +- ...er_district_heating_and_cooling_systems.py | 254 ++-- tests/model_connectors/test_teaser_heating.py | 118 +- tests/model_connectors/test_time_series_5g.py | 154 +-- .../test_time_series_heating_indirect.py | 156 +-- .../test_time_series_mft_ets.py | 288 ++-- tests/modelica/test_csv_modelica.py | 168 +-- tests/modelica/test_input_parser.py | 352 ++--- tests/modelica/test_modelica_runner.py | 460 +++---- .../test_system_parameters.py | 968 ++++++------- 38 files changed, 4435 insertions(+), 4435 deletions(-) diff --git a/tests/GMT_Lib/test_gmt_lib.py b/tests/GMT_Lib/test_gmt_lib.py index b5ff54baa..01aa594e8 100644 --- a/tests/GMT_Lib/test_gmt_lib.py +++ b/tests/GMT_Lib/test_gmt_lib.py @@ -1,600 +1,600 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path -# from shutil import copyfile - -# import pytest -# from jinja2 import Environment, FileSystemLoader, StrictUndefined - -# from geojson_modelica_translator.modelica.GMT_Lib.DHC.Components.Plants.Heating.boiler_polynomial import ( -# PolynomialBoiler, -# ) -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Conversion.ACACTransformer import ( -# ACACTransformer, -# ) -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Lines.Lines import DistributionLines -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Loads.capacitive import ( -# CapacitiveLoad, -# ) -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Loads.Inductive import ( -# InductiveLoad, -# ) -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.community_pv import ( -# CommunityPV, -# ) -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.generators import Generator -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.grid import Grid -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.wind_turbines import ( -# WindTurbine, -# ) -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Storage.Battery import Battery -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Storage.capacitor import Capacitor -# from geojson_modelica_translator.modelica.GMT_Lib.Electrical.Examples.pv_subsystem import PVSubsystem -# from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from geojson_modelica_translator.utils import linecount - -# PARENT_DIR = Path(__file__).parent -# GMT_LIB_PATH = PARENT_DIR.parent.parent / "geojson_modelica_translator" / "modelica" / "GMT_Lib" -# COOLING_PLANT_PATH = GMT_LIB_PATH / "DHC" / "Components" / "Plants" / "Cooling" -# MICROGRID_PARAMS = PARENT_DIR.parent / "data_shared" / "system_params_microgrid_example.json" - -# env = Environment( -# loader=FileSystemLoader(GMT_LIB_PATH), -# undefined=StrictUndefined, -# variable_start_string="{$", -# variable_end_string="$}", -# ) - -# COOLING_PLANT_PARAMS = { -# "chiller_performance": "Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_York_YT_1055kW_5_96COP_Vanes", -# "plant_type": "Buildings.DHC.Plants.Cooling.ElectricChillerParallel", -# "delta_temp_approach": 3, -# "chw_mass_flow_nominal": 18.3, -# "chw_pressure_drop_nominal": 44800, -# "chiller_water_flow_minimum": 0.03, -# "cw_mass_flow_nominal": 34.7, -# "cw_pressure_drop_nominal": 46200, -# "fan_power": 4999, -# "chw_temp_setpoint": 281.15, -# "cooling_tower_pressure_drop_valve_nominal": 5999, -# "chw_pressure_drop_valve_nominal": 5999, -# "cw_pressure_drop_valve_nominal": 5999, -# } - - -# def test_generate_cooling_plant(snapshot): -# # -- Setup -# template_path = (COOLING_PLANT_PATH / "CoolingPlant.mot").relative_to(GMT_LIB_PATH) - -# # -- Act -# actual = env.get_template(template_path.as_posix()).render(**COOLING_PLANT_PARAMS) - -# # -- Assert -# assert actual == snapshot - - -# def test_build_cooling_plant(): -# # -- Setup -# template_path = (COOLING_PLANT_PATH / "CoolingPlant.mot").relative_to(GMT_LIB_PATH) - -# # -- Act -# output = env.get_template(template_path.as_posix()).render(**COOLING_PLANT_PARAMS) -# package_output_dir = PARENT_DIR / "output" / "Cooling" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# with open(package_output_dir / "CoolingPlant.mo", "w") as f: -# f.write(output) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "CoolingPlant.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_cooling_plant(): -# # -- Setup -# template_path = (COOLING_PLANT_PATH / "CoolingPlant.mot").relative_to(GMT_LIB_PATH) -# output = env.get_template(template_path.as_posix()).render(**COOLING_PLANT_PARAMS) -# package_output_dir = PARENT_DIR / "output" / "Cooling" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# with open(package_output_dir / "CoolingPlant.mo", "w") as f: -# f.write(output) - -# # copy over the script -# copyfile(COOLING_PLANT_PATH / "CoolingPlant.mos", package_output_dir / "CoolingPlant.mos") - -# # -- Act -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# "CoolingPlant", -# file_to_load=package_output_dir / "CoolingPlant.mo", -# file_to_run="CoolingPlant.mo", -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=90, # (in seconds) -# ) - -# # -- Assert -# assert success is True - - -# @pytest.mark.simulation -# def test_simulate_polynomial_boiler(): -# # -- Setup - -# package_output_dir = PARENT_DIR / "output" / "Polynomial_Boiler" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# boiler = PolynomialBoiler(sys_params) -# boiler.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# "BoilerPolynomial", -# file_to_load=package_output_dir / "BoilerPolynomial.mo", -# run_path=package_output_dir, -# start_time=0, -# stop_time=86400, -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "BoilerPolynomial.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_community_pv(): -# # -- Setup - -# package_output_dir = PARENT_DIR / "output" / "CommunityPV" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# cpv = CommunityPV(sys_params) -# cpv.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "PVPanels1.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_community_pv(): -# # -- Setup - -# package_output_dir = PARENT_DIR / "output" / "CommunityPV" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# cpv = CommunityPV(sys_params) -# cpv.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", "PVPanels1", file_to_load=package_output_dir / "PVPanels1.mo", run_path=package_output_dir -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "PVPanels1.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_wind_turbine(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "WindTurbine" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# cpv = WindTurbine(sys_params) -# cpv.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "WindTurbine0.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_wind_turbine(): -# # -- Setup - -# package_output_dir = PARENT_DIR / "output" / "WindTurbine" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# cpv = WindTurbine(sys_params) -# cpv.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# "WindTurbine0", -# file_to_load=package_output_dir / "WindTurbine0.mo", -# run_path=package_output_dir, -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "WindTurbine0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_distribution_lines(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "DistributionLines" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# cpv = DistributionLines(sys_params) -# cpv.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "ACLine0.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_distribution_lines(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "DistributionLines" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# cpv = DistributionLines(sys_params) -# cpv.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", "ACLine0", file_to_load=package_output_dir / "ACLine0.mo", run_path=package_output_dir -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "ACLine0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# @pytest.mark.skip(reason="Capacitors are not yet implemented") -# def test_build_capacitor(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Capacitor" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# cap = Capacitor(sys_params) -# cap.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Capacitor0.mo") > 20 - - -# @pytest.mark.skip(reason="Capacitors are not yet implemented") -# @pytest.mark.simulation -# def test_simulate_capacitor(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Capacitor" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# capacitor = Capacitor(sys_params) -# capacitor.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", "Capacitor0", file_to_load=package_output_dir / "Capacitor0.mo", run_path=package_output_dir -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Capacitor0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_battery(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Battery" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# bat = Battery(sys_params) -# bat.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "AcBattery0.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_battery(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Battery" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# battery = Battery(sys_params) -# battery.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", "AcBattery0", file_to_load=package_output_dir / "AcBattery0.mo", run_path=package_output_dir -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "AcBattery0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_generator(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Generator" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# gen = Generator(sys_params) -# gen.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Generator0.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_generator(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Generator" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# generator = Generator(sys_params) -# generator.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", "Generator0", file_to_load=package_output_dir / "Generator0.mo", run_path=package_output_dir -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Generator0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_grid(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Grid" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# grid = Grid(sys_params) -# grid.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Grid.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_grid(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Grid" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# grid = Grid(sys_params) -# grid.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", "Grid", file_to_load=package_output_dir / "Grid.mo", run_path=package_output_dir -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Grid.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_capacitive_load(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Capacitive" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# capacitive = CapacitiveLoad(sys_params) -# capacitive.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Capacitive0.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_capacitive_load(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Capacitive" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# capacitive = CapacitiveLoad(sys_params) -# capacitive.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# "Capacitive0", -# file_to_load=package_output_dir / "Capacitive0.mo", -# run_path=package_output_dir, -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Capacitive0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_inductive_load(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Inductive" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# inductive = InductiveLoad(sys_params) -# inductive.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Inductive0.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_inductive_load(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "Inductive" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# inductive = InductiveLoad(sys_params) -# inductive.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# "Inductive0", -# file_to_load=package_output_dir / "Inductive0.mo", -# run_path=package_output_dir, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=90, # (in seconds) -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "Inductive0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_pv_subsystem(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "PVSubsystem" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# pv_subsystem = PVSubsystem(sys_params) -# pv_subsystem.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "PVsubsystem.mo") > 20 - - -# @pytest.mark.simulation -# def test_simulate_pv_subsystem(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "PVsubsystem" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# # Build the model -# pv_subsystem = PVSubsystem(sys_params) -# pv_subsystem.build_from_template(package_output_dir) - -# # Run the simulation -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# "PVsubsystem", -# file_to_load=package_output_dir / "PVsubsystem.mo", -# run_path=package_output_dir, -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "PVsubsystem.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# def test_build_transformer(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "ACACTransformer" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# transformer = ACACTransformer(sys_params) -# transformer.build_from_template(package_output_dir) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "ACACTransformer0.mo") > 20 - - +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path +from shutil import copyfile + +import pytest +from jinja2 import Environment, FileSystemLoader, StrictUndefined + +from geojson_modelica_translator.modelica.GMT_Lib.DHC.Components.Plants.Heating.boiler_polynomial import ( + PolynomialBoiler, +) +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Conversion.ACACTransformer import ( + ACACTransformer, +) +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Lines.Lines import DistributionLines +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Loads.capacitive import ( + CapacitiveLoad, +) +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Loads.Inductive import ( + InductiveLoad, +) +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.community_pv import ( + CommunityPV, +) +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.generators import Generator +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.grid import Grid +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Sources.wind_turbines import ( + WindTurbine, +) +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Storage.Battery import Battery +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.AC.ThreePhasesBalanced.Storage.capacitor import Capacitor +from geojson_modelica_translator.modelica.GMT_Lib.Electrical.Examples.pv_subsystem import PVSubsystem +from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from geojson_modelica_translator.utils import linecount + +PARENT_DIR = Path(__file__).parent +GMT_LIB_PATH = PARENT_DIR.parent.parent / "geojson_modelica_translator" / "modelica" / "GMT_Lib" +COOLING_PLANT_PATH = GMT_LIB_PATH / "DHC" / "Components" / "Plants" / "Cooling" +MICROGRID_PARAMS = PARENT_DIR.parent / "data_shared" / "system_params_microgrid_example.json" + +env = Environment( + loader=FileSystemLoader(GMT_LIB_PATH), + undefined=StrictUndefined, + variable_start_string="{$", + variable_end_string="$}", +) + +COOLING_PLANT_PARAMS = { + "chiller_performance": "Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_York_YT_1055kW_5_96COP_Vanes", + "plant_type": "Buildings.DHC.Plants.Cooling.ElectricChillerParallel", + "delta_temp_approach": 3, + "chw_mass_flow_nominal": 18.3, + "chw_pressure_drop_nominal": 44800, + "chiller_water_flow_minimum": 0.03, + "cw_mass_flow_nominal": 34.7, + "cw_pressure_drop_nominal": 46200, + "fan_power": 4999, + "chw_temp_setpoint": 281.15, + "cooling_tower_pressure_drop_valve_nominal": 5999, + "chw_pressure_drop_valve_nominal": 5999, + "cw_pressure_drop_valve_nominal": 5999, +} + + +def test_generate_cooling_plant(snapshot): + # -- Setup + template_path = (COOLING_PLANT_PATH / "CoolingPlant.mot").relative_to(GMT_LIB_PATH) + + # -- Act + actual = env.get_template(template_path.as_posix()).render(**COOLING_PLANT_PARAMS) + + # -- Assert + assert actual == snapshot + + +def test_build_cooling_plant(): + # -- Setup + template_path = (COOLING_PLANT_PATH / "CoolingPlant.mot").relative_to(GMT_LIB_PATH) + + # -- Act + output = env.get_template(template_path.as_posix()).render(**COOLING_PLANT_PARAMS) + package_output_dir = PARENT_DIR / "output" / "Cooling" + package_output_dir.mkdir(parents=True, exist_ok=True) + with open(package_output_dir / "CoolingPlant.mo", "w") as f: + f.write(output) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "CoolingPlant.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_cooling_plant(): + # -- Setup + template_path = (COOLING_PLANT_PATH / "CoolingPlant.mot").relative_to(GMT_LIB_PATH) + output = env.get_template(template_path.as_posix()).render(**COOLING_PLANT_PARAMS) + package_output_dir = PARENT_DIR / "output" / "Cooling" + package_output_dir.mkdir(parents=True, exist_ok=True) + with open(package_output_dir / "CoolingPlant.mo", "w") as f: + f.write(output) + + # copy over the script + copyfile(COOLING_PLANT_PATH / "CoolingPlant.mos", package_output_dir / "CoolingPlant.mos") + + # -- Act + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + "CoolingPlant", + file_to_load=package_output_dir / "CoolingPlant.mo", + file_to_run="CoolingPlant.mo", + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=90, # (in seconds) + ) + + # -- Assert + assert success is True + + +@pytest.mark.simulation +def test_simulate_polynomial_boiler(): + # -- Setup + + package_output_dir = PARENT_DIR / "output" / "Polynomial_Boiler" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + boiler = PolynomialBoiler(sys_params) + boiler.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + "BoilerPolynomial", + file_to_load=package_output_dir / "BoilerPolynomial.mo", + run_path=package_output_dir, + start_time=0, + stop_time=86400, + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "BoilerPolynomial.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_community_pv(): + # -- Setup + + package_output_dir = PARENT_DIR / "output" / "CommunityPV" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + cpv = CommunityPV(sys_params) + cpv.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "PVPanels1.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_community_pv(): + # -- Setup + + package_output_dir = PARENT_DIR / "output" / "CommunityPV" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + cpv = CommunityPV(sys_params) + cpv.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", "PVPanels1", file_to_load=package_output_dir / "PVPanels1.mo", run_path=package_output_dir + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "PVPanels1.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_wind_turbine(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "WindTurbine" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + cpv = WindTurbine(sys_params) + cpv.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "WindTurbine0.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_wind_turbine(): + # -- Setup + + package_output_dir = PARENT_DIR / "output" / "WindTurbine" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + cpv = WindTurbine(sys_params) + cpv.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + "WindTurbine0", + file_to_load=package_output_dir / "WindTurbine0.mo", + run_path=package_output_dir, + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "WindTurbine0.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_distribution_lines(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "DistributionLines" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + cpv = DistributionLines(sys_params) + cpv.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "ACLine0.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_distribution_lines(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "DistributionLines" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + cpv = DistributionLines(sys_params) + cpv.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", "ACLine0", file_to_load=package_output_dir / "ACLine0.mo", run_path=package_output_dir + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "ACLine0.mo") > 20 + # Did the simulation run? + assert success is True + + +@pytest.mark.skip(reason="Capacitors are not yet implemented") +def test_build_capacitor(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Capacitor" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + cap = Capacitor(sys_params) + cap.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Capacitor0.mo") > 20 + + +@pytest.mark.skip(reason="Capacitors are not yet implemented") +@pytest.mark.simulation +def test_simulate_capacitor(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Capacitor" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + capacitor = Capacitor(sys_params) + capacitor.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", "Capacitor0", file_to_load=package_output_dir / "Capacitor0.mo", run_path=package_output_dir + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Capacitor0.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_battery(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Battery" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + bat = Battery(sys_params) + bat.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "AcBattery0.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_battery(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Battery" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + battery = Battery(sys_params) + battery.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", "AcBattery0", file_to_load=package_output_dir / "AcBattery0.mo", run_path=package_output_dir + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "AcBattery0.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_generator(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Generator" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + gen = Generator(sys_params) + gen.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Generator0.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_generator(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Generator" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + generator = Generator(sys_params) + generator.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", "Generator0", file_to_load=package_output_dir / "Generator0.mo", run_path=package_output_dir + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Generator0.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_grid(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Grid" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + grid = Grid(sys_params) + grid.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Grid.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_grid(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Grid" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + grid = Grid(sys_params) + grid.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", "Grid", file_to_load=package_output_dir / "Grid.mo", run_path=package_output_dir + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Grid.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_capacitive_load(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Capacitive" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + capacitive = CapacitiveLoad(sys_params) + capacitive.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Capacitive0.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_capacitive_load(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Capacitive" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + capacitive = CapacitiveLoad(sys_params) + capacitive.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + "Capacitive0", + file_to_load=package_output_dir / "Capacitive0.mo", + run_path=package_output_dir, + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Capacitive0.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_inductive_load(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Inductive" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + inductive = InductiveLoad(sys_params) + inductive.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Inductive0.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_inductive_load(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "Inductive" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + inductive = InductiveLoad(sys_params) + inductive.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + "Inductive0", + file_to_load=package_output_dir / "Inductive0.mo", + run_path=package_output_dir, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=90, # (in seconds) + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "Inductive0.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_pv_subsystem(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "PVSubsystem" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + pv_subsystem = PVSubsystem(sys_params) + pv_subsystem.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "PVsubsystem.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_pv_subsystem(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "PVsubsystem" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + # Build the model + pv_subsystem = PVSubsystem(sys_params) + pv_subsystem.build_from_template(package_output_dir) + + # Run the simulation + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + "PVsubsystem", + file_to_load=package_output_dir / "PVsubsystem.mo", + run_path=package_output_dir, + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "PVsubsystem.mo") > 20 + # Did the simulation run? + assert success is True + + +def test_build_transformer(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "ACACTransformer" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + transformer = ACACTransformer(sys_params) + transformer.build_from_template(package_output_dir) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "ACACTransformer0.mo") > 20 + + +@pytest.mark.simulation +def test_simulate_transformer(): + # -- Setup + package_output_dir = PARENT_DIR / "output" / "ACACTransformer" + package_output_dir.mkdir(parents=True, exist_ok=True) + sys_params = SystemParameters(MICROGRID_PARAMS) + + # -- Act + transformer = ACACTransformer(sys_params) + transformer.build_from_template(package_output_dir) + + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + "ACACTransformer", + file_to_load=package_output_dir / "ACACTransformer0.mo", + run_path=package_output_dir, + ) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / "ACACTransformer0.mo") > 20 + # Did the simulation run? + assert success is True + + +# Keeping the code below because it may come back and this was a weird issue. # @pytest.mark.simulation -# def test_simulate_transformer(): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" / "ACACTransformer" -# package_output_dir.mkdir(parents=True, exist_ok=True) -# sys_params = SystemParameters(MICROGRID_PARAMS) - -# # -- Act -# transformer = ACACTransformer(sys_params) -# transformer.build_from_template(package_output_dir) - -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# "ACACTransformer", -# file_to_load=package_output_dir / "ACACTransformer0.mo", -# run_path=package_output_dir, -# ) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / "ACACTransformer0.mo") > 20 -# # Did the simulation run? -# assert success is True - - -# # Keeping the code below because it may come back and this was a weird issue. -# # @pytest.mark.simulation -# # def test_stub_mbl_v9_with_not_msl_v4(): -# # """Need to have a stub where mbl_v9 is selected that is simulatable (with -# # MSV V3.2) in order to not create a failed pytest command with exit code 5.""" -# # assert False is not True +# def test_stub_mbl_v9_with_not_msl_v4(): +# """Need to have a stub where mbl_v9 is selected that is simulatable (with +# MSV V3.2) in order to not create a failed pytest command with exit code 5.""" +# assert False is not True diff --git a/tests/GMT_Lib/test_gmt_lib_des.py b/tests/GMT_Lib/test_gmt_lib_des.py index 8ff34b2b6..36850d557 100644 --- a/tests/GMT_Lib/test_gmt_lib_des.py +++ b/tests/GMT_Lib/test_gmt_lib_des.py @@ -1,172 +1,172 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import unittest -# from pathlib import Path -# from shutil import rmtree - -# import pytest -# from jinja2 import Environment, FileSystemLoader, StrictUndefined - -# from geojson_modelica_translator.modelica.GMT_Lib.DHC.DHC_5G_waste_heat_GHX import DHC5GWasteHeatAndGHX -# from geojson_modelica_translator.modelica.GMT_Lib.DHC.DHC_5G_waste_heat_GHX_variable import DHC5GWasteHeatAndGHXVariable -# from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from geojson_modelica_translator.utils import linecount - -# PARENT_DIR = Path(__file__).parent -# GMT_LIB_PATH = PARENT_DIR.parent.parent / "geojson_modelica_translator" / "modelica" / "GMT_Lib" -# DES_PARAMS = PARENT_DIR.parent / "data_shared" / "system_params_des_5g.json" - -# env = Environment( -# loader=FileSystemLoader(GMT_LIB_PATH), -# undefined=StrictUndefined, -# variable_start_string="{$", -# variable_end_string="$}", -# ) - - -# class GmtLibDesTest(unittest.TestCase): -# @pytest.mark.simulation -# def test_5G_des_waste_heat_and_ghx(self): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" -# package_name = "DES_5G" -# if (package_output_dir / package_name).exists(): -# rmtree(package_output_dir / package_name) -# sys_params = SystemParameters(DES_PARAMS) - -# # -- Act -# cpv = DHC5GWasteHeatAndGHX(sys_params) -# cpv.build_from_template(package_output_dir, package_name) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 - -# # Test to make sure that a zero SWH peak is set to a minimum value. -# # Otherwise, Modelica will error out. -# with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: -# assert "#Peak water heating load = 7714.5 Watts" in f.read() - -# # # -- Act - with simulation -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# f"{package_name}.Districts.district", -# file_to_load=package_output_dir / package_name / "package.mo", -# run_path=package_output_dir / package_name, -# start_time=0, -# stop_time=86400, -# ) - -# assert success is True - -# @pytest.mark.dymola -# def test_5G_des_waste_heat_and_ghx_dymola(self): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" -# package_name = "DES_5G_Dymola" -# if (package_output_dir / package_name).exists(): -# rmtree(package_output_dir / package_name) -# sys_params = SystemParameters(DES_PARAMS) - -# # -- Act -# cpv = DHC5GWasteHeatAndGHX(sys_params) -# cpv.build_from_template(package_output_dir, package_name) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 - -# # Test to make sure that a zero SWH peak is set to a minimum value. -# # Otherwise, Modelica will error out. -# with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: -# assert "#Peak water heating load = 7714.5 Watts" in f.read() - -# # -- Act - with simulation -# runner = ModelicaRunner() -# success, _ = runner.run_in_dymola( -# "simulate", -# f"{package_name}.Districts.district", -# file_to_load=package_output_dir / package_name, -# run_path=package_output_dir / package_name, -# start_time=0, -# stop_time=86400, -# step_size=300, -# debug=True, -# ) - -# assert success is True - -# @pytest.mark.simulation -# def test_5G_des_waste_heat_and_ghx_variable(self): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" -# package_name = "DES_5G_Variable" -# if (package_output_dir / package_name).exists(): -# rmtree(package_output_dir / package_name) -# sys_params = SystemParameters(DES_PARAMS) - -# # -- Act -# cpv = DHC5GWasteHeatAndGHXVariable(sys_params) -# cpv.build_from_template(package_output_dir, package_name) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 - -# # Test to make sure that a zero SWH peak is set to a minimum value. -# # Otherwise, Modelica will error out. -# with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: -# assert "#Peak water heating load = 7714.5 Watts" in f.read() - -# # # -- Act - with simulation -# runner = ModelicaRunner() -# success, _ = runner.run_in_docker( -# "compile_and_run", -# f"{package_name}.Districts.district", -# file_to_load=package_output_dir / package_name / "package.mo", -# run_path=package_output_dir / package_name, -# start_time=0, -# stop_time=86400, -# ) - -# assert success is True - -# @pytest.mark.dymola -# def test_5G_des_waste_heat_and_ghx_variable_dymola(self): -# # -- Setup -# package_output_dir = PARENT_DIR / "output" -# package_name = "DES_5G_Variable_Dymola" -# if (package_output_dir / package_name).exists(): -# rmtree(package_output_dir / package_name) -# sys_params = SystemParameters(DES_PARAMS) - -# # -- Act -# cpv = DHC5GWasteHeatAndGHXVariable(sys_params) -# cpv.build_from_template(package_output_dir, package_name) - -# # -- Assert -# # Did the mofile get created? -# assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 - -# # Test to make sure that a zero SWH peak is set to a minimum value. -# # Otherwise, Modelica will error out. -# with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: -# assert "#Peak water heating load = 7714.5 Watts" in f.read() - -# # # -- Act - with simulation -# runner = ModelicaRunner() -# success, _ = runner.run_in_dymola( -# "simulate", -# f"{package_name}.Districts.district", -# file_to_load=package_output_dir / package_name, -# run_path=package_output_dir / package_name, -# start_time=0, -# stop_time=86400, -# step_size=300, -# debug=True, -# ) - -# assert success is True +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import unittest +from pathlib import Path +from shutil import rmtree + +import pytest +from jinja2 import Environment, FileSystemLoader, StrictUndefined + +from geojson_modelica_translator.modelica.GMT_Lib.DHC.DHC_5G_waste_heat_GHX import DHC5GWasteHeatAndGHX +from geojson_modelica_translator.modelica.GMT_Lib.DHC.DHC_5G_waste_heat_GHX_variable import DHC5GWasteHeatAndGHXVariable +from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from geojson_modelica_translator.utils import linecount + +PARENT_DIR = Path(__file__).parent +GMT_LIB_PATH = PARENT_DIR.parent.parent / "geojson_modelica_translator" / "modelica" / "GMT_Lib" +DES_PARAMS = PARENT_DIR.parent / "data_shared" / "system_params_des_5g.json" + +env = Environment( + loader=FileSystemLoader(GMT_LIB_PATH), + undefined=StrictUndefined, + variable_start_string="{$", + variable_end_string="$}", +) + + +class GmtLibDesTest(unittest.TestCase): + @pytest.mark.simulation + def test_5G_des_waste_heat_and_ghx(self): + # -- Setup + package_output_dir = PARENT_DIR / "output" + package_name = "DES_5G" + if (package_output_dir / package_name).exists(): + rmtree(package_output_dir / package_name) + sys_params = SystemParameters(DES_PARAMS) + + # -- Act + cpv = DHC5GWasteHeatAndGHX(sys_params) + cpv.build_from_template(package_output_dir, package_name) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 + + # Test to make sure that a zero SWH peak is set to a minimum value. + # Otherwise, Modelica will error out. + with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: + assert "#Peak water heating load = 7714.5 Watts" in f.read() + + # # -- Act - with simulation + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + f"{package_name}.Districts.district", + file_to_load=package_output_dir / package_name / "package.mo", + run_path=package_output_dir / package_name, + start_time=0, + stop_time=86400, + ) + + assert success is True + + @pytest.mark.dymola + def test_5G_des_waste_heat_and_ghx_dymola(self): + # -- Setup + package_output_dir = PARENT_DIR / "output" + package_name = "DES_5G_Dymola" + if (package_output_dir / package_name).exists(): + rmtree(package_output_dir / package_name) + sys_params = SystemParameters(DES_PARAMS) + + # -- Act + cpv = DHC5GWasteHeatAndGHX(sys_params) + cpv.build_from_template(package_output_dir, package_name) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 + + # Test to make sure that a zero SWH peak is set to a minimum value. + # Otherwise, Modelica will error out. + with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: + assert "#Peak water heating load = 7714.5 Watts" in f.read() + + # -- Act - with simulation + runner = ModelicaRunner() + success, _ = runner.run_in_dymola( + "simulate", + f"{package_name}.Districts.district", + file_to_load=package_output_dir / package_name, + run_path=package_output_dir / package_name, + start_time=0, + stop_time=86400, + step_size=300, + debug=True, + ) + + assert success is True + + @pytest.mark.simulation + def test_5G_des_waste_heat_and_ghx_variable(self): + # -- Setup + package_output_dir = PARENT_DIR / "output" + package_name = "DES_5G_Variable" + if (package_output_dir / package_name).exists(): + rmtree(package_output_dir / package_name) + sys_params = SystemParameters(DES_PARAMS) + + # -- Act + cpv = DHC5GWasteHeatAndGHXVariable(sys_params) + cpv.build_from_template(package_output_dir, package_name) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 + + # Test to make sure that a zero SWH peak is set to a minimum value. + # Otherwise, Modelica will error out. + with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: + assert "#Peak water heating load = 7714.5 Watts" in f.read() + + # # -- Act - with simulation + runner = ModelicaRunner() + success, _ = runner.run_in_docker( + "compile_and_run", + f"{package_name}.Districts.district", + file_to_load=package_output_dir / package_name / "package.mo", + run_path=package_output_dir / package_name, + start_time=0, + stop_time=86400, + ) + + assert success is True + + @pytest.mark.dymola + def test_5G_des_waste_heat_and_ghx_variable_dymola(self): + # -- Setup + package_output_dir = PARENT_DIR / "output" + package_name = "DES_5G_Variable_Dymola" + if (package_output_dir / package_name).exists(): + rmtree(package_output_dir / package_name) + sys_params = SystemParameters(DES_PARAMS) + + # -- Act + cpv = DHC5GWasteHeatAndGHXVariable(sys_params) + cpv.build_from_template(package_output_dir, package_name) + + # -- Assert + # Did the mofile get created? + assert linecount(package_output_dir / package_name / "Districts" / "district.mo") > 20 + + # Test to make sure that a zero SWH peak is set to a minimum value. + # Otherwise, Modelica will error out. + with open(package_output_dir / package_name / "Resources" / "Data" / "Districts" / "8" / "B11.mos") as f: + assert "#Peak water heating load = 7714.5 Watts" in f.read() + + # # -- Act - with simulation + runner = ModelicaRunner() + success, _ = runner.run_in_dymola( + "simulate", + f"{package_name}.Districts.district", + file_to_load=package_output_dir / package_name, + run_path=package_output_dir / package_name, + start_time=0, + stop_time=86400, + step_size=300, + debug=True, + ) + + assert success is True diff --git a/tests/geojson/test_geojson.py b/tests/geojson/test_geojson.py index 58c0234b7..651e478db 100644 --- a/tests/geojson/test_geojson.py +++ b/tests/geojson/test_geojson.py @@ -1,160 +1,160 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path -# from unittest import TestCase - -# import pytest - -# from geojson_modelica_translator.geojson.urbanopt_geojson import GeoJsonValidationError, UrbanOptGeoJson - - -# class GeoJSONTest(TestCase): -# def setUp(self): -# self.data_dir = Path(__file__).parent / "data" -# self.output_dir = Path(__file__).parent / "output" -# if not self.output_dir.exists(): -# self.output_dir.mkdir(exist_ok=True) - -# def test_load_geojson(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# assert json.data is not None -# assert len(json.data.features) == 4 - -# def test_missing_file(self): -# fn = "non-existent-path" -# with pytest.raises(GeoJsonValidationError, match=f"URBANopt GeoJSON file does not exist: {fn}"): -# UrbanOptGeoJson(fn) - -# def test_valid_instance(self): -# """No exception should be raised when the geojson file is valid""" -# filename = self.data_dir / "geojson_1.json" -# assert UrbanOptGeoJson(filename) - -# def test_validate(self): -# filename = self.data_dir / "geojson_1_invalid.json" -# with pytest.raises(GeoJsonValidationError, match="is not valid under any of the given schemas"): -# UrbanOptGeoJson(filename) - -# def test_get_all_features(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# feature_properties = json.get_feature("$.features.[*].properties") -# assert len(feature_properties) == 4 -# # Check that the first feature has the expected properties -# assert feature_properties[0]["floor_height"] == 9 - -# def test_get_feature(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# feature = json.get_feature("$.features[1]") -# assert feature["properties"]["floor_height"] == 3 - -# def test_get_feature_invalid(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# with pytest.raises(KeyError, match="No matches found"): -# json.get_feature("$.features[4]") - -# def test_get_feature_by_id(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# feature = json.get_feature_by_id("5a7229e737f4de77124f946d") -# assert feature["properties"]["footprint_area"] == 8612 - -# def test_get_feature_by_id_invalid(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# with pytest.raises(KeyError, match="No matches found"): -# json.get_feature_by_id("non-existent-id") - -# def test_get_feature_by_id_missing(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# with pytest.raises(SystemExit): -# json.get_feature_by_id() - -# def test_get_building_paths(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# building_paths = json.get_building_paths(scenario_name="baseline_test") -# assert len(building_paths) == 3 -# # Check that the building paths end with the dir of the building_id -# assert building_paths[0].stem == "5a6b99ec37f4de7f94020090" -# assert building_paths[1].stem == "5a72287837f4de77124f946a" -# assert building_paths[2].stem == "5a7229e737f4de77124f946d" -# # Check that the correct error is raised if the path doesn't exist -# with pytest.raises(FileNotFoundError, match="File not found"): -# json.get_building_paths(scenario_name="baseline") - -# def test_get_building_ids(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# building_names = json.get_building_names() -# assert len(building_names) == 3 -# assert building_names[0] == "Medium Office" - -# def test_get_buildings(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# buildings = json.get_buildings(ids=None) -# assert len(buildings) == 3 -# assert buildings[2]["properties"]["floor_area"] == 34448 - -# def test_get_building_properties_by_id(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# building_properties = json.get_building_properties_by_id("5a72287837f4de77124f946a") -# assert building_properties["floor_area"] == 24567 - -# # These no longer throw exceptions, they just write to the log file. -# # def test_get_meters_for_building(self): -# # filename = self.data_dir / "geojson_1.json" -# # json = UrbanOptGeoJson(filename) -# # with pytest.raises(KeyError, match="No meters found"): -# # json.get_meters_for_building("5a72287837f4de77124f946a") - -# # def test_get_meter_readings_for_building(self): -# # filename = self.data_dir / "geojson_1.json" -# # json = UrbanOptGeoJson(filename) -# # with pytest.raises(KeyError, match="No meter readings found"): -# # json.get_meter_readings_for_building(building_id="5a72287837f4de77124f946a", meter_type="Electricity") - -# # def test_get_monthly_readings(self): -# # filename = self.data_dir / "geojson_1.json" -# # json = UrbanOptGeoJson(filename) -# # with pytest.raises(KeyError, match="No monthly readings found"): -# # json.get_monthly_readings(building_id="5a72287837f4de77124f946a") - -# def test_set_property_on_building_id(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# building_id = "5a72287837f4de77124f946a" -# property_name = "floor_area" -# property_value = 12345 -# json.set_property_on_building_id(building_id, property_name, property_value) -# assert json.get_building_properties_by_id(building_id)[property_name] == property_value - -# def test_get_property_by_building_id(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# building_id = "5a72287837f4de77124f946a" -# property_name = "building_type" -# assert json.get_property_by_building_id(building_id, property_name) == "Retail other than mall" - -# def test_get_site_lat_lon_none(self): -# filename = self.data_dir / "geojson_1.json" -# json = UrbanOptGeoJson(filename) -# assert json.get_site_lat_lon() is None - -# def test_get_site_lat_lon(self): -# filename = ( -# self.data_dir.parent.parent -# / "model_connectors" -# / "data" -# / "sdk_output_skeleton_13_buildings" -# / "exportGeo.json" -# ) -# json = UrbanOptGeoJson(filename) -# assert json.get_site_lat_lon() == [42.816772, -78.849485] +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path +from unittest import TestCase + +import pytest + +from geojson_modelica_translator.geojson.urbanopt_geojson import GeoJsonValidationError, UrbanOptGeoJson + + +class GeoJSONTest(TestCase): + def setUp(self): + self.data_dir = Path(__file__).parent / "data" + self.output_dir = Path(__file__).parent / "output" + if not self.output_dir.exists(): + self.output_dir.mkdir(exist_ok=True) + + def test_load_geojson(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + assert json.data is not None + assert len(json.data.features) == 4 + + def test_missing_file(self): + fn = "non-existent-path" + with pytest.raises(GeoJsonValidationError, match=f"URBANopt GeoJSON file does not exist: {fn}"): + UrbanOptGeoJson(fn) + + def test_valid_instance(self): + """No exception should be raised when the geojson file is valid""" + filename = self.data_dir / "geojson_1.json" + assert UrbanOptGeoJson(filename) + + def test_validate(self): + filename = self.data_dir / "geojson_1_invalid.json" + with pytest.raises(GeoJsonValidationError, match="is not valid under any of the given schemas"): + UrbanOptGeoJson(filename) + + def test_get_all_features(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + feature_properties = json.get_feature("$.features.[*].properties") + assert len(feature_properties) == 4 + # Check that the first feature has the expected properties + assert feature_properties[0]["floor_height"] == 9 + + def test_get_feature(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + feature = json.get_feature("$.features[1]") + assert feature["properties"]["floor_height"] == 3 + + def test_get_feature_invalid(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + with pytest.raises(KeyError, match="No matches found"): + json.get_feature("$.features[4]") + + def test_get_feature_by_id(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + feature = json.get_feature_by_id("5a7229e737f4de77124f946d") + assert feature["properties"]["footprint_area"] == 8612 + + def test_get_feature_by_id_invalid(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + with pytest.raises(KeyError, match="No matches found"): + json.get_feature_by_id("non-existent-id") + + def test_get_feature_by_id_missing(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + with pytest.raises(SystemExit): + json.get_feature_by_id() + + def test_get_building_paths(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + building_paths = json.get_building_paths(scenario_name="baseline_test") + assert len(building_paths) == 3 + # Check that the building paths end with the dir of the building_id + assert building_paths[0].stem == "5a6b99ec37f4de7f94020090" + assert building_paths[1].stem == "5a72287837f4de77124f946a" + assert building_paths[2].stem == "5a7229e737f4de77124f946d" + # Check that the correct error is raised if the path doesn't exist + with pytest.raises(FileNotFoundError, match="File not found"): + json.get_building_paths(scenario_name="baseline") + + def test_get_building_ids(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + building_names = json.get_building_names() + assert len(building_names) == 3 + assert building_names[0] == "Medium Office" + + def test_get_buildings(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + buildings = json.get_buildings(ids=None) + assert len(buildings) == 3 + assert buildings[2]["properties"]["floor_area"] == 34448 + + def test_get_building_properties_by_id(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + building_properties = json.get_building_properties_by_id("5a72287837f4de77124f946a") + assert building_properties["floor_area"] == 24567 + + # These no longer throw exceptions, they just write to the log file. + # def test_get_meters_for_building(self): + # filename = self.data_dir / "geojson_1.json" + # json = UrbanOptGeoJson(filename) + # with pytest.raises(KeyError, match="No meters found"): + # json.get_meters_for_building("5a72287837f4de77124f946a") + + # def test_get_meter_readings_for_building(self): + # filename = self.data_dir / "geojson_1.json" + # json = UrbanOptGeoJson(filename) + # with pytest.raises(KeyError, match="No meter readings found"): + # json.get_meter_readings_for_building(building_id="5a72287837f4de77124f946a", meter_type="Electricity") + + # def test_get_monthly_readings(self): + # filename = self.data_dir / "geojson_1.json" + # json = UrbanOptGeoJson(filename) + # with pytest.raises(KeyError, match="No monthly readings found"): + # json.get_monthly_readings(building_id="5a72287837f4de77124f946a") + + def test_set_property_on_building_id(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + building_id = "5a72287837f4de77124f946a" + property_name = "floor_area" + property_value = 12345 + json.set_property_on_building_id(building_id, property_name, property_value) + assert json.get_building_properties_by_id(building_id)[property_name] == property_value + + def test_get_property_by_building_id(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + building_id = "5a72287837f4de77124f946a" + property_name = "building_type" + assert json.get_property_by_building_id(building_id, property_name) == "Retail other than mall" + + def test_get_site_lat_lon_none(self): + filename = self.data_dir / "geojson_1.json" + json = UrbanOptGeoJson(filename) + assert json.get_site_lat_lon() is None + + def test_get_site_lat_lon(self): + filename = ( + self.data_dir.parent.parent + / "model_connectors" + / "data" + / "sdk_output_skeleton_13_buildings" + / "exportGeo.json" + ) + json = UrbanOptGeoJson(filename) + assert json.get_site_lat_lon() == [42.816772, -78.849485] diff --git a/tests/geojson/test_schemas.py b/tests/geojson/test_schemas.py index d3f9da39c..cd5a23922 100644 --- a/tests/geojson/test_schemas.py +++ b/tests/geojson/test_schemas.py @@ -1,49 +1,49 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import unittest - -# import pytest - -# from geojson_modelica_translator.geojson.schemas import Schemas - - -# class SchemasTest(unittest.TestCase): -# def test_load_schemas(self): -# s = Schemas() -# data = s.retrieve("building") -# assert data["title"] == "URBANopt Building" - -# def test_invalid_retrieve(self): -# s = Schemas() -# with pytest.raises(NameError) as context: -# s.retrieve("judicate") -# assert "Schema for judicate does not exist" in str(context.value) - -# def test_validate_schema(self): -# s = Schemas() -# s.retrieve("building") - -# # verify that the schema can validate an instance with simple parameters -# instance = { -# "id": "5a6b99ec37f4de7f94020090", -# "type": "Building", -# "name": "Medium Office", -# "footprint_area": 17059, -# "footprint_perimeter": 533, -# "building_type": "Office", -# "number_of_stories": 3, -# "system_type": "PTAC with district hot water", -# "number_of_stories_above_ground": 3, -# "building_status": "Proposed", -# "floor_area": 51177, -# "year_built": 2010, -# } -# res = s.validate("building", instance) -# assert len(res) == 0 - -# # bad system_type -# instance["type"] = "MagicBuilding" -# res = s.validate("building", instance) -# assert "'MagicBuilding' is not one of ['Building']" in res[0] -# assert len(res) == 1 +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import unittest + +import pytest + +from geojson_modelica_translator.geojson.schemas import Schemas + + +class SchemasTest(unittest.TestCase): + def test_load_schemas(self): + s = Schemas() + data = s.retrieve("building") + assert data["title"] == "URBANopt Building" + + def test_invalid_retrieve(self): + s = Schemas() + with pytest.raises(NameError) as context: + s.retrieve("judicate") + assert "Schema for judicate does not exist" in str(context.value) + + def test_validate_schema(self): + s = Schemas() + s.retrieve("building") + + # verify that the schema can validate an instance with simple parameters + instance = { + "id": "5a6b99ec37f4de7f94020090", + "type": "Building", + "name": "Medium Office", + "footprint_area": 17059, + "footprint_perimeter": 533, + "building_type": "Office", + "number_of_stories": 3, + "system_type": "PTAC with district hot water", + "number_of_stories_above_ground": 3, + "building_status": "Proposed", + "floor_area": 51177, + "year_built": 2010, + } + res = s.validate("building", instance) + assert len(res) == 0 + + # bad system_type + instance["type"] = "MagicBuilding" + res = s.validate("building", instance) + assert "'MagicBuilding' is not one of ['Building']" in res[0] + assert len(res) == 1 diff --git a/tests/geojson_modelica_translator/test_results_ghp.py b/tests/geojson_modelica_translator/test_results_ghp.py index 86156f4e3..2313552aa 100644 --- a/tests/geojson_modelica_translator/test_results_ghp.py +++ b/tests/geojson_modelica_translator/test_results_ghp.py @@ -1,99 +1,99 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pandas as pd +import pandas as pd -# from geojson_modelica_translator.results_ghp import ResultsModelica -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.results_ghp import ResultsModelica +from tests.base_test_case import TestCaseBase -# class ResultsTest(TestCaseBase): -# def setUp(self): -# self.data_dir = Path(__file__).parent / "data" +class ResultsTest(TestCaseBase): + def setUp(self): + self.data_dir = Path(__file__).parent / "data" -# def test_result(self): -# # Construct the path to the Modelica project directory -# modelica_path = Path(self.data_dir) / "modelica_5" -# modelica_path = modelica_path.resolve() + def test_result(self): + # Construct the path to the Modelica project directory + modelica_path = Path(self.data_dir) / "modelica_5" + modelica_path = modelica_path.resolve() -# # Construct the path to the CSV file -# csv_file_path = ( -# modelica_path -# / "modelica_5.Districts.DistrictEnergySystem_results" -# / "modelica_5.Districts.DistrictEnergySystem_result.csv" -# ) + # Construct the path to the CSV file + csv_file_path = ( + modelica_path + / "modelica_5.Districts.DistrictEnergySystem_results" + / "modelica_5.Districts.DistrictEnergySystem_result.csv" + ) -# # Delete csv path if it exists -# if csv_file_path.exists(): -# csv_file_path.unlink() + # Delete csv path if it exists + if csv_file_path.exists(): + csv_file_path.unlink() -# result = ResultsModelica(modelica_path) -# result.calculate_results() + result = ResultsModelica(modelica_path) + result.calculate_results() -# # Check if the CSV file exists -# assert csv_file_path.exists(), f"File does not exist at path: {csv_file_path}" + # Check if the CSV file exists + assert csv_file_path.exists(), f"File does not exist at path: {csv_file_path}" -# # Read the CSV file into a DataFrame -# csv_data = pd.read_csv(csv_file_path) + # Read the CSV file into a DataFrame + csv_data = pd.read_csv(csv_file_path) -# assert "Datetime" in csv_data.columns, "The 'Datetime' column is missing from the CSV file." + assert "Datetime" in csv_data.columns, "The 'Datetime' column is missing from the CSV file." -# assert "heating_electric_power_d55aa383" in csv_data.columns, ( -# "The heating_electric_power column is missing from the CSV file." -# ) + assert "heating_electric_power_d55aa383" in csv_data.columns, ( + "The heating_electric_power column is missing from the CSV file." + ) -# assert "pump_power_3da62a1d" in csv_data.columns, "The pump_power column is missing from the CSV file." + assert "pump_power_3da62a1d" in csv_data.columns, "The pump_power column is missing from the CSV file." -# assert "electrical_power_consumed" in csv_data.columns, ( -# "The electrical_power_consumed column is missing from the CSV file." -# ) + assert "electrical_power_consumed" in csv_data.columns, ( + "The electrical_power_consumed column is missing from the CSV file." + ) -# def test_result_multiple_ghp(self): -# # Construct the path to the Modelica project directory -# modelica_path = Path(self.data_dir) / "modelica_multiple" -# modelica_path = modelica_path.resolve() + def test_result_multiple_ghp(self): + # Construct the path to the Modelica project directory + modelica_path = Path(self.data_dir) / "modelica_multiple" + modelica_path = modelica_path.resolve() -# # Construct the path to the CSV file -# csv_file_path = ( -# modelica_path -# / "modelica_multiple.Districts.DistrictEnergySystem_results" -# / "modelica_multiple.Districts.DistrictEnergySystem_result.csv" -# ) + # Construct the path to the CSV file + csv_file_path = ( + modelica_path + / "modelica_multiple.Districts.DistrictEnergySystem_results" + / "modelica_multiple.Districts.DistrictEnergySystem_result.csv" + ) -# # Delete csv path if it exists -# if csv_file_path.exists(): -# csv_file_path.unlink() + # Delete csv path if it exists + if csv_file_path.exists(): + csv_file_path.unlink() -# result = ResultsModelica(modelica_path) -# result.calculate_results() + result = ResultsModelica(modelica_path) + result.calculate_results() -# # Check if the CSV file exists -# assert csv_file_path.exists(), f"File does not exist at path: {csv_file_path}" + # Check if the CSV file exists + assert csv_file_path.exists(), f"File does not exist at path: {csv_file_path}" -# # Read the CSV file into a DataFrame -# csv_data_multiple = pd.read_csv(csv_file_path) + # Read the CSV file into a DataFrame + csv_data_multiple = pd.read_csv(csv_file_path) -# assert "Datetime" in csv_data_multiple.columns, "The 'Datetime' column is missing from the CSV file." + assert "Datetime" in csv_data_multiple.columns, "The 'Datetime' column is missing from the CSV file." -# # Check if any columns contain the "heating_electric_power_" substring -# heating_electric_power = [col for col in csv_data_multiple.columns if "heating_electric_power_" in col] + # Check if any columns contain the "heating_electric_power_" substring + heating_electric_power = [col for col in csv_data_multiple.columns if "heating_electric_power_" in col] -# assert heating_electric_power, "No columns with 'heating_electric_power' found in the CSV file." + assert heating_electric_power, "No columns with 'heating_electric_power' found in the CSV file." -# assert len(heating_electric_power) == 13, ( -# f"Expected 13 columns with 'heating_electric_power_' but found {len(heating_electric_power)}." -# ) + assert len(heating_electric_power) == 13, ( + f"Expected 13 columns with 'heating_electric_power_' but found {len(heating_electric_power)}." + ) -# pump_power = [col for col in csv_data_multiple.columns if "pump_power_" in col] + pump_power = [col for col in csv_data_multiple.columns if "pump_power_" in col] -# # Assert that there is at least one column with the substring -# assert pump_power, "No columns with 'pump_power' found in the CSV file." + # Assert that there is at least one column with the substring + assert pump_power, "No columns with 'pump_power' found in the CSV file." -# assert len(pump_power) == 26, f"Expected 26 columns with 'pump_power' but found {len(pump_power)}." + assert len(pump_power) == 26, f"Expected 26 columns with 'pump_power' but found {len(pump_power)}." -# assert "electrical_power_consumed" in csv_data_multiple.columns, ( -# "The electrical_power_consumed column is missing from the CSV file." -# ) + assert "electrical_power_consumed" in csv_data_multiple.columns, ( + "The electrical_power_consumed column is missing from the CSV file." + ) diff --git a/tests/geojson_modelica_translator/test_scaffold.py b/tests/geojson_modelica_translator/test_scaffold.py index 05daba78b..48f641dd6 100644 --- a/tests/geojson_modelica_translator/test_scaffold.py +++ b/tests/geojson_modelica_translator/test_scaffold.py @@ -1,33 +1,33 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# import shutil -# import unittest -# from pathlib import Path +import shutil +import unittest +from pathlib import Path -# from geojson_modelica_translator.scaffold import Scaffold +from geojson_modelica_translator.scaffold import Scaffold -# class ScaffoldTest(unittest.TestCase): -# def setUp(self): -# self.data_dir = Path(__file__).parent / "data" -# self.output_dir = Path(__file__).parent / "output" -# if self.output_dir.exists(): -# shutil.rmtree(self.output_dir) -# self.output_dir.mkdir(exist_ok=True) +class ScaffoldTest(unittest.TestCase): + def setUp(self): + self.data_dir = Path(__file__).parent / "data" + self.output_dir = Path(__file__).parent / "output" + if self.output_dir.exists(): + shutil.rmtree(self.output_dir) + self.output_dir.mkdir(exist_ok=True) -# def test_scaffold(self): -# scaffold = Scaffold(self.output_dir, "scaffold_01", overwrite=True) -# scaffold.create() -# assert (Path(self.output_dir) / "scaffold_01" / "Resources" / "Scripts" / "Loads" / "Dymola").exists() + def test_scaffold(self): + scaffold = Scaffold(self.output_dir, "scaffold_01", overwrite=True) + scaffold.create() + assert (Path(self.output_dir) / "scaffold_01" / "Resources" / "Scripts" / "Loads" / "Dymola").exists() -# # def test_add_building(self): -# # scaffold = Scaffold(self.output_dir, "scaffold_02", overwrite=True) -# # load_1 = FakeConnector(None) -# # self.assertIsInstance(load_1, building_base) -# # scaffold.loads.append(load_1) -# # scaffold.create() -# # -# # r = scaffold.to_modelica() -# # self.assertTrue(r) + # def test_add_building(self): + # scaffold = Scaffold(self.output_dir, "scaffold_02", overwrite=True) + # load_1 = FakeConnector(None) + # self.assertIsInstance(load_1, building_base) + # scaffold.loads.append(load_1) + # scaffold.create() + # + # r = scaffold.to_modelica() + # self.assertTrue(r) diff --git a/tests/geojson_modelica_translator/test_translator.py b/tests/geojson_modelica_translator/test_translator.py index 87e4c7c0a..634609780 100644 --- a/tests/geojson_modelica_translator/test_translator.py +++ b/tests/geojson_modelica_translator/test_translator.py @@ -1,55 +1,55 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson_modelica_translator import GeoJsonModelicaTranslator -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson_modelica_translator import GeoJsonModelicaTranslator +from tests.base_test_case import TestCaseBase -# ROOT_DIR = Path(__file__).parent +ROOT_DIR = Path(__file__).parent -# class GeoJSONTranslatorTest(TestCaseBase): -# geojson_file = TestCaseBase.SHARED_DATA_DIR / "geojson_district" / "geojson.json" -# sys_params_file = TestCaseBase.SHARED_DATA_DIR / "geojson_district" / "system_params.json" +class GeoJSONTranslatorTest(TestCaseBase): + geojson_file = TestCaseBase.SHARED_DATA_DIR / "geojson_district" / "geojson.json" + sys_params_file = TestCaseBase.SHARED_DATA_DIR / "geojson_district" / "system_params.json" -# def test_to_modelica_is_successful_when_inputs_are_valid(self): -# # -- Setup, Act -# project_name = "generate_package" -# _, output_dir = self.set_up(ROOT_DIR, project_name) -# gmt = GeoJsonModelicaTranslator( -# self.geojson_file, -# self.sys_params_file, -# output_dir, -# project_name, -# ) + def test_to_modelica_is_successful_when_inputs_are_valid(self): + # -- Setup, Act + project_name = "generate_package" + _, output_dir = self.set_up(ROOT_DIR, project_name) + gmt = GeoJsonModelicaTranslator( + self.geojson_file, + self.sys_params_file, + output_dir, + project_name, + ) -# gmt.to_modelica() + gmt.to_modelica() -# # -- Assert -# assert (output_dir / project_name / "package.mo").exists() + # -- Assert + assert (output_dir / project_name / "package.mo").exists() -# @pytest.mark.simulation -# @pytest.mark.skip("OMC Spawn - Failed to find spawn executable in Buildings Library") -# def test_successfully_creates_and_simulates_when_inputs_are_valid(self): -# # -- Setup -# project_name = "simulate_package" -# _, output_dir = self.set_up(ROOT_DIR, project_name) + @pytest.mark.simulation + @pytest.mark.skip("OMC Spawn - Failed to find spawn executable in Buildings Library") + def test_successfully_creates_and_simulates_when_inputs_are_valid(self): + # -- Setup + project_name = "simulate_package" + _, output_dir = self.set_up(ROOT_DIR, project_name) -# gmt = GeoJsonModelicaTranslator( -# self.geojson_file, -# self.sys_params_file, -# output_dir, -# project_name, -# ) + gmt = GeoJsonModelicaTranslator( + self.geojson_file, + self.sys_params_file, + output_dir, + project_name, + ) -# package = gmt.to_modelica() + package = gmt.to_modelica() -# # -- Act -# success, results_dir = package.simulate() + # -- Act + success, results_dir = package.simulate() -# # -- Assert -# assert success, "simulation did not complete successfully" -# assert (results_dir / "stdout.log").exists() + # -- Assert + assert success, "simulation did not complete successfully" + assert (results_dir / "stdout.log").exists() diff --git a/tests/geojson_modelica_translator/test_utils.py b/tests/geojson_modelica_translator/test_utils.py index ee7c721f8..cf5760c81 100644 --- a/tests/geojson_modelica_translator/test_utils.py +++ b/tests/geojson_modelica_translator/test_utils.py @@ -1,23 +1,23 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# import unittest -# from pathlib import Path +import unittest +from pathlib import Path -# from geojson_modelica_translator.utils import ModelicaPath +from geojson_modelica_translator.utils import ModelicaPath -# class ModelicaPathTest(unittest.TestCase): -# def setUp(self): -# self.output_dir = Path(__file__).parent / "output" +class ModelicaPathTest(unittest.TestCase): + def setUp(self): + self.output_dir = Path(__file__).parent / "output" -# def test_properties(self): -# mp = ModelicaPath("Loads", root_dir=None) -# assert mp.files_dir == "Loads" -# assert mp.resources_dir == "Resources/Data/Loads" + def test_properties(self): + mp = ModelicaPath("Loads", root_dir=None) + assert mp.files_dir == "Loads" + assert mp.resources_dir == "Resources/Data/Loads" -# def test_single_sub_resource(self): -# root_dir = self.output_dir / "modelica_path_01" -# ModelicaPath("RandomContainer", root_dir, overwrite=True) -# assert (Path(root_dir) / "RandomContainer").exists() -# assert (Path(root_dir) / "Resources" / "Data" / "RandomContainer").exists() + def test_single_sub_resource(self): + root_dir = self.output_dir / "modelica_path_01" + ModelicaPath("RandomContainer", root_dir, overwrite=True) + assert (Path(root_dir) / "RandomContainer").exists() + assert (Path(root_dir) / "Resources" / "Data" / "RandomContainer").exists() diff --git a/tests/management/test_format_modelica_files.py b/tests/management/test_format_modelica_files.py index 78d7fc1ed..6b0c4dda5 100644 --- a/tests/management/test_format_modelica_files.py +++ b/tests/management/test_format_modelica_files.py @@ -1,38 +1,38 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# import re -# import shutil -# import unittest -# from pathlib import Path +import re +import shutil +import unittest +from pathlib import Path -# import pytest +import pytest -# from management.format_modelica_files import SKIP_FILES, TEMPLATE_FILES, preprocess_and_format +from management.format_modelica_files import SKIP_FILES, TEMPLATE_FILES, preprocess_and_format -# class FormatModelicaFilesTest(unittest.TestCase): -# def setUp(self): -# self.output_dir = Path(__file__).parent / "output" -# if self.output_dir.exists(): -# shutil.rmtree(self.output_dir) -# self.output_dir.mkdir(exist_ok=True) +class FormatModelicaFilesTest(unittest.TestCase): + def setUp(self): + self.output_dir = Path(__file__).parent / "output" + if self.output_dir.exists(): + shutil.rmtree(self.output_dir) + self.output_dir.mkdir(exist_ok=True) -# @pytest.mark.skipif(shutil.which("modelicafmt") is None, reason="Modelica formatter is not installed. Skipping.") -# def test_no_meaningful_diff_when_formatting_mot_files(self): -# """After applying formatter to .mot (Jinja) files, we expect the only differences to be in whitespace""" -# for file_ in TEMPLATE_FILES: -# outfilepath = self.output_dir / file_.name + @pytest.mark.skipif(shutil.which("modelicafmt") is None, reason="Modelica formatter is not installed. Skipping.") + def test_no_meaningful_diff_when_formatting_mot_files(self): + """After applying formatter to .mot (Jinja) files, we expect the only differences to be in whitespace""" + for file_ in TEMPLATE_FILES: + outfilepath = self.output_dir / file_.name -# if file_.suffix != ".mot" or file_.name in SKIP_FILES: -# continue + if file_.suffix != ".mot" or file_.name in SKIP_FILES: + continue -# preprocess_and_format(str(file_), outfilepath) + preprocess_and_format(str(file_), outfilepath) -# # strip whitespace from file contents and assert they're equal -# with open(file_) as orig, open(outfilepath) as new: -# orig_stripped = re.sub(r"\s", "", orig.read()) -# new_stripped = re.sub(r"\s", "", new.read()) -# assert orig_stripped == new_stripped, ( -# f"Original and formatted files for {file_} should have the same content" -# ) + # strip whitespace from file contents and assert they're equal + with open(file_) as orig, open(outfilepath) as new: + orig_stripped = re.sub(r"\s", "", orig.read()) + new_stripped = re.sub(r"\s", "", new.read()) + assert orig_stripped == new_stripped, ( + f"Original and formatted files for {file_} should have the same content" + ) diff --git a/tests/management/test_uo_des.py b/tests/management/test_uo_des.py index ac76396d8..6fd81fbb8 100644 --- a/tests/management/test_uo_des.py +++ b/tests/management/test_uo_des.py @@ -1,368 +1,368 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path -# from shutil import rmtree -# from unittest import TestCase - -# import pytest -# from click.testing import CliRunner - -# from geojson_modelica_translator.geojson_modelica_translator import GeoJsonModelicaTranslator -# from management.uo_des import cli - -# # Integration tests that the CLI works as expected for an end user - - -# class CLIIntegrationTest(TestCase): -# def setUp(self): -# self.runner = CliRunner() -# self.data_dir = Path(__file__).parent / "data" -# self.output_dir = Path(__file__).parent / "output" -# self.output_dir.mkdir(exist_ok=True) -# self.scenario_file_path = self.data_dir / "sdk_project_scraps" / "baseline_scenario.csv" -# self.feature_file_path = self.data_dir / "sdk_project_scraps" / "example_project.json" -# self.feature_file_path_ghe = self.data_dir / "sdk_project_scraps" / "exportGeo_combine_GHE.json" -# self.feature_file_path_germany = self.data_dir / "sdk_project_scraps" / "exportGeo_germany_ghe.json" -# self.sys_param_path = ( -# self.data_dir / "sdk_project_scraps" / "run" / "baseline_scenario" / "system_parameter.json" -# ) -# self.day_200_in_seconds = 17280000 # in seconds -# self.day_201_in_seconds = 17366400 # in seconds -# self.step_size_90_seconds = 90 # in seconds - -# def test_cli_builds_sys_params(self): -# self.sys_param_path.unlink(missing_ok=True) - -# # run subprocess as if we're an end-user -# res = self.runner.invoke( -# cli, -# [ -# "build-sys-param", -# str(self.sys_param_path), -# str(self.scenario_file_path.resolve()), -# str(self.feature_file_path.resolve()), -# ], -# ) - -# assert res.exit_code == 0 - -# # If this file exists, the cli command ran successfully -# assert self.sys_param_path.exists() - -# def test_cli_builds_sys_params_with_ghe(self): -# self.sys_param_path.unlink(missing_ok=True) - -# # run subprocess as if we're an end-user -# res = self.runner.invoke( -# cli, -# [ -# "build-sys-param", -# str(self.sys_param_path), -# str(self.scenario_file_path.resolve()), -# str(self.feature_file_path_ghe.resolve()), -# "5G_ghe", -# ], -# ) - -# assert res.exit_code == 0 - -# # If this file exists, the cli command ran successfully -# assert self.sys_param_path.exists() - -# def test_cli_builds_sys_params_with_german_weatherfile(self): -# self.sys_param_path.unlink(missing_ok=True) - -# # run subprocess as if we're an end-user -# res = self.runner.invoke( -# cli, -# [ -# "build-sys-param", -# str(self.sys_param_path), -# str(self.scenario_file_path.resolve()), -# str(self.feature_file_path_germany.resolve()), -# "5G_ghe", -# ], -# ) - -# assert res.exit_code == 0 - -# # If this file exists, the cli command ran successfully -# assert self.sys_param_path.exists() - -# def test_cli_makes_model(self): -# # -- Setup -# # Generate a sys-params file using the CLI -# project_name = "modelica_project_4g" -# if (self.output_dir / project_name).exists(): -# rmtree(self.output_dir / project_name) - -# self.sys_param_path.unlink(missing_ok=True) - -# # run subprocess as if we're an end-user -# res = self.runner.invoke( -# cli, -# [ -# "build-sys-param", -# str(self.sys_param_path), -# str(self.scenario_file_path.resolve()), -# str(self.feature_file_path.resolve()), -# ], -# ) - -# assert res.exit_code == 0 - -# # If this file exists, the cli successfully built the system parameter file -# assert self.sys_param_path.exists() - -# # Next, verify the package can be generated without the CLI (verify our files are valid) - -# gmt = GeoJsonModelicaTranslator( -# self.feature_file_path, -# self.sys_param_path, -# self.output_dir, -# project_name, -# ) - -# gmt.to_modelica() - -# # If this file exists, the cli successfully built the model -# assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() -# # Great! We know our files are good, let's cleanup and test the CLI -# rmtree(self.output_dir / project_name) - -# # -- Act -# res = self.runner.invoke( -# cli, -# [ -# "create-model", -# str(self.sys_param_path), -# str(self.feature_file_path), -# str(self.output_dir / project_name), -# ], -# ) - -# # -- Assert -# assert res.exit_code == 0 -# # If this file exists, the cli successfully built the model -# assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() - -# def test_cli_makes_model_with_ghe(self): -# # -- Setup -# # first verify the package can be generated without the CLI (ie verify our -# # files are valid) -# project_name = "modelica_project_5g" -# if (self.output_dir / project_name).exists(): -# rmtree(self.output_dir / project_name) - -# self.sys_param_path.unlink(missing_ok=True) - -# # run subprocess as if we're an end-user -# res = self.runner.invoke( -# cli, -# [ -# "build-sys-param", -# str(self.sys_param_path), -# str(self.scenario_file_path.resolve()), -# str(self.feature_file_path_ghe.resolve()), -# "5G_ghe", -# ], -# ) - -# assert res.exit_code == 0 - -# # If this file exists, the cli command ran successfully -# assert self.sys_param_path.exists() - -# gmt = GeoJsonModelicaTranslator( -# self.feature_file_path_ghe, -# self.sys_param_path, -# self.output_dir, -# project_name, -# ) - -# gmt.to_modelica() - -# # If this file exists, the code successfully built the model -# assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() -# # Great! We know our files are good, let's cleanup and test the CLI -# rmtree(self.output_dir / project_name) - -# # -- Act -# res = self.runner.invoke( -# cli, -# [ -# "create-model", -# str(self.sys_param_path), -# str(self.feature_file_path_ghe), -# str(self.output_dir / project_name), -# ], -# ) - -# # -- Assert -# assert res.exit_code == 0 - -# # If this file exists, the cli command ran successfully -# assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() - -# def test_cli_makes_model_with_german_weather(self): -# # -- Setup -# # first verify the package can be generated without the CLI (ie verify our -# # files are valid) -# project_name = "modelica_project_germany" -# if (self.output_dir / project_name).exists(): -# rmtree(self.output_dir / project_name) - -# self.sys_param_path.unlink(missing_ok=True) - -# # run subprocess as if we're an end-user -# res = self.runner.invoke( -# cli, -# [ -# "build-sys-param", -# str(self.sys_param_path), -# str(self.scenario_file_path.resolve()), -# str(self.feature_file_path_germany.resolve()), -# "5G_ghe", -# ], -# ) - -# assert res.exit_code == 0 - -# # If this file exists, the cli command ran successfully -# assert self.sys_param_path.exists() - -# gmt = GeoJsonModelicaTranslator( -# self.feature_file_path_germany, -# self.sys_param_path, -# self.output_dir, -# project_name, -# ) - -# gmt.to_modelica() - -# # If this file exists, the cli successfully built the model -# assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() -# # Great! We know our files are good, let's cleanup and test the CLI -# rmtree(self.output_dir / project_name) - -# # -- Act -# res = self.runner.invoke( -# cli, -# [ -# "create-model", -# str(self.sys_param_path), -# str(self.feature_file_path_germany), -# str(self.output_dir / project_name), -# ], -# ) - -# # -- Assert -# assert res.exit_code == 0 - -# # If this file exists, the cli command ran successfully -# assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() - -# def test_cli_overwrites_properly(self): -# # run subprocess as if we're an end-user, expecting to hit error message -# project_name = "modelica_project" -# (self.output_dir / project_name).mkdir(exist_ok=True) - -# no_overwrite_result = self.runner.invoke( -# cli, -# [ -# "create-model", -# str(self.sys_param_path), -# str(self.feature_file_path_ghe), -# str(self.output_dir / project_name), -# ], -# ) - -# assert no_overwrite_result.exit_code != 0 -# assert "already exists and overwrite flag is not given" in str(no_overwrite_result.exception) - -# # Run subprocess with overwrite flag, expect it to write new files without errors -# self.runner.invoke( -# cli, -# [ -# "create-model", -# str(self.sys_param_path), -# str(self.feature_file_path_ghe), -# str(self.output_dir / project_name), -# "--overwrite", -# ], -# ) - -# # If this file exists, the cli command ran successfully -# assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() - -# def test_cli_returns_graceful_error_on_space(self): -# bad_project_name = "modelica project" -# # (self.output_dir / bad_project_name).mkdir(exist_ok=True) - -# expected_failure = self.runner.invoke( -# cli, -# [ -# "create-model", -# str(self.sys_param_path), -# str(self.feature_file_path), -# str(self.output_dir / bad_project_name), -# ], -# ) - -# assert expected_failure.exit_code != 0 -# assert "Modelica does not support spaces in project names or paths." in str(expected_failure.exception) - -# @pytest.mark.simulation -# def test_cli_runs_existing_4g_model(self): -# project_name = "modelica_project_4g" -# results_dir = f"{project_name}.Districts.DistrictEnergySystem_results" -# if (self.output_dir / project_name / results_dir).exists(): -# rmtree(self.output_dir / project_name / results_dir) - -# # run subprocess as if we're an end-user -# self.runner.invoke( -# cli, -# [ -# "run-model", -# str(self.output_dir / project_name), -# "-a", -# str(self.day_200_in_seconds), -# "-z", -# str(self.day_201_in_seconds), -# "-x", -# str(self.step_size_90_seconds), -# ], -# ) - -# # If this file exists, the cli command ran successfully -# assert ( -# self.output_dir / project_name / results_dir / f"{project_name}.Districts.DistrictEnergySystem_res.mat" -# ).exists() - -# @pytest.mark.simulation -# def test_cli_runs_existing_5g_model(self): -# project_name = "modelica_project_5g" -# results_dir = f"{project_name}.Districts.DistrictEnergySystem_results" -# if (self.output_dir / project_name / results_dir).exists(): -# rmtree(self.output_dir / project_name / results_dir) - -# # run subprocess as if we're an end-user -# self.runner.invoke( -# cli, -# [ -# "run-model", -# str(self.output_dir / project_name), -# "-a", -# str(self.day_200_in_seconds), -# "-z", -# str(self.day_201_in_seconds), -# "-x", -# str(self.step_size_90_seconds), -# ], -# ) - -# # If this file exists, the cli command ran successfully -# assert ( -# self.output_dir / project_name / results_dir / f"{project_name}.Districts.DistrictEnergySystem_res.mat" -# ).exists() +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path +from shutil import rmtree +from unittest import TestCase + +import pytest +from click.testing import CliRunner + +from geojson_modelica_translator.geojson_modelica_translator import GeoJsonModelicaTranslator +from management.uo_des import cli + +# Integration tests that the CLI works as expected for an end user + + +class CLIIntegrationTest(TestCase): + def setUp(self): + self.runner = CliRunner() + self.data_dir = Path(__file__).parent / "data" + self.output_dir = Path(__file__).parent / "output" + self.output_dir.mkdir(exist_ok=True) + self.scenario_file_path = self.data_dir / "sdk_project_scraps" / "baseline_scenario.csv" + self.feature_file_path = self.data_dir / "sdk_project_scraps" / "example_project.json" + self.feature_file_path_ghe = self.data_dir / "sdk_project_scraps" / "exportGeo_combine_GHE.json" + self.feature_file_path_germany = self.data_dir / "sdk_project_scraps" / "exportGeo_germany_ghe.json" + self.sys_param_path = ( + self.data_dir / "sdk_project_scraps" / "run" / "baseline_scenario" / "system_parameter.json" + ) + self.day_200_in_seconds = 17280000 # in seconds + self.day_201_in_seconds = 17366400 # in seconds + self.step_size_90_seconds = 90 # in seconds + + def test_cli_builds_sys_params(self): + self.sys_param_path.unlink(missing_ok=True) + + # run subprocess as if we're an end-user + res = self.runner.invoke( + cli, + [ + "build-sys-param", + str(self.sys_param_path), + str(self.scenario_file_path.resolve()), + str(self.feature_file_path.resolve()), + ], + ) + + assert res.exit_code == 0 + + # If this file exists, the cli command ran successfully + assert self.sys_param_path.exists() + + def test_cli_builds_sys_params_with_ghe(self): + self.sys_param_path.unlink(missing_ok=True) + + # run subprocess as if we're an end-user + res = self.runner.invoke( + cli, + [ + "build-sys-param", + str(self.sys_param_path), + str(self.scenario_file_path.resolve()), + str(self.feature_file_path_ghe.resolve()), + "5G_ghe", + ], + ) + + assert res.exit_code == 0 + + # If this file exists, the cli command ran successfully + assert self.sys_param_path.exists() + + def test_cli_builds_sys_params_with_german_weatherfile(self): + self.sys_param_path.unlink(missing_ok=True) + + # run subprocess as if we're an end-user + res = self.runner.invoke( + cli, + [ + "build-sys-param", + str(self.sys_param_path), + str(self.scenario_file_path.resolve()), + str(self.feature_file_path_germany.resolve()), + "5G_ghe", + ], + ) + + assert res.exit_code == 0 + + # If this file exists, the cli command ran successfully + assert self.sys_param_path.exists() + + def test_cli_makes_model(self): + # -- Setup + # Generate a sys-params file using the CLI + project_name = "modelica_project_4g" + if (self.output_dir / project_name).exists(): + rmtree(self.output_dir / project_name) + + self.sys_param_path.unlink(missing_ok=True) + + # run subprocess as if we're an end-user + res = self.runner.invoke( + cli, + [ + "build-sys-param", + str(self.sys_param_path), + str(self.scenario_file_path.resolve()), + str(self.feature_file_path.resolve()), + ], + ) + + assert res.exit_code == 0 + + # If this file exists, the cli successfully built the system parameter file + assert self.sys_param_path.exists() + + # Next, verify the package can be generated without the CLI (verify our files are valid) + + gmt = GeoJsonModelicaTranslator( + self.feature_file_path, + self.sys_param_path, + self.output_dir, + project_name, + ) + + gmt.to_modelica() + + # If this file exists, the cli successfully built the model + assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() + # Great! We know our files are good, let's cleanup and test the CLI + rmtree(self.output_dir / project_name) + + # -- Act + res = self.runner.invoke( + cli, + [ + "create-model", + str(self.sys_param_path), + str(self.feature_file_path), + str(self.output_dir / project_name), + ], + ) + + # -- Assert + assert res.exit_code == 0 + # If this file exists, the cli successfully built the model + assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() + + def test_cli_makes_model_with_ghe(self): + # -- Setup + # first verify the package can be generated without the CLI (ie verify our + # files are valid) + project_name = "modelica_project_5g" + if (self.output_dir / project_name).exists(): + rmtree(self.output_dir / project_name) + + self.sys_param_path.unlink(missing_ok=True) + + # run subprocess as if we're an end-user + res = self.runner.invoke( + cli, + [ + "build-sys-param", + str(self.sys_param_path), + str(self.scenario_file_path.resolve()), + str(self.feature_file_path_ghe.resolve()), + "5G_ghe", + ], + ) + + assert res.exit_code == 0 + + # If this file exists, the cli command ran successfully + assert self.sys_param_path.exists() + + gmt = GeoJsonModelicaTranslator( + self.feature_file_path_ghe, + self.sys_param_path, + self.output_dir, + project_name, + ) + + gmt.to_modelica() + + # If this file exists, the code successfully built the model + assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() + # Great! We know our files are good, let's cleanup and test the CLI + rmtree(self.output_dir / project_name) + + # -- Act + res = self.runner.invoke( + cli, + [ + "create-model", + str(self.sys_param_path), + str(self.feature_file_path_ghe), + str(self.output_dir / project_name), + ], + ) + + # -- Assert + assert res.exit_code == 0 + + # If this file exists, the cli command ran successfully + assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() + + def test_cli_makes_model_with_german_weather(self): + # -- Setup + # first verify the package can be generated without the CLI (ie verify our + # files are valid) + project_name = "modelica_project_germany" + if (self.output_dir / project_name).exists(): + rmtree(self.output_dir / project_name) + + self.sys_param_path.unlink(missing_ok=True) + + # run subprocess as if we're an end-user + res = self.runner.invoke( + cli, + [ + "build-sys-param", + str(self.sys_param_path), + str(self.scenario_file_path.resolve()), + str(self.feature_file_path_germany.resolve()), + "5G_ghe", + ], + ) + + assert res.exit_code == 0 + + # If this file exists, the cli command ran successfully + assert self.sys_param_path.exists() + + gmt = GeoJsonModelicaTranslator( + self.feature_file_path_germany, + self.sys_param_path, + self.output_dir, + project_name, + ) + + gmt.to_modelica() + + # If this file exists, the cli successfully built the model + assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() + # Great! We know our files are good, let's cleanup and test the CLI + rmtree(self.output_dir / project_name) + + # -- Act + res = self.runner.invoke( + cli, + [ + "create-model", + str(self.sys_param_path), + str(self.feature_file_path_germany), + str(self.output_dir / project_name), + ], + ) + + # -- Assert + assert res.exit_code == 0 + + # If this file exists, the cli command ran successfully + assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() + + def test_cli_overwrites_properly(self): + # run subprocess as if we're an end-user, expecting to hit error message + project_name = "modelica_project" + (self.output_dir / project_name).mkdir(exist_ok=True) + + no_overwrite_result = self.runner.invoke( + cli, + [ + "create-model", + str(self.sys_param_path), + str(self.feature_file_path_ghe), + str(self.output_dir / project_name), + ], + ) + + assert no_overwrite_result.exit_code != 0 + assert "already exists and overwrite flag is not given" in str(no_overwrite_result.exception) + + # Run subprocess with overwrite flag, expect it to write new files without errors + self.runner.invoke( + cli, + [ + "create-model", + str(self.sys_param_path), + str(self.feature_file_path_ghe), + str(self.output_dir / project_name), + "--overwrite", + ], + ) + + # If this file exists, the cli command ran successfully + assert (self.output_dir / project_name / "Districts" / "DistrictEnergySystem.mo").exists() + + def test_cli_returns_graceful_error_on_space(self): + bad_project_name = "modelica project" + # (self.output_dir / bad_project_name).mkdir(exist_ok=True) + + expected_failure = self.runner.invoke( + cli, + [ + "create-model", + str(self.sys_param_path), + str(self.feature_file_path), + str(self.output_dir / bad_project_name), + ], + ) + + assert expected_failure.exit_code != 0 + assert "Modelica does not support spaces in project names or paths." in str(expected_failure.exception) + + @pytest.mark.simulation + def test_cli_runs_existing_4g_model(self): + project_name = "modelica_project_4g" + results_dir = f"{project_name}.Districts.DistrictEnergySystem_results" + if (self.output_dir / project_name / results_dir).exists(): + rmtree(self.output_dir / project_name / results_dir) + + # run subprocess as if we're an end-user + self.runner.invoke( + cli, + [ + "run-model", + str(self.output_dir / project_name), + "-a", + str(self.day_200_in_seconds), + "-z", + str(self.day_201_in_seconds), + "-x", + str(self.step_size_90_seconds), + ], + ) + + # If this file exists, the cli command ran successfully + assert ( + self.output_dir / project_name / results_dir / f"{project_name}.Districts.DistrictEnergySystem_res.mat" + ).exists() + + @pytest.mark.simulation + def test_cli_runs_existing_5g_model(self): + project_name = "modelica_project_5g" + results_dir = f"{project_name}.Districts.DistrictEnergySystem_results" + if (self.output_dir / project_name / results_dir).exists(): + rmtree(self.output_dir / project_name / results_dir) + + # run subprocess as if we're an end-user + self.runner.invoke( + cli, + [ + "run-model", + str(self.output_dir / project_name), + "-a", + str(self.day_200_in_seconds), + "-z", + str(self.day_201_in_seconds), + "-x", + str(self.step_size_90_seconds), + ], + ) + + # If this file exists, the cli command ran successfully + assert ( + self.output_dir / project_name / results_dir / f"{project_name}.Districts.DistrictEnergySystem_res.mat" + ).exists() diff --git a/tests/model_connectors/test_chilled_water_plant.py b/tests/model_connectors/test_chilled_water_plant.py index ebaeddf0c..cb7352143 100644 --- a/tests/model_connectors/test_chilled_water_plant.py +++ b/tests/model_connectors/test_chilled_water_plant.py @@ -1,59 +1,59 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest - -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.networks.network_chilled_water_stub import NetworkChilledWaterStub -# from geojson_modelica_translator.model_connectors.plants import CoolingPlant -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class DistrictSystemTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# project_name = "chilled_water_plant_stub" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(filename) - -# cooling_plant = CoolingPlant(sys_params) -# # create chilled water stub for the ets -# chilled_water_stub = NetworkChilledWaterStub(sys_params) -# cp_cw_coupling = Coupling(cooling_plant, chilled_water_stub) - -# graph = CouplingGraph( -# [ -# cp_cw_coupling, -# ] -# ) - -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() - -# def test_build_district_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# def test_simulate_district_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest + +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.networks.network_chilled_water_stub import NetworkChilledWaterStub +from geojson_modelica_translator.model_connectors.plants import CoolingPlant +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class DistrictSystemTest(TestCaseBase): + def setUp(self): + super().setUp() + + project_name = "chilled_water_plant_stub" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(filename) + + cooling_plant = CoolingPlant(sys_params) + # create chilled water stub for the ets + chilled_water_stub = NetworkChilledWaterStub(sys_params) + cp_cw_coupling = Coupling(cooling_plant, chilled_water_stub) + + graph = CouplingGraph( + [ + cp_cw_coupling, + ] + ) + + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() + + def test_build_district_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + def test_simulate_district_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + ) diff --git a/tests/model_connectors/test_chp_system.py b/tests/model_connectors/test_chp_system.py index a72b6b899..ce2493fbb 100644 --- a/tests/model_connectors/test_chp_system.py +++ b/tests/model_connectors/test_chp_system.py @@ -1,75 +1,75 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub +from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class CombinedHeatingPowerTest(TestCaseBase): -# def setUp(self): -# super().setUp() +class CombinedHeatingPowerTest(TestCaseBase): + def setUp(self): + super().setUp() -# self.project_name = "heat_with_chp" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) + self.project_name = "heat_with_chp" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_chp.json" -# self.sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_chp.json" + self.sys_params = SystemParameters(filename) -# # create network and plant -# network = Network2Pipe(self.sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) + # create network and plant + network = Network2Pipe(self.sys_params) + heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) -# # create our our load/ets/stubs -# all_couplings = [Coupling(network, heating_plant)] -# for geojson_load in self.gj.buildings: -# time_series_load = TimeSeries(self.sys_params, geojson_load) -# geojson_load_id = geojson_load.feature.properties["id"] -# heating_indirect_system = HeatingIndirect(self.sys_params, geojson_load_id) -# cold_water_stub = EtsColdWaterStub(self.sys_params) -# all_couplings.append(Coupling(time_series_load, heating_indirect_system)) -# all_couplings.append(Coupling(time_series_load, cold_water_stub)) -# all_couplings.append(Coupling(heating_indirect_system, network)) + # create our our load/ets/stubs + all_couplings = [Coupling(network, heating_plant)] + for geojson_load in self.gj.buildings: + time_series_load = TimeSeries(self.sys_params, geojson_load) + geojson_load_id = geojson_load.feature.properties["id"] + heating_indirect_system = HeatingIndirect(self.sys_params, geojson_load_id) + cold_water_stub = EtsColdWaterStub(self.sys_params) + all_couplings.append(Coupling(time_series_load, heating_indirect_system)) + all_couplings.append(Coupling(time_series_load, cold_water_stub)) + all_couplings.append(Coupling(heating_indirect_system, network)) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, -# project_name=self.project_name, -# system_parameters=self.sys_params, -# coupling_graph=graph, -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, + project_name=self.project_name, + system_parameters=self.sys_params, + coupling_graph=graph, + ) + self.district.to_modelica() -# def test_build_chp_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_chp_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# def test_simulate_chp_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=0, # Day 0 (in seconds) -# stop_time=9999, # For 2.78 hours (in seconds) -# step_size=300, # (in seconds) -# ) + @pytest.mark.simulation + def test_simulate_chp_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=0, # Day 0 (in seconds) + stop_time=9999, # For 2.78 hours (in seconds) + step_size=300, # (in seconds) + ) diff --git a/tests/model_connectors/test_cooling_indirect.py b/tests/model_connectors/test_cooling_indirect.py index a5f7b8e4b..d088d151b 100644 --- a/tests/model_connectors/test_cooling_indirect.py +++ b/tests/model_connectors/test_cooling_indirect.py @@ -1,41 +1,41 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# from modelica_builder.package_parser import PackageParser - -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect -# from geojson_modelica_translator.scaffold import Scaffold -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class CoolingIndirectTest(TestCaseBase): -# def test_cooling_indirect(self): -# project_name = "cooling_indirect" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) -# # scaffold the project ourselves -# scaffold = Scaffold(self.output_dir, project_name) -# scaffold.create() - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(filename) - -# # currently we must setup the root project before we can run to_modelica -# package = PackageParser.new_from_template(scaffold.project_path, scaffold.project_name, order=[]) -# package.save() -# # now test the connector (independent of the larger geojson translator) -# geojson_id = self.gj.buildings[0].feature.properties["id"] -# self.cooling_indirect = CoolingIndirect(sys_params, geojson_id) -# self.cooling_indirect.to_modelica(scaffold) - -# root_path = Path(scaffold.substations_path.files_dir).resolve() -# model_filepath = root_path / f"CoolingIndirect_{geojson_id}.mo" -# assert Path(model_filepath).exists(), f"File does not exist: {model_filepath}" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +from modelica_builder.package_parser import PackageParser + +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect +from geojson_modelica_translator.scaffold import Scaffold +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class CoolingIndirectTest(TestCaseBase): + def test_cooling_indirect(self): + project_name = "cooling_indirect" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + # scaffold the project ourselves + scaffold = Scaffold(self.output_dir, project_name) + scaffold.create() + + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(filename) + + # currently we must setup the root project before we can run to_modelica + package = PackageParser.new_from_template(scaffold.project_path, scaffold.project_name, order=[]) + package.save() + # now test the connector (independent of the larger geojson translator) + geojson_id = self.gj.buildings[0].feature.properties["id"] + self.cooling_indirect = CoolingIndirect(sys_params, geojson_id) + self.cooling_indirect.to_modelica(scaffold) + + root_path = Path(scaffold.substations_path.files_dir).resolve() + model_filepath = root_path / f"CoolingIndirect_{geojson_id}.mo" + assert Path(model_filepath).exists(), f"File does not exist: {model_filepath}" diff --git a/tests/model_connectors/test_diagram_graph.py b/tests/model_connectors/test_diagram_graph.py index 4640bbd5b..02ed841a7 100644 --- a/tests/model_connectors/test_diagram_graph.py +++ b/tests/model_connectors/test_diagram_graph.py @@ -1,187 +1,187 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import pytest - -# from geojson_modelica_translator.model_connectors.couplings.diagram import Diagram, DiagramNode -# from geojson_modelica_translator.model_connectors.couplings.utils import ( -# DiagramLine, -# DiagramTransformation, -# parse_diagram_commands, -# ) -# from tests.base_test_case import TestCaseBase - - -# class MockCoupling: -# def __init__(self, coupling_id, a, b): -# self.id = coupling_id -# self._model_a = a -# self._model_b = b - - -# class MockModel: -# def __init__(self, model_id): -# self.id = model_id - - -# def mock_coupling_factory(coupling_id, model_a_id, model_b_id): -# return MockCoupling(coupling_id=coupling_id, a=MockModel(model_a_id), b=MockModel(model_b_id)) - - -# class DiagramGraphTest(TestCaseBase): -# def test_parse_diagram_commands_parses_transformations(self): -# # Setup -# modelica_content = """ -# model Simple -# {{ ignored.context }} -# Modelica.Blocks.Sources.RealExpression abc(y=1) -# annnotation (Placement({{ diagram.transformation.abc.real_expression }})) -# end Simple;""" - -# # Act -# commands = parse_diagram_commands(modelica_content) - -# # Assert -# assert len(commands) == 1 -# cmd = commands[0] -# assert isinstance(cmd, DiagramTransformation) -# assert cmd.model_name == "abc" -# assert cmd.model_type == "real_expression" - -# def test_parse_diagram_commands_parses_lines(self): -# # Setup -# modelica_content = """ -# model Simple -# {{ ignored.context }} -# equation -# connect(abc.port_a, def.port_b) -# annotation(Line({{ diagram.line.abc.port_a.def.port_b }})); -# end Simple;""" - -# # Act -# commands = parse_diagram_commands(modelica_content) - -# # Assert -# assert len(commands) == 1 -# cmd = commands[0] -# assert isinstance(cmd, DiagramLine) -# assert cmd.a_name == "abc" -# assert cmd.a_port == "port_a" -# assert cmd.b_name == "def" -# assert cmd.b_port == "port_b" - -# def test_parse_diagram_commands_errors_when_command_is_invalid(self): -# # Setup -# bad_transformation = "{{ diagram.transformation.bad }}" -# bad_line = "{{ diagram.line.bad }}" - -# # Act/Assert -# with pytest.raises(TypeError, match='Invalid diagram templating command: "transformation".*'): -# parse_diagram_commands(bad_transformation) - -# with pytest.raises(TypeError, match='Invalid diagram templating command: "line".*'): -# parse_diagram_commands(bad_line) - -# def test_diagram_commands_to_graph_succeeds_for_transformations(self): -# # Setup -# load_a_id = "load_a" -# ets_a_id = "ets_a" -# coupling_id = "coupling_a" -# load_ets_coupling = mock_coupling_factory(coupling_id, load_a_id, ets_a_id) -# couplings = [ -# load_ets_coupling, -# ] - -# diagram_commands_by_id = { -# load_a_id: [ -# DiagramTransformation( -# model_name="some_load", -# model_type="load", -# ) -# ], -# ets_a_id: [ -# DiagramTransformation( -# model_name="some_ets", -# model_type="ets", -# ) -# ], -# # also create a transformation which is coupling specific (ie defined in a coupling template file) -# coupling_id: [ -# DiagramTransformation( -# model_name="some_real_expression", -# model_type="real_expression", -# ) -# ], -# } - -# expected_diagram_graph = { -# load_a_id: {"some_load": DiagramNode(load_a_id, "some_load", "load")}, -# ets_a_id: {"some_ets": DiagramNode(ets_a_id, "some_ets", "ets")}, -# coupling_id: {"some_real_expression": DiagramNode(coupling_id, "some_real_expression", "real_expression")}, -# } - -# # Act -# diagram_graph = Diagram._diagram_commands_to_graph(diagram_commands_by_id, couplings) - -# # Assert -# assert expected_diagram_graph == diagram_graph - -# def test_diagram_commands_to_graph_succeeds_for_transformations_and_lines(self): -# # Setup -# load_a_id = "load_a" -# ets_a_id = "ets_a" -# coupling_id = "coupling_a" -# load_ets_coupling = mock_coupling_factory(coupling_id, load_a_id, ets_a_id) -# couplings = [ -# load_ets_coupling, -# ] - -# diagram_commands_by_id = { -# load_a_id: [ -# DiagramTransformation( -# model_name="some_load", -# model_type="load", -# ) -# ], -# ets_a_id: [ -# DiagramTransformation( -# model_name="some_ets", -# model_type="ets", -# ) -# ], -# coupling_id: [ -# DiagramTransformation( -# model_name="some_real_expression", -# model_type="real_expression", -# ), -# # create lines which connect these components -# DiagramLine( -# a_name="some_load", -# a_port="port_a", -# b_name="some_ets", -# b_port="port_b", -# ), -# DiagramLine(a_name="some_real_expression", a_port="y", b_name="some_ets", b_port="control_in"), -# ], -# } - -# # create expected nodes and their connections -# load_node = DiagramNode(load_a_id, "some_load", "load") -# ets_node = DiagramNode(ets_a_id, "some_ets", "ets") -# real_expression_node = DiagramNode(coupling_id, "some_real_expression", "real_expression") -# load_node.add_connection("port_a", ets_node, "port_b") -# ets_node.add_connection("port_b", load_node, "port_a") -# ets_node.add_connection("control_in", real_expression_node, "y") -# real_expression_node.add_connection("y", ets_node, "control_in") - -# expected_diagram_graph = { -# load_a_id: {"some_load": load_node}, -# ets_a_id: {"some_ets": ets_node}, -# coupling_id: {"some_real_expression": real_expression_node}, -# } - -# # Act -# diagram_graph = Diagram._diagram_commands_to_graph(diagram_commands_by_id, couplings) - -# # Assert -# assert expected_diagram_graph == diagram_graph +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import pytest + +from geojson_modelica_translator.model_connectors.couplings.diagram import Diagram, DiagramNode +from geojson_modelica_translator.model_connectors.couplings.utils import ( + DiagramLine, + DiagramTransformation, + parse_diagram_commands, +) +from tests.base_test_case import TestCaseBase + + +class MockCoupling: + def __init__(self, coupling_id, a, b): + self.id = coupling_id + self._model_a = a + self._model_b = b + + +class MockModel: + def __init__(self, model_id): + self.id = model_id + + +def mock_coupling_factory(coupling_id, model_a_id, model_b_id): + return MockCoupling(coupling_id=coupling_id, a=MockModel(model_a_id), b=MockModel(model_b_id)) + + +class DiagramGraphTest(TestCaseBase): + def test_parse_diagram_commands_parses_transformations(self): + # Setup + modelica_content = """ +model Simple + {{ ignored.context }} + Modelica.Blocks.Sources.RealExpression abc(y=1) + annnotation (Placement({{ diagram.transformation.abc.real_expression }})) +end Simple;""" + + # Act + commands = parse_diagram_commands(modelica_content) + + # Assert + assert len(commands) == 1 + cmd = commands[0] + assert isinstance(cmd, DiagramTransformation) + assert cmd.model_name == "abc" + assert cmd.model_type == "real_expression" + + def test_parse_diagram_commands_parses_lines(self): + # Setup + modelica_content = """ +model Simple + {{ ignored.context }} +equation + connect(abc.port_a, def.port_b) + annotation(Line({{ diagram.line.abc.port_a.def.port_b }})); +end Simple;""" + + # Act + commands = parse_diagram_commands(modelica_content) + + # Assert + assert len(commands) == 1 + cmd = commands[0] + assert isinstance(cmd, DiagramLine) + assert cmd.a_name == "abc" + assert cmd.a_port == "port_a" + assert cmd.b_name == "def" + assert cmd.b_port == "port_b" + + def test_parse_diagram_commands_errors_when_command_is_invalid(self): + # Setup + bad_transformation = "{{ diagram.transformation.bad }}" + bad_line = "{{ diagram.line.bad }}" + + # Act/Assert + with pytest.raises(TypeError, match='Invalid diagram templating command: "transformation".*'): + parse_diagram_commands(bad_transformation) + + with pytest.raises(TypeError, match='Invalid diagram templating command: "line".*'): + parse_diagram_commands(bad_line) + + def test_diagram_commands_to_graph_succeeds_for_transformations(self): + # Setup + load_a_id = "load_a" + ets_a_id = "ets_a" + coupling_id = "coupling_a" + load_ets_coupling = mock_coupling_factory(coupling_id, load_a_id, ets_a_id) + couplings = [ + load_ets_coupling, + ] + + diagram_commands_by_id = { + load_a_id: [ + DiagramTransformation( + model_name="some_load", + model_type="load", + ) + ], + ets_a_id: [ + DiagramTransformation( + model_name="some_ets", + model_type="ets", + ) + ], + # also create a transformation which is coupling specific (ie defined in a coupling template file) + coupling_id: [ + DiagramTransformation( + model_name="some_real_expression", + model_type="real_expression", + ) + ], + } + + expected_diagram_graph = { + load_a_id: {"some_load": DiagramNode(load_a_id, "some_load", "load")}, + ets_a_id: {"some_ets": DiagramNode(ets_a_id, "some_ets", "ets")}, + coupling_id: {"some_real_expression": DiagramNode(coupling_id, "some_real_expression", "real_expression")}, + } + + # Act + diagram_graph = Diagram._diagram_commands_to_graph(diagram_commands_by_id, couplings) + + # Assert + assert expected_diagram_graph == diagram_graph + + def test_diagram_commands_to_graph_succeeds_for_transformations_and_lines(self): + # Setup + load_a_id = "load_a" + ets_a_id = "ets_a" + coupling_id = "coupling_a" + load_ets_coupling = mock_coupling_factory(coupling_id, load_a_id, ets_a_id) + couplings = [ + load_ets_coupling, + ] + + diagram_commands_by_id = { + load_a_id: [ + DiagramTransformation( + model_name="some_load", + model_type="load", + ) + ], + ets_a_id: [ + DiagramTransformation( + model_name="some_ets", + model_type="ets", + ) + ], + coupling_id: [ + DiagramTransformation( + model_name="some_real_expression", + model_type="real_expression", + ), + # create lines which connect these components + DiagramLine( + a_name="some_load", + a_port="port_a", + b_name="some_ets", + b_port="port_b", + ), + DiagramLine(a_name="some_real_expression", a_port="y", b_name="some_ets", b_port="control_in"), + ], + } + + # create expected nodes and their connections + load_node = DiagramNode(load_a_id, "some_load", "load") + ets_node = DiagramNode(ets_a_id, "some_ets", "ets") + real_expression_node = DiagramNode(coupling_id, "some_real_expression", "real_expression") + load_node.add_connection("port_a", ets_node, "port_b") + ets_node.add_connection("port_b", load_node, "port_a") + ets_node.add_connection("control_in", real_expression_node, "y") + real_expression_node.add_connection("y", ets_node, "control_in") + + expected_diagram_graph = { + load_a_id: {"some_load": load_node}, + ets_a_id: {"some_ets": ets_node}, + coupling_id: {"some_real_expression": real_expression_node}, + } + + # Act + diagram_graph = Diagram._diagram_commands_to_graph(diagram_commands_by_id, couplings) + + # Assert + assert expected_diagram_graph == diagram_graph diff --git a/tests/model_connectors/test_district_5g.py b/tests/model_connectors/test_district_5g.py index 512cc5ddc..9cbd5748c 100644 --- a/tests/model_connectors/test_district_5g.py +++ b/tests/model_connectors/test_district_5g.py @@ -1,61 +1,61 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# from geojson_modelica_translator.model_connectors.networks.network_ambient_water_stub import NetworkAmbientWaterStub -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +from geojson_modelica_translator.model_connectors.networks.network_ambient_water_stub import NetworkAmbientWaterStub +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class DistrictSystemTest(TestCaseBase): -# def setUp(self): -# super().setUp() +class DistrictSystemTest(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "fifth_generation_district" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "fifth_generation_district" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_5g_sys_params.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "time_series_5g_sys_params.json" + sys_params = SystemParameters(filename) -# # create ambient water stub -# ambient_water_stub = NetworkAmbientWaterStub(sys_params) + # create ambient water stub + ambient_water_stub = NetworkAmbientWaterStub(sys_params) -# # create our our load/ets/stubs -# all_couplings = [] -# for geojson_load in self.gj.buildings: -# time_series_load = TimeSeries(sys_params, geojson_load) -# all_couplings.append(Coupling(time_series_load, ambient_water_stub, district_type="fifth_generation")) + # create our our load/ets/stubs + all_couplings = [] + for geojson_load in self.gj.buildings: + time_series_load = TimeSeries(sys_params, geojson_load) + all_couplings.append(Coupling(time_series_load, ambient_water_stub, district_type="fifth_generation")) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) -# self.district.to_modelica() + self.district.to_modelica() -# def test_build_district_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_district_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# def test_simulate_district_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# ) + @pytest.mark.simulation + def test_simulate_district_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + ) diff --git a/tests/model_connectors/test_district_cooling_system.py b/tests/model_connectors/test_district_cooling_system.py index 2100e4187..c940f1990 100644 --- a/tests/model_connectors/test_district_cooling_system.py +++ b/tests/model_connectors/test_district_cooling_system.py @@ -1,71 +1,71 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants.cooling_plant import CoolingPlant -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe +from geojson_modelica_translator.model_connectors.plants.cooling_plant import CoolingPlant +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# @pytest.mark.simulation -# class DistrictCoolingSystemTest(TestCaseBase): -# def setUp(self): -# # TODO: remove all the unittest stuff since we use pytest -# super().setUp() +@pytest.mark.simulation +class DistrictCoolingSystemTest(TestCaseBase): + def setUp(self): + # TODO: remove all the unittest stuff since we use pytest + super().setUp() -# project_name = "district_cooling_system" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "district_cooling_system" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# params_filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(params_filename) + # load system parameter data + params_filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(params_filename) -# # create network and plant -# network = Network2Pipe(sys_params) -# cooling_plant = CoolingPlant(sys_params) + # create network and plant + network = Network2Pipe(sys_params) + cooling_plant = CoolingPlant(sys_params) -# # create our our load/ets/stubs -# all_couplings = [Coupling(network, cooling_plant)] -# for geojson_load in self.gj.buildings: -# time_series_load = TimeSeries(sys_params, geojson_load) -# geojson_load_id = geojson_load.feature.properties["id"] -# cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) -# hot_water_stub = EtsHotWaterStub(sys_params) -# all_couplings.append(Coupling(time_series_load, cooling_indirect_system)) -# all_couplings.append(Coupling(time_series_load, hot_water_stub)) -# all_couplings.append(Coupling(cooling_indirect_system, network)) + # create our our load/ets/stubs + all_couplings = [Coupling(network, cooling_plant)] + for geojson_load in self.gj.buildings: + time_series_load = TimeSeries(sys_params, geojson_load) + geojson_load_id = geojson_load.feature.properties["id"] + cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) + hot_water_stub = EtsHotWaterStub(sys_params) + all_couplings.append(Coupling(time_series_load, cooling_indirect_system)) + all_couplings.append(Coupling(time_series_load, hot_water_stub)) + all_couplings.append(Coupling(cooling_indirect_system, network)) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() -# def test_build_district_cooling_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_district_cooling_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# def test_simulate_district_cooling_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# ) + @pytest.mark.simulation + def test_simulate_district_cooling_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + ) diff --git a/tests/model_connectors/test_district_heating_and_cooling_systems.py b/tests/model_connectors/test_district_heating_and_cooling_systems.py index 144f41c41..20d71bcab 100644 --- a/tests/model_connectors/test_district_heating_and_cooling_systems.py +++ b/tests/model_connectors/test_district_heating_and_cooling_systems.py @@ -1,164 +1,164 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import numpy as np -# import pytest -# from buildingspy.io.outputfile import Reader - -# 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 TimeSeries -# from geojson_modelica_translator.model_connectors.networks import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants import CoolingPlant -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class DistrictHeatingAndCoolingSystemsTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# self.project_name = "district_heating_and_cooling_systems" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# self.sys_params = SystemParameters(filename) - -# # create cooling network and plant -# cooling_network = Network2Pipe(self.sys_params) -# cooling_plant = CoolingPlant(self.sys_params) - -# # create heating network and plant -# heating_network = Network2Pipe(self.sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) - -# # create our load/ets/stubs -# # store all couplings to construct the District system -# all_couplings = [ -# Coupling(cooling_network, cooling_plant), -# Coupling(heating_network, heating_plant), -# ] - -# # keep track of separate loads and etses for testing purposes -# self.loads = [] -# heat_etses = [] -# cool_etses = [] -# for geojson_load in self.gj.buildings: -# time_series_load = TimeSeries(self.sys_params, geojson_load) -# self.loads.append(time_series_load) -# geojson_load_id = geojson_load.feature.properties["id"] - -# cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) -# cool_etses.append(cooling_indirect) -# all_couplings.append(Coupling(time_series_load, cooling_indirect)) -# all_couplings.append(Coupling(cooling_indirect, cooling_network)) - -# heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) -# heat_etses.append(heating_indirect) -# all_couplings.append(Coupling(time_series_load, heating_indirect)) -# all_couplings.append(Coupling(heating_indirect, heating_network)) - -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) - -# self.district = District( -# root_dir=self.output_dir, -# project_name=self.project_name, -# system_parameters=self.sys_params, -# coupling_graph=graph, -# ) -# self.district.to_modelica() - -# def test_build_district_heating_and_cooling_systems(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# # FIXME: Skipping this until spawn modelica is able to compile the model with success -# # @pytest.mark.compilation -# # def test_compile_district_heating_and_cooling_systems(self): -# # root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# # self.compile_and_assert_in_docker(Path(root_path) / 'DistrictEnergySystem.mo', -# # project_path=self.district._scaffold.project_path, -# # project_name=self.district._scaffold.project_name) - -# @pytest.mark.simulation -# @pytest.mark.skip(reason="Works with qss solver, but not with dassl") -# def test_simulate_district_heating_and_cooling_systems(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=90, # (in seconds) -# ) - -# # -# # Validate model outputs -# # -# results_dir = ( -# f"{self.district._scaffold.project_path}/{self.project_name}.Districts.DistrictEnergySystem_results" -# ) -# mat_file = f"{results_dir}/{self.project_name}.Districts.DistrictEnergySystem_res.mat" -# mat_results = Reader(mat_file, "dymola") - -# # check the mass flow rates of the first load are in the expected range -# load = self.loads[0] -# (_, heat_m_flow) = mat_results.values(f"{load.id}.ports_aHeaWat[1].m_flow") -# # NL: changed the line below to be aChiWat (not repeating aHeaWat). -# (_, cool_m_flow) = mat_results.values(f"{load.id}.ports_aChiWat[1].m_flow") -# assert (heat_m_flow >= 0).all(), "Heating mass flow rate must be greater than or equal to zero" -# assert (cool_m_flow >= 0).all(), "Cooling mass flow rate must be greater than or equal to zero" - -# # this tolerance determines how much we allow the actual mass flow rate to exceed the nominal value -# m_flow_nominal_tolerance = 0.01 -# (_, heat_m_flow_nominal) = mat_results.values(f"{load.id}.mHeaWat_flow_nominal") -# heat_m_flow_nominal = heat_m_flow_nominal[0] -# (_, cool_m_flow_nominal) = mat_results.values(f"{load.id}.mChiWat_flow_nominal") -# cool_m_flow_nominal = cool_m_flow_nominal[0] - -# assert heat_m_flow <= pytest.approx(heat_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( -# f"Heating mass flow rate must be less than nominal " -# f"mass flow rate ({heat_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" -# ) - -# assert cool_m_flow <= pytest.approx(cool_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( -# "Cooling mass flow rate must be less than nominal " -# f"mass flow rate ({cool_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" -# ) - -# # check the thermal load -# (_, load_q_req_hea_flow) = mat_results.values(f"{load.id}.QReqHea_flow") -# (_, load_q_req_coo_flow) = mat_results.values(f"{load.id}.QReqCoo_flow") -# (_, load_q_heat_flow) = mat_results.values(f"{load.id}.QHea_flow") -# (_, load_q_cool_flow) = mat_results.values(f"{load.id}.QCoo_flow") - -# # make sure the q flow is positive -# load_q_req_hea_flow, load_q_req_coo_flow = np.abs(load_q_req_hea_flow), np.abs(load_q_req_coo_flow) -# load_q_heat_flow, load_q_cool_flow = np.abs(load_q_heat_flow), np.abs(load_q_cool_flow) - -# cool_cvrmsd = self.cvrmsd(load_q_cool_flow, load_q_req_coo_flow) -# heat_cvrmsd = self.cvrmsd(load_q_heat_flow, load_q_req_hea_flow) - -# cvrmsd_max = 0.3 -# # TODO: fix q flows to meet the CVRMSD maximum, then make these assertions rather than warnings -# if cool_cvrmsd >= cvrmsd_max: -# print( -# "WARNING: The difference between the thermal cooling load of the load and ETS is too large " -# f"(CVRMSD={cool_cvrmsd}). TODO: make this warning an assertion." -# ) -# if heat_cvrmsd >= cvrmsd_max: -# print( -# "WARNING: The difference between the thermal heating load of the load and ETS is too large " -# f"(CVRMSD={heat_cvrmsd}). TODO: make this warning an assertion." -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import numpy as np +import pytest +from buildingspy.io.outputfile import Reader + +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 TimeSeries +from geojson_modelica_translator.model_connectors.networks import Network2Pipe +from geojson_modelica_translator.model_connectors.plants import CoolingPlant +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class DistrictHeatingAndCoolingSystemsTest(TestCaseBase): + def setUp(self): + super().setUp() + + self.project_name = "district_heating_and_cooling_systems" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + self.sys_params = SystemParameters(filename) + + # create cooling network and plant + cooling_network = Network2Pipe(self.sys_params) + cooling_plant = CoolingPlant(self.sys_params) + + # create heating network and plant + heating_network = Network2Pipe(self.sys_params) + heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) + + # create our load/ets/stubs + # store all couplings to construct the District system + all_couplings = [ + Coupling(cooling_network, cooling_plant), + Coupling(heating_network, heating_plant), + ] + + # keep track of separate loads and etses for testing purposes + self.loads = [] + heat_etses = [] + cool_etses = [] + for geojson_load in self.gj.buildings: + time_series_load = TimeSeries(self.sys_params, geojson_load) + self.loads.append(time_series_load) + geojson_load_id = geojson_load.feature.properties["id"] + + cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) + cool_etses.append(cooling_indirect) + all_couplings.append(Coupling(time_series_load, cooling_indirect)) + all_couplings.append(Coupling(cooling_indirect, cooling_network)) + + heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) + heat_etses.append(heating_indirect) + all_couplings.append(Coupling(time_series_load, heating_indirect)) + all_couplings.append(Coupling(heating_indirect, heating_network)) + + # create the couplings and graph + graph = CouplingGraph(all_couplings) + + self.district = District( + root_dir=self.output_dir, + project_name=self.project_name, + system_parameters=self.sys_params, + coupling_graph=graph, + ) + self.district.to_modelica() + + def test_build_district_heating_and_cooling_systems(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + # FIXME: Skipping this until spawn modelica is able to compile the model with success + # @pytest.mark.compilation + # def test_compile_district_heating_and_cooling_systems(self): + # root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + # self.compile_and_assert_in_docker(Path(root_path) / 'DistrictEnergySystem.mo', + # project_path=self.district._scaffold.project_path, + # project_name=self.district._scaffold.project_name) + + @pytest.mark.simulation + @pytest.mark.skip(reason="Works with qss solver, but not with dassl") + def test_simulate_district_heating_and_cooling_systems(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=90, # (in seconds) + ) + + # + # Validate model outputs + # + results_dir = ( + f"{self.district._scaffold.project_path}/{self.project_name}.Districts.DistrictEnergySystem_results" + ) + mat_file = f"{results_dir}/{self.project_name}.Districts.DistrictEnergySystem_res.mat" + mat_results = Reader(mat_file, "dymola") + + # check the mass flow rates of the first load are in the expected range + load = self.loads[0] + (_, heat_m_flow) = mat_results.values(f"{load.id}.ports_aHeaWat[1].m_flow") + # NL: changed the line below to be aChiWat (not repeating aHeaWat). + (_, cool_m_flow) = mat_results.values(f"{load.id}.ports_aChiWat[1].m_flow") + assert (heat_m_flow >= 0).all(), "Heating mass flow rate must be greater than or equal to zero" + assert (cool_m_flow >= 0).all(), "Cooling mass flow rate must be greater than or equal to zero" + + # this tolerance determines how much we allow the actual mass flow rate to exceed the nominal value + m_flow_nominal_tolerance = 0.01 + (_, heat_m_flow_nominal) = mat_results.values(f"{load.id}.mHeaWat_flow_nominal") + heat_m_flow_nominal = heat_m_flow_nominal[0] + (_, cool_m_flow_nominal) = mat_results.values(f"{load.id}.mChiWat_flow_nominal") + cool_m_flow_nominal = cool_m_flow_nominal[0] + + assert heat_m_flow <= pytest.approx(heat_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( + f"Heating mass flow rate must be less than nominal " + f"mass flow rate ({heat_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" + ) + + assert cool_m_flow <= pytest.approx(cool_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( + "Cooling mass flow rate must be less than nominal " + f"mass flow rate ({cool_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" + ) + + # check the thermal load + (_, load_q_req_hea_flow) = mat_results.values(f"{load.id}.QReqHea_flow") + (_, load_q_req_coo_flow) = mat_results.values(f"{load.id}.QReqCoo_flow") + (_, load_q_heat_flow) = mat_results.values(f"{load.id}.QHea_flow") + (_, load_q_cool_flow) = mat_results.values(f"{load.id}.QCoo_flow") + + # make sure the q flow is positive + load_q_req_hea_flow, load_q_req_coo_flow = np.abs(load_q_req_hea_flow), np.abs(load_q_req_coo_flow) + load_q_heat_flow, load_q_cool_flow = np.abs(load_q_heat_flow), np.abs(load_q_cool_flow) + + cool_cvrmsd = self.cvrmsd(load_q_cool_flow, load_q_req_coo_flow) + heat_cvrmsd = self.cvrmsd(load_q_heat_flow, load_q_req_hea_flow) + + cvrmsd_max = 0.3 + # TODO: fix q flows to meet the CVRMSD maximum, then make these assertions rather than warnings + if cool_cvrmsd >= cvrmsd_max: + print( + "WARNING: The difference between the thermal cooling load of the load and ETS is too large " + f"(CVRMSD={cool_cvrmsd}). TODO: make this warning an assertion." + ) + if heat_cvrmsd >= cvrmsd_max: + print( + "WARNING: The difference between the thermal heating load of the load and ETS is too large " + f"(CVRMSD={heat_cvrmsd}). TODO: make this warning an assertion." + ) diff --git a/tests/model_connectors/test_district_heating_system.py b/tests/model_connectors/test_district_heating_system.py index f98c51251..f1a1e399d 100644 --- a/tests/model_connectors/test_district_heating_system.py +++ b/tests/model_connectors/test_district_heating_system.py @@ -1,72 +1,72 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub +from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class DistrictHeatingSystemNewTest(TestCaseBase): -# def setUp(self): -# super().setUp() +class DistrictHeatingSystemNewTest(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "district_heating_system" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "district_heating_system" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(filename) -# # create network and plant -# network = Network2Pipe(sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(sys_params) + # create network and plant + network = Network2Pipe(sys_params) + heating_plant = HeatingPlantWithOptionalCHP(sys_params) -# # create our our load/ets/stubs -# all_couplings = [Coupling(network, heating_plant)] -# for geojson_load in self.gj.buildings: -# time_series_load = TimeSeries(sys_params, geojson_load) -# geojson_load_id = geojson_load.feature.properties["id"] -# heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) -# cold_water_stub = EtsColdWaterStub(sys_params) -# all_couplings.append(Coupling(time_series_load, heating_indirect_system)) -# all_couplings.append(Coupling(time_series_load, cold_water_stub)) -# all_couplings.append(Coupling(heating_indirect_system, network)) + # create our our load/ets/stubs + all_couplings = [Coupling(network, heating_plant)] + for geojson_load in self.gj.buildings: + time_series_load = TimeSeries(sys_params, geojson_load) + geojson_load_id = geojson_load.feature.properties["id"] + heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) + cold_water_stub = EtsColdWaterStub(sys_params) + all_couplings.append(Coupling(time_series_load, heating_indirect_system)) + all_couplings.append(Coupling(time_series_load, cold_water_stub)) + all_couplings.append(Coupling(heating_indirect_system, network)) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() -# def test_build_district_heating_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_district_heating_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# def test_simulate_district_heating_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # At 1 hour step size (in seconds) -# ) + @pytest.mark.simulation + def test_simulate_district_heating_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # At 1 hour step size (in seconds) + ) diff --git a/tests/model_connectors/test_district_multi_ghe.py b/tests/model_connectors/test_district_multi_ghe.py index 59a1e947a..44e4df35f 100644 --- a/tests/model_connectors/test_district_multi_ghe.py +++ b/tests/model_connectors/test_district_multi_ghe.py @@ -1,109 +1,109 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest - -# 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.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# 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.borefield import Borefield -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class DistrictSystemTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# project_name = "district_multi_ghe" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with multiple buildings -# geojson_filename = Path(self.data_dir) / "sdk_output_skeleton_13_buildings" / "exportGeo.json" -# self.gj = UrbanOptGeoJson(geojson_filename) - -# # load system parameter data -# sys_param_filename = ( -# Path(self.data_dir) -# / "sdk_output_skeleton_13_buildings" -# / "run" -# / "baseline_scenario" -# / "ghe_dir" -# / "sys_params_proportional.json" -# ) -# sys_params = SystemParameters(sys_param_filename) - -# # read the loop order and create building groups -# loop_order = load_loop_order(sys_param_filename) - -# # create ambient water stub -# ambient_water_stub = NetworkDistributionPump(sys_params) - -# # create ground coupling -# ground_coupling = GroundCoupling(sys_params) - -# # create district data -# design_data = DesignDataSeries(sys_params) - -# # create the couplings and graph -# all_couplings = [] -# 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 self.gj.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")) - -# graph = CouplingGraph(all_couplings) - -# self.district = District( -# root_dir=self.output_dir, -# project_name=project_name, -# system_parameters=sys_params, -# geojson_file=self.gj, -# coupling_graph=graph, -# ) - -# self.district.to_modelica() - -# def test_build_multi_ghe_district(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# @pytest.mark.skip(reason="Model is too large for OM. Simulates as expected using Dymola") -# @pytest.mark.dymola -# # TODO: Improve simulation with OM to enable running this test natively -# def test_simulate_multi_ghe_district(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# run_path=self.district._scaffold.project_path, -# file_to_load=self.district._scaffold.package_path, -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest + +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.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +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.borefield import Borefield +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class DistrictSystemTest(TestCaseBase): + def setUp(self): + super().setUp() + + project_name = "district_multi_ghe" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with multiple buildings + geojson_filename = Path(self.data_dir) / "sdk_output_skeleton_13_buildings" / "exportGeo.json" + self.gj = UrbanOptGeoJson(geojson_filename) + + # load system parameter data + sys_param_filename = ( + Path(self.data_dir) + / "sdk_output_skeleton_13_buildings" + / "run" + / "baseline_scenario" + / "ghe_dir" + / "sys_params_proportional.json" + ) + sys_params = SystemParameters(sys_param_filename) + + # read the loop order and create building groups + loop_order = load_loop_order(sys_param_filename) + + # create ambient water stub + ambient_water_stub = NetworkDistributionPump(sys_params) + + # create ground coupling + ground_coupling = GroundCoupling(sys_params) + + # create district data + design_data = DesignDataSeries(sys_params) + + # create the couplings and graph + all_couplings = [] + 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 self.gj.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")) + + graph = CouplingGraph(all_couplings) + + self.district = District( + root_dir=self.output_dir, + project_name=project_name, + system_parameters=sys_params, + geojson_file=self.gj, + coupling_graph=graph, + ) + + self.district.to_modelica() + + def test_build_multi_ghe_district(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + @pytest.mark.skip(reason="Model is too large for OM. Simulates as expected using Dymola") + @pytest.mark.dymola + # TODO: Improve simulation with OM to enable running this test natively + def test_simulate_multi_ghe_district(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + run_path=self.district._scaffold.project_path, + file_to_load=self.district._scaffold.package_path, + ) diff --git a/tests/model_connectors/test_district_system.py b/tests/model_connectors/test_district_system.py index 8aef02e31..596bb49d9 100644 --- a/tests/model_connectors/test_district_system.py +++ b/tests/model_connectors/test_district_system.py @@ -1,72 +1,72 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# from geojson_modelica_translator.model_connectors.networks.network_chilled_water_stub import NetworkChilledWaterStub -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +from geojson_modelica_translator.model_connectors.networks.network_chilled_water_stub import NetworkChilledWaterStub +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class DistrictSystemTest(TestCaseBase): -# def setUp(self): -# super().setUp() +class DistrictSystemTest(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "district_system" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "district_system" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(filename) -# # Create the time series load, ets and their coupling -# time_series_load = TimeSeries(sys_params, self.gj.buildings[0]) -# geojson_load_id = self.gj.buildings[0].feature.properties["id"] -# cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) -# ts_ci_coupling = Coupling(time_series_load, cooling_indirect_system) + # Create the time series load, ets and their coupling + time_series_load = TimeSeries(sys_params, self.gj.buildings[0]) + geojson_load_id = self.gj.buildings[0].feature.properties["id"] + cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) + ts_ci_coupling = Coupling(time_series_load, cooling_indirect_system) -# # create chilled water stub for the ets -# chilled_water_stub = NetworkChilledWaterStub(sys_params) -# ci_cw_coupling = Coupling(cooling_indirect_system, chilled_water_stub) + # create chilled water stub for the ets + chilled_water_stub = NetworkChilledWaterStub(sys_params) + ci_cw_coupling = Coupling(cooling_indirect_system, chilled_water_stub) -# # create hot water stub for the load -# hot_water_stub = EtsHotWaterStub(sys_params) -# ts_hw_coupling = Coupling(time_series_load, hot_water_stub) + # create hot water stub for the load + hot_water_stub = EtsHotWaterStub(sys_params) + ts_hw_coupling = Coupling(time_series_load, hot_water_stub) -# graph = CouplingGraph( -# [ -# ts_ci_coupling, -# ci_cw_coupling, -# ts_hw_coupling, -# ] -# ) + graph = CouplingGraph( + [ + ts_ci_coupling, + ci_cw_coupling, + ts_hw_coupling, + ] + ) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() -# def test_build_district_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_district_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# def test_simulate_district_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# ) + @pytest.mark.simulation + def test_simulate_district_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + ) diff --git a/tests/model_connectors/test_heated_water_plant.py b/tests/model_connectors/test_heated_water_plant.py index 5e1ed0445..cf994b1ed 100644 --- a/tests/model_connectors/test_heated_water_plant.py +++ b/tests/model_connectors/test_heated_water_plant.py @@ -1,58 +1,58 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest - -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.networks.network_heated_water_stub import NetworkHeatedWaterStub -# from geojson_modelica_translator.model_connectors.plants import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class DistrictSystemTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# project_name = "heated_water_plant_stub" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(filename) - -# heating_plant = HeatingPlantWithOptionalCHP(sys_params) -# heated_water_stub = NetworkHeatedWaterStub(sys_params) -# hp_hw_coupling = Coupling(heating_plant, heated_water_stub) - -# graph = CouplingGraph( -# [ -# hp_hw_coupling, -# ] -# ) - -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() - -# def test_build_district_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# def test_simulate_district_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest + +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.networks.network_heated_water_stub import NetworkHeatedWaterStub +from geojson_modelica_translator.model_connectors.plants import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class DistrictSystemTest(TestCaseBase): + def setUp(self): + super().setUp() + + project_name = "heated_water_plant_stub" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(filename) + + heating_plant = HeatingPlantWithOptionalCHP(sys_params) + heated_water_stub = NetworkHeatedWaterStub(sys_params) + hp_hw_coupling = Coupling(heating_plant, heated_water_stub) + + graph = CouplingGraph( + [ + hp_hw_coupling, + ] + ) + + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() + + def test_build_district_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + def test_simulate_district_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + ) diff --git a/tests/model_connectors/test_heating_indirect.py b/tests/model_connectors/test_heating_indirect.py index 98869afca..97e34d42a 100644 --- a/tests/model_connectors/test_heating_indirect.py +++ b/tests/model_connectors/test_heating_indirect.py @@ -1,42 +1,42 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# from modelica_builder.package_parser import PackageParser - -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect -# from geojson_modelica_translator.scaffold import Scaffold -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class HeatingIndirectTest(TestCaseBase): -# def test_heating_indirect(self): -# project_name = "heating_indirect" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) -# # scaffold the project ourselves -# scaffold = Scaffold(self.output_dir, project_name) -# scaffold.create() - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(filename) - -# # currently we must setup the root project before we can run to_modelica -# package = PackageParser.new_from_template(scaffold.project_path, scaffold.project_name, order=[]) -# package.save() -# # now test the connector (independent of the larger geojson translator) -# geojson_load_id = self.gj.buildings[0].feature.properties["id"] -# self.heating_indirect = HeatingIndirect(sys_params, geojson_load_id) -# self.heating_indirect.to_modelica(scaffold) - -# root_path = Path(scaffold.substations_path.files_dir).resolve() -# geojson_id = self.gj.buildings[0].feature.properties["id"] -# model_filepath = Path(root_path) / f"HeatingIndirect_{geojson_id}.mo" -# assert Path(model_filepath).exists(), f"File does not exist: {model_filepath}" +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +from modelica_builder.package_parser import PackageParser + +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect +from geojson_modelica_translator.scaffold import Scaffold +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class HeatingIndirectTest(TestCaseBase): + def test_heating_indirect(self): + project_name = "heating_indirect" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + # scaffold the project ourselves + scaffold = Scaffold(self.output_dir, project_name) + scaffold.create() + + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(filename) + + # currently we must setup the root project before we can run to_modelica + package = PackageParser.new_from_template(scaffold.project_path, scaffold.project_name, order=[]) + package.save() + # now test the connector (independent of the larger geojson translator) + geojson_load_id = self.gj.buildings[0].feature.properties["id"] + self.heating_indirect = HeatingIndirect(sys_params, geojson_load_id) + self.heating_indirect.to_modelica(scaffold) + + root_path = Path(scaffold.substations_path.files_dir).resolve() + geojson_id = self.gj.buildings[0].feature.properties["id"] + model_filepath = Path(root_path) / f"HeatingIndirect_{geojson_id}.mo" + assert Path(model_filepath).exists(), f"File does not exist: {model_filepath}" diff --git a/tests/model_connectors/test_mixed_loads.py b/tests/model_connectors/test_mixed_loads.py index b43aae819..e14da589c 100644 --- a/tests/model_connectors/test_mixed_loads.py +++ b/tests/model_connectors/test_mixed_loads.py @@ -1,101 +1,101 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest - -# 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 -# from geojson_modelica_translator.model_connectors.networks import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants import CoolingPlant -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# @pytest.mark.simulation -# class MixedLoadsTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# self.project_name = "mixed_loads" -# _, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) - -# filename = self.SHARED_DATA_DIR / "mixed_loads_district" / "geojson.json" -# self.gj = UrbanOptGeoJson(filename) - -# # load system parameter data -# filename = self.SHARED_DATA_DIR / "mixed_loads_district" / "system_params.json" -# self.sys_params = SystemParameters(filename) - -# # create cooling network and plant -# cooling_network = Network2Pipe(self.sys_params) -# cooling_plant = CoolingPlant(self.sys_params) - -# # create heating network and plant -# heating_network = Network2Pipe(self.sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) - -# # store all couplings to construct the District system -# all_couplings = [ -# Coupling(cooling_network, cooling_plant), -# Coupling(heating_network, heating_plant), -# ] - -# # keep track of separate loads and etses for testing purposes -# loads = [] -# heat_etses = [] -# cool_etses = [] -# load_model_map = {"spawn": Spawn, "rc": Teaser, "time_series": TimeSeries} -# for geojson_load in self.gj.buildings: -# load_model_name = self.sys_params.get_param_by_id(geojson_load.id, "load_model") -# load_model = load_model_map[load_model_name] -# load = load_model(self.sys_params, geojson_load) -# loads.append(load) -# geojson_load_id = geojson_load.feature.properties["id"] - -# cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) -# cool_etses.append(cooling_indirect) -# all_couplings.append(Coupling(load, cooling_indirect)) -# all_couplings.append(Coupling(cooling_indirect, cooling_network)) - -# heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) -# heat_etses.append(heating_indirect) -# all_couplings.append(Coupling(load, heating_indirect)) -# all_couplings.append(Coupling(heating_indirect, heating_network)) - -# # verify we used all load types in the model -# used_classes = [type(x) for x in loads] -# for expected_load in load_model_map.values(): -# assert expected_load in used_classes - -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) - -# self.district = District( -# root_dir=self.output_dir, -# project_name=self.project_name, -# system_parameters=self.sys_params, -# coupling_graph=graph, -# ) -# self.district.to_modelica() - -# def test_build_mixed_loads_district_energy_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# @pytest.mark.skip("OMC Spawn - Failed to find spawn executable in Buildings Library") -# def test_simulate_mixed_loads_district_energy_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # (in seconds) -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest + +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 +from geojson_modelica_translator.model_connectors.networks import Network2Pipe +from geojson_modelica_translator.model_connectors.plants import CoolingPlant +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +@pytest.mark.simulation +class MixedLoadsTest(TestCaseBase): + def setUp(self): + super().setUp() + + self.project_name = "mixed_loads" + _, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) + + filename = self.SHARED_DATA_DIR / "mixed_loads_district" / "geojson.json" + self.gj = UrbanOptGeoJson(filename) + + # load system parameter data + filename = self.SHARED_DATA_DIR / "mixed_loads_district" / "system_params.json" + self.sys_params = SystemParameters(filename) + + # create cooling network and plant + cooling_network = Network2Pipe(self.sys_params) + cooling_plant = CoolingPlant(self.sys_params) + + # create heating network and plant + heating_network = Network2Pipe(self.sys_params) + heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) + + # store all couplings to construct the District system + all_couplings = [ + Coupling(cooling_network, cooling_plant), + Coupling(heating_network, heating_plant), + ] + + # keep track of separate loads and etses for testing purposes + loads = [] + heat_etses = [] + cool_etses = [] + load_model_map = {"spawn": Spawn, "rc": Teaser, "time_series": TimeSeries} + for geojson_load in self.gj.buildings: + load_model_name = self.sys_params.get_param_by_id(geojson_load.id, "load_model") + load_model = load_model_map[load_model_name] + load = load_model(self.sys_params, geojson_load) + loads.append(load) + geojson_load_id = geojson_load.feature.properties["id"] + + cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) + cool_etses.append(cooling_indirect) + all_couplings.append(Coupling(load, cooling_indirect)) + all_couplings.append(Coupling(cooling_indirect, cooling_network)) + + heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) + heat_etses.append(heating_indirect) + all_couplings.append(Coupling(load, heating_indirect)) + all_couplings.append(Coupling(heating_indirect, heating_network)) + + # verify we used all load types in the model + used_classes = [type(x) for x in loads] + for expected_load in load_model_map.values(): + assert expected_load in used_classes + + # create the couplings and graph + graph = CouplingGraph(all_couplings) + + self.district = District( + root_dir=self.output_dir, + project_name=self.project_name, + system_parameters=self.sys_params, + coupling_graph=graph, + ) + self.district.to_modelica() + + def test_build_mixed_loads_district_energy_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + @pytest.mark.skip("OMC Spawn - Failed to find spawn executable in Buildings Library") + def test_simulate_mixed_loads_district_energy_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # (in seconds) + ) diff --git a/tests/model_connectors/test_spawn.py b/tests/model_connectors/test_spawn.py index 0a6bba7ca..de8038059 100644 --- a/tests/model_connectors/test_spawn.py +++ b/tests/model_connectors/test_spawn.py @@ -1,66 +1,66 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub -# from geojson_modelica_translator.model_connectors.load_connectors.spawn import Spawn -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub +from geojson_modelica_translator.model_connectors.load_connectors.spawn import Spawn +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class SpawnModelConnectorSingleBuildingTest(TestCaseBase): -# def setUp(self): -# super().setUp() +class SpawnModelConnectorSingleBuildingTest(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "spawn_single" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "spawn_single" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "spawn_geojson_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "spawn_geojson_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "spawn_system_params_ex1.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "spawn_system_params_ex1.json" + sys_params = SystemParameters(filename) -# # build spawn model with hot and cold water stubbed out -# spawn = Spawn(sys_params, self.gj.buildings[0]) -# hot_stub = EtsHotWaterStub(sys_params) -# cold_stub = EtsColdWaterStub(sys_params) + # build spawn model with hot and cold water stubbed out + spawn = Spawn(sys_params, self.gj.buildings[0]) + hot_stub = EtsHotWaterStub(sys_params) + cold_stub = EtsColdWaterStub(sys_params) -# graph = CouplingGraph( -# [ -# Coupling(spawn, hot_stub), -# Coupling(spawn, cold_stub), -# ] -# ) + graph = CouplingGraph( + [ + Coupling(spawn, hot_stub), + Coupling(spawn, cold_stub), + ] + ) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) -# self.district.to_modelica() + self.district.to_modelica() -# def test_build_spawn_cooling(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_spawn_cooling(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") -# def test_simulate_spawn_single(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # (in seconds) -# ) + @pytest.mark.simulation + @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") + def test_simulate_spawn_single(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # (in seconds) + ) diff --git a/tests/model_connectors/test_spawn_cooling.py b/tests/model_connectors/test_spawn_cooling.py index bb2fe891a..006e094ba 100644 --- a/tests/model_connectors/test_spawn_cooling.py +++ b/tests/model_connectors/test_spawn_cooling.py @@ -1,73 +1,73 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub -# from geojson_modelica_translator.model_connectors.load_connectors.spawn import Spawn -# from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants.cooling_plant import CoolingPlant -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub +from geojson_modelica_translator.model_connectors.load_connectors.spawn import Spawn +from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe +from geojson_modelica_translator.model_connectors.plants.cooling_plant import CoolingPlant +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class TestSpawnCooling(TestCaseBase): -# def setUp(self): -# super().setUp() +class TestSpawnCooling(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "spawn_district_cooling" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "spawn_district_cooling" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "spawn_geojson_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "spawn_geojson_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "spawn_system_params_ex1.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "spawn_system_params_ex1.json" + sys_params = SystemParameters(filename) -# # create network and plant -# network = Network2Pipe(sys_params) -# cooling_plant = CoolingPlant(sys_params) + # create network and plant + network = Network2Pipe(sys_params) + cooling_plant = CoolingPlant(sys_params) -# # create our our load/ets/stubs -# all_couplings = [Coupling(network, cooling_plant)] -# for geojson_load in self.gj.buildings: -# spawn_load = Spawn(sys_params, geojson_load) -# geojson_load_id = geojson_load.feature.properties["id"] -# cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) -# hot_water_stub = EtsHotWaterStub(sys_params) -# all_couplings.append(Coupling(spawn_load, cooling_indirect_system)) -# all_couplings.append(Coupling(spawn_load, hot_water_stub)) -# all_couplings.append(Coupling(cooling_indirect_system, network)) + # create our our load/ets/stubs + all_couplings = [Coupling(network, cooling_plant)] + for geojson_load in self.gj.buildings: + spawn_load = Spawn(sys_params, geojson_load) + geojson_load_id = geojson_load.feature.properties["id"] + cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) + hot_water_stub = EtsHotWaterStub(sys_params) + all_couplings.append(Coupling(spawn_load, cooling_indirect_system)) + all_couplings.append(Coupling(spawn_load, hot_water_stub)) + all_couplings.append(Coupling(cooling_indirect_system, network)) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() -# def test_build_spawn_cooling(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_spawn_cooling(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") -# def test_simulate_spawn_cooling(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # (in seconds) -# ) + @pytest.mark.simulation + @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") + def test_simulate_spawn_cooling(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # (in seconds) + ) diff --git a/tests/model_connectors/test_spawn_district_heating_and_cooling_systems.py b/tests/model_connectors/test_spawn_district_heating_and_cooling_systems.py index 1f704e71e..df5533b79 100644 --- a/tests/model_connectors/test_spawn_district_heating_and_cooling_systems.py +++ b/tests/model_connectors/test_spawn_district_heating_and_cooling_systems.py @@ -1,126 +1,126 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest -# from buildingspy.io.outputfile import Reader - -# 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 -# from geojson_modelica_translator.model_connectors.networks import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants import CoolingPlant -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class DistrictHeatingAndCoolingSystemsTest(TestCaseBase): -# def setUp(self): -# self.project_name = "spawn_district_heating_and_cooling_systems" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) - -# filename = Path(self.data_dir) / "spawn_geojson_ex1.json" -# self.gj = UrbanOptGeoJson(filename) - -# # load system parameter data -# filename = Path(self.data_dir) / "spawn_system_params_ex1.json" -# self.sys_params = SystemParameters(filename) - -# # create cooling network and plant -# cooling_network = Network2Pipe(self.sys_params) -# cooling_plant = CoolingPlant(self.sys_params) - -# # create heating network and plant -# heating_network = Network2Pipe(self.sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) - -# # create our load/ets/stubs -# # store all couplings to construct the District system -# all_couplings = [ -# Coupling(cooling_network, cooling_plant), -# Coupling(heating_network, heating_plant), -# ] - -# # keep track of separate loads and etses for testing purposes -# self.loads = [] -# heat_etses = [] -# cool_etses = [] -# for geojson_load in self.gj.buildings: -# spawn_load = Spawn(self.sys_params, geojson_load) -# self.loads.append(spawn_load) -# geojson_load_id = geojson_load.feature.properties["id"] - -# cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) -# cool_etses.append(cooling_indirect) -# all_couplings.append(Coupling(spawn_load, cooling_indirect)) -# all_couplings.append(Coupling(cooling_indirect, cooling_network)) - -# heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) -# heat_etses.append(heating_indirect) -# all_couplings.append(Coupling(spawn_load, heating_indirect)) -# all_couplings.append(Coupling(heating_indirect, heating_network)) - -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) - -# self.district = District( -# root_dir=self.output_dir, -# project_name=self.project_name, -# system_parameters=self.sys_params, -# coupling_graph=graph, -# ) -# self.district.to_modelica() - -# def test_build_spawn_cooling(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") -# def test_simulate_spawn_district_heating_and_cooling_systems(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # (in seconds) -# ) - -# # -# # Validate model outputs -# # - -# results_dir = ( -# f"{self.district._scaffold.project_path}/{self.project_name}.Districts.DistrictEnergySystem_results" -# ) -# mat_file = f"{results_dir}/{self.project_name}_Districts_DistrictEnergySystem_res.mat" -# mat_results = Reader(mat_file, "dymola") - -# # check the mass flow rates of the first load are in the expected range -# load = self.loads[0] -# (_, heat_m_flow) = mat_results.values(f"{load.id}.ports_aHeaWat[1].m_flow") -# (_, cool_m_flow) = mat_results.values(f"{load.id}.ports_aChiWat[1].m_flow") -# assert (heat_m_flow >= 0).all(), "Heating mass flow rate must be greater than or equal to zero" -# assert (cool_m_flow >= 0).all(), "Cooling mass flow rate must be greater than or equal to zero" - -# # this tolerance determines how much we allow the actual mass flow rate to exceed the nominal value -# m_flow_nominal_tolerance = 0.01 -# (_, heat_m_flow_nominal) = mat_results.values(f"{load.id}.mLoaHea_flow_nominal[1]") -# heat_m_flow_nominal = heat_m_flow_nominal[0] -# (_, cool_m_flow_nominal) = mat_results.values(f"{load.id}.mLoaCoo_flow_nominal[1]") -# cool_m_flow_nominal = cool_m_flow_nominal[0] - -# assert heat_m_flow <= pytest.approx(heat_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( -# "Heating mass flow rate must be less than nominal " -# f"mass flow rate ({heat_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" -# ) - -# assert cool_m_flow <= pytest.approx(cool_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( -# "Cooling mass flow rate must be less than nominal " -# f"mass flow rate ({cool_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest +from buildingspy.io.outputfile import Reader + +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 +from geojson_modelica_translator.model_connectors.networks import Network2Pipe +from geojson_modelica_translator.model_connectors.plants import CoolingPlant +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class DistrictHeatingAndCoolingSystemsTest(TestCaseBase): + def setUp(self): + self.project_name = "spawn_district_heating_and_cooling_systems" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) + + filename = Path(self.data_dir) / "spawn_geojson_ex1.json" + self.gj = UrbanOptGeoJson(filename) + + # load system parameter data + filename = Path(self.data_dir) / "spawn_system_params_ex1.json" + self.sys_params = SystemParameters(filename) + + # create cooling network and plant + cooling_network = Network2Pipe(self.sys_params) + cooling_plant = CoolingPlant(self.sys_params) + + # create heating network and plant + heating_network = Network2Pipe(self.sys_params) + heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) + + # create our load/ets/stubs + # store all couplings to construct the District system + all_couplings = [ + Coupling(cooling_network, cooling_plant), + Coupling(heating_network, heating_plant), + ] + + # keep track of separate loads and etses for testing purposes + self.loads = [] + heat_etses = [] + cool_etses = [] + for geojson_load in self.gj.buildings: + spawn_load = Spawn(self.sys_params, geojson_load) + self.loads.append(spawn_load) + geojson_load_id = geojson_load.feature.properties["id"] + + cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) + cool_etses.append(cooling_indirect) + all_couplings.append(Coupling(spawn_load, cooling_indirect)) + all_couplings.append(Coupling(cooling_indirect, cooling_network)) + + heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) + heat_etses.append(heating_indirect) + all_couplings.append(Coupling(spawn_load, heating_indirect)) + all_couplings.append(Coupling(heating_indirect, heating_network)) + + # create the couplings and graph + graph = CouplingGraph(all_couplings) + + self.district = District( + root_dir=self.output_dir, + project_name=self.project_name, + system_parameters=self.sys_params, + coupling_graph=graph, + ) + self.district.to_modelica() + + def test_build_spawn_cooling(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") + def test_simulate_spawn_district_heating_and_cooling_systems(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # (in seconds) + ) + + # + # Validate model outputs + # + + results_dir = ( + f"{self.district._scaffold.project_path}/{self.project_name}.Districts.DistrictEnergySystem_results" + ) + mat_file = f"{results_dir}/{self.project_name}_Districts_DistrictEnergySystem_res.mat" + mat_results = Reader(mat_file, "dymola") + + # check the mass flow rates of the first load are in the expected range + load = self.loads[0] + (_, heat_m_flow) = mat_results.values(f"{load.id}.ports_aHeaWat[1].m_flow") + (_, cool_m_flow) = mat_results.values(f"{load.id}.ports_aChiWat[1].m_flow") + assert (heat_m_flow >= 0).all(), "Heating mass flow rate must be greater than or equal to zero" + assert (cool_m_flow >= 0).all(), "Cooling mass flow rate must be greater than or equal to zero" + + # this tolerance determines how much we allow the actual mass flow rate to exceed the nominal value + m_flow_nominal_tolerance = 0.01 + (_, heat_m_flow_nominal) = mat_results.values(f"{load.id}.mLoaHea_flow_nominal[1]") + heat_m_flow_nominal = heat_m_flow_nominal[0] + (_, cool_m_flow_nominal) = mat_results.values(f"{load.id}.mLoaCoo_flow_nominal[1]") + cool_m_flow_nominal = cool_m_flow_nominal[0] + + assert heat_m_flow <= pytest.approx(heat_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( + "Heating mass flow rate must be less than nominal " + f"mass flow rate ({heat_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" + ) + + assert cool_m_flow <= pytest.approx(cool_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( + "Cooling mass flow rate must be less than nominal " + f"mass flow rate ({cool_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" + ) diff --git a/tests/model_connectors/test_spawn_heating.py b/tests/model_connectors/test_spawn_heating.py index e3e50208e..a693917cf 100644 --- a/tests/model_connectors/test_spawn_heating.py +++ b/tests/model_connectors/test_spawn_heating.py @@ -1,73 +1,73 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect -# from geojson_modelica_translator.model_connectors.load_connectors.spawn import Spawn -# from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub +from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect +from geojson_modelica_translator.model_connectors.load_connectors.spawn import Spawn +from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class TestSpawnHeating(TestCaseBase): -# def setUp(self): -# super().setUp() +class TestSpawnHeating(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "spawn_district_heating" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "spawn_district_heating" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "spawn_geojson_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "spawn_geojson_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "spawn_system_params_ex1.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "spawn_system_params_ex1.json" + sys_params = SystemParameters(filename) -# # create network and plant -# network = Network2Pipe(sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(sys_params) + # create network and plant + network = Network2Pipe(sys_params) + heating_plant = HeatingPlantWithOptionalCHP(sys_params) -# # create our our load/ets/stubs -# all_couplings = [Coupling(network, heating_plant)] -# for geojson_load in self.gj.buildings: -# spawn_load = Spawn(sys_params, geojson_load) -# geojson_load_id = geojson_load.feature.properties["id"] -# heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) -# cold_water_stub = EtsColdWaterStub(sys_params) -# all_couplings.append(Coupling(spawn_load, heating_indirect_system)) -# all_couplings.append(Coupling(spawn_load, cold_water_stub)) -# all_couplings.append(Coupling(heating_indirect_system, network)) + # create our our load/ets/stubs + all_couplings = [Coupling(network, heating_plant)] + for geojson_load in self.gj.buildings: + spawn_load = Spawn(sys_params, geojson_load) + geojson_load_id = geojson_load.feature.properties["id"] + heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) + cold_water_stub = EtsColdWaterStub(sys_params) + all_couplings.append(Coupling(spawn_load, heating_indirect_system)) + all_couplings.append(Coupling(spawn_load, cold_water_stub)) + all_couplings.append(Coupling(heating_indirect_system, network)) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() -# def test_build_spawn_cooling(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_spawn_cooling(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") -# def test_simulate_spawn_heating(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # (in seconds) -# ) + @pytest.mark.simulation + @pytest.mark.skip("OMC Failed to find spawn executable in Buildings Library") + def test_simulate_spawn_heating(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # (in seconds) + ) diff --git a/tests/model_connectors/test_teaser.py b/tests/model_connectors/test_teaser.py index 5c4921896..13d87f678 100644 --- a/tests/model_connectors/test_teaser.py +++ b/tests/model_connectors/test_teaser.py @@ -1,65 +1,65 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub -# from geojson_modelica_translator.model_connectors.load_connectors.teaser import Teaser -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub +from geojson_modelica_translator.model_connectors.load_connectors.teaser import Teaser +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class TeaserModelConnectorSingleBuildingTest(TestCaseBase): -# def setUp(self): -# super().setUp() +class TeaserModelConnectorSingleBuildingTest(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "teaser_single" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "teaser_single" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "teaser_geojson_ex1.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "teaser_geojson_ex1.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "teaser_system_params_ex1.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "teaser_system_params_ex1.json" + sys_params = SystemParameters(filename) -# # build spawn model with hot and cold water stubbed out -# teaser = Teaser(sys_params, self.gj.buildings[0]) -# hot_stub = EtsHotWaterStub(sys_params) -# cold_stub = EtsColdWaterStub(sys_params) + # build spawn model with hot and cold water stubbed out + teaser = Teaser(sys_params, self.gj.buildings[0]) + hot_stub = EtsHotWaterStub(sys_params) + cold_stub = EtsColdWaterStub(sys_params) -# graph = CouplingGraph( -# [ -# Coupling(teaser, hot_stub), -# Coupling(teaser, cold_stub), -# ] -# ) + graph = CouplingGraph( + [ + Coupling(teaser, hot_stub), + Coupling(teaser, cold_stub), + ] + ) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) -# self.district.to_modelica() + self.district.to_modelica() -# def test_build_teaser_single(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_teaser_single(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# def test_simulate_teaser_single(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=90, # (in seconds) -# ) + @pytest.mark.simulation + def test_simulate_teaser_single(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=90, # (in seconds) + ) diff --git a/tests/model_connectors/test_teaser_cooling.py b/tests/model_connectors/test_teaser_cooling.py index 9560c11b6..d365a6a78 100644 --- a/tests/model_connectors/test_teaser_cooling.py +++ b/tests/model_connectors/test_teaser_cooling.py @@ -1,73 +1,73 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub -# from geojson_modelica_translator.model_connectors.load_connectors.teaser import Teaser -# from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants.cooling_plant import CoolingPlant -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.cooling_indirect import CoolingIndirect +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_hot_water_stub import EtsHotWaterStub +from geojson_modelica_translator.model_connectors.load_connectors.teaser import Teaser +from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe +from geojson_modelica_translator.model_connectors.plants.cooling_plant import CoolingPlant +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class TestTeaserCooling(TestCaseBase): -# def setUp(self): -# super().setUp() +class TestTeaserCooling(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "teaser_district_cooling" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "teaser_district_cooling" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "teaser_geojson_two_loads.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "teaser_geojson_two_loads.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "teaser_system_params_two_loads.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "teaser_system_params_two_loads.json" + sys_params = SystemParameters(filename) -# # create network and plant -# network = Network2Pipe(sys_params) -# cooling_plant = CoolingPlant(sys_params) + # create network and plant + network = Network2Pipe(sys_params) + cooling_plant = CoolingPlant(sys_params) -# # create our our load/ets/stubs -# all_couplings = [Coupling(network, cooling_plant)] -# for geojson_load in self.gj.buildings: -# teaser_load = Teaser(sys_params, geojson_load) -# geojson_load_id = geojson_load.feature.properties["id"] -# cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) -# hot_water_stub = EtsHotWaterStub(sys_params) -# all_couplings.append(Coupling(teaser_load, cooling_indirect_system)) -# all_couplings.append(Coupling(teaser_load, hot_water_stub)) -# all_couplings.append(Coupling(cooling_indirect_system, network)) + # create our our load/ets/stubs + all_couplings = [Coupling(network, cooling_plant)] + for geojson_load in self.gj.buildings: + teaser_load = Teaser(sys_params, geojson_load) + geojson_load_id = geojson_load.feature.properties["id"] + cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) + hot_water_stub = EtsHotWaterStub(sys_params) + all_couplings.append(Coupling(teaser_load, cooling_indirect_system)) + all_couplings.append(Coupling(teaser_load, hot_water_stub)) + all_couplings.append(Coupling(cooling_indirect_system, network)) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() -# def test_build_teaser_cooling(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_teaser_cooling(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# @pytest.mark.skip(reason="Takes forever to run. Teaser is a problem for another day.") -# def test_simulate_teaser_cooling(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # (in seconds) -# ) + @pytest.mark.simulation + @pytest.mark.skip(reason="Takes forever to run. Teaser is a problem for another day.") + def test_simulate_teaser_cooling(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # (in seconds) + ) diff --git a/tests/model_connectors/test_teaser_district_heating_and_cooling_systems.py b/tests/model_connectors/test_teaser_district_heating_and_cooling_systems.py index c94b7139b..b51a4891b 100644 --- a/tests/model_connectors/test_teaser_district_heating_and_cooling_systems.py +++ b/tests/model_connectors/test_teaser_district_heating_and_cooling_systems.py @@ -1,127 +1,127 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest -# from buildingspy.io.outputfile import Reader - -# 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 Teaser -# from geojson_modelica_translator.model_connectors.networks import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants import CoolingPlant -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class TestTeaserDistrictHeatingAndCoolingSystems(TestCaseBase): -# def setUp(self): -# super().setUp() - -# self.project_name = "teaser_district_heating_and_cooling_systems" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) - -# filename = Path(self.data_dir) / "teaser_geojson_two_loads.json" -# self.gj = UrbanOptGeoJson(filename) - -# # load system parameter data -# filename = Path(self.data_dir) / "teaser_system_params_two_loads.json" -# self.sys_params = SystemParameters(filename) - -# # create cooling network and plant -# cooling_network = Network2Pipe(self.sys_params) -# cooling_plant = CoolingPlant(self.sys_params) - -# # create heating network and plant -# heating_network = Network2Pipe(self.sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) - -# # create our load/ets/stubs -# # store all couplings to construct the District system -# all_couplings = [ -# Coupling(cooling_network, cooling_plant), -# Coupling(heating_network, heating_plant), -# ] - -# # keep track of separate loads and etses for testing purposes -# self.loads = [] -# heat_etses = [] -# cool_etses = [] -# for geojson_load in self.gj.buildings: -# teaser_load = Teaser(self.sys_params, geojson_load) -# self.loads.append(teaser_load) -# geojson_load_id = geojson_load.feature.properties["id"] - -# cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) -# cool_etses.append(cooling_indirect) -# all_couplings.append(Coupling(teaser_load, cooling_indirect)) -# all_couplings.append(Coupling(cooling_indirect, cooling_network)) - -# heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) -# heat_etses.append(heating_indirect) -# all_couplings.append(Coupling(teaser_load, heating_indirect)) -# all_couplings.append(Coupling(heating_indirect, heating_network)) - -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) - -# self.district = District( -# root_dir=self.output_dir, -# project_name=self.project_name, -# system_parameters=self.sys_params, -# coupling_graph=graph, -# ) -# self.district.to_modelica() - -# def test_build_teaser_district_heating_and_cooling_systems(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# @pytest.mark.skip(reason="Takes forever to run. Teaser is a problem for another day.") -# def test_teaser_district_heating_and_cooling_systems(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # At 1 hour intervals (in seconds) -# ) - -# # -# # Validate model outputs -# # -# results_dir = ( -# f"{self.district._scaffold.project_path}/{self.project_name}.Districts.DistrictEnergySystem_results" -# ) - -# mat_file = f"{results_dir}/{self.project_name}.Districts.DistrictEnergySystem_res.mat" -# mat_results = Reader(mat_file, "dymola") - -# # check the mass flow rates of the first load are in the expected range -# load = self.loads[0] -# (_, heat_m_flow) = mat_results.values(f"{load.id}.ports_aHeaWat[1].m_flow") -# (_, cool_m_flow) = mat_results.values(f"{load.id}.ports_aChiWat[1].m_flow") -# assert (heat_m_flow >= 0).all(), "Heating mass flow rate must be greater than or equal to zero" -# assert (cool_m_flow >= 0).all(), "Cooling mass flow rate must be greater than or equal to zero" - -# # this tolerance determines how much we allow the actual mass flow rate to exceed the nominal value -# m_flow_nominal_tolerance = 0.01 -# (_, heat_m_flow_nominal) = mat_results.values(f"{load.id}.terUni[1].mLoaHea_flow_nominal") -# heat_m_flow_nominal = heat_m_flow_nominal[0] -# (_, cool_m_flow_nominal) = mat_results.values(f"{load.id}.terUni[1].mLoaCoo_flow_nominal") -# cool_m_flow_nominal = cool_m_flow_nominal[0] - -# assert heat_m_flow <= pytest.approx(heat_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( -# "Heating mass flow rate must be less than nominal " -# f"mass flow rate ({heat_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" -# ) -# assert cool_m_flow <= pytest.approx(cool_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( -# "Cooling mass flow rate must be less than nominal " -# f"mass flow rate ({cool_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest +from buildingspy.io.outputfile import Reader + +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 Teaser +from geojson_modelica_translator.model_connectors.networks import Network2Pipe +from geojson_modelica_translator.model_connectors.plants import CoolingPlant +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class TestTeaserDistrictHeatingAndCoolingSystems(TestCaseBase): + def setUp(self): + super().setUp() + + self.project_name = "teaser_district_heating_and_cooling_systems" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, self.project_name) + + filename = Path(self.data_dir) / "teaser_geojson_two_loads.json" + self.gj = UrbanOptGeoJson(filename) + + # load system parameter data + filename = Path(self.data_dir) / "teaser_system_params_two_loads.json" + self.sys_params = SystemParameters(filename) + + # create cooling network and plant + cooling_network = Network2Pipe(self.sys_params) + cooling_plant = CoolingPlant(self.sys_params) + + # create heating network and plant + heating_network = Network2Pipe(self.sys_params) + heating_plant = HeatingPlantWithOptionalCHP(self.sys_params) + + # create our load/ets/stubs + # store all couplings to construct the District system + all_couplings = [ + Coupling(cooling_network, cooling_plant), + Coupling(heating_network, heating_plant), + ] + + # keep track of separate loads and etses for testing purposes + self.loads = [] + heat_etses = [] + cool_etses = [] + for geojson_load in self.gj.buildings: + teaser_load = Teaser(self.sys_params, geojson_load) + self.loads.append(teaser_load) + geojson_load_id = geojson_load.feature.properties["id"] + + cooling_indirect = CoolingIndirect(self.sys_params, geojson_load_id) + cool_etses.append(cooling_indirect) + all_couplings.append(Coupling(teaser_load, cooling_indirect)) + all_couplings.append(Coupling(cooling_indirect, cooling_network)) + + heating_indirect = HeatingIndirect(self.sys_params, geojson_load_id) + heat_etses.append(heating_indirect) + all_couplings.append(Coupling(teaser_load, heating_indirect)) + all_couplings.append(Coupling(heating_indirect, heating_network)) + + # create the couplings and graph + graph = CouplingGraph(all_couplings) + + self.district = District( + root_dir=self.output_dir, + project_name=self.project_name, + system_parameters=self.sys_params, + coupling_graph=graph, + ) + self.district.to_modelica() + + def test_build_teaser_district_heating_and_cooling_systems(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + @pytest.mark.skip(reason="Takes forever to run. Teaser is a problem for another day.") + def test_teaser_district_heating_and_cooling_systems(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # At 1 hour intervals (in seconds) + ) + + # + # Validate model outputs + # + results_dir = ( + f"{self.district._scaffold.project_path}/{self.project_name}.Districts.DistrictEnergySystem_results" + ) + + mat_file = f"{results_dir}/{self.project_name}.Districts.DistrictEnergySystem_res.mat" + mat_results = Reader(mat_file, "dymola") + + # check the mass flow rates of the first load are in the expected range + load = self.loads[0] + (_, heat_m_flow) = mat_results.values(f"{load.id}.ports_aHeaWat[1].m_flow") + (_, cool_m_flow) = mat_results.values(f"{load.id}.ports_aChiWat[1].m_flow") + assert (heat_m_flow >= 0).all(), "Heating mass flow rate must be greater than or equal to zero" + assert (cool_m_flow >= 0).all(), "Cooling mass flow rate must be greater than or equal to zero" + + # this tolerance determines how much we allow the actual mass flow rate to exceed the nominal value + m_flow_nominal_tolerance = 0.01 + (_, heat_m_flow_nominal) = mat_results.values(f"{load.id}.terUni[1].mLoaHea_flow_nominal") + heat_m_flow_nominal = heat_m_flow_nominal[0] + (_, cool_m_flow_nominal) = mat_results.values(f"{load.id}.terUni[1].mLoaCoo_flow_nominal") + cool_m_flow_nominal = cool_m_flow_nominal[0] + + assert heat_m_flow <= pytest.approx(heat_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( + "Heating mass flow rate must be less than nominal " + f"mass flow rate ({heat_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" + ) + assert cool_m_flow <= pytest.approx(cool_m_flow_nominal, rel=m_flow_nominal_tolerance).all(), ( + "Cooling mass flow rate must be less than nominal " + f"mass flow rate ({cool_m_flow_nominal}) plus a tolerance ({m_flow_nominal_tolerance * 100}%)" + ) diff --git a/tests/model_connectors/test_teaser_heating.py b/tests/model_connectors/test_teaser_heating.py index a478611fa..99439f0bf 100644 --- a/tests/model_connectors/test_teaser_heating.py +++ b/tests/model_connectors/test_teaser_heating.py @@ -1,73 +1,73 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md -# from pathlib import Path +from pathlib import Path -# import pytest +import pytest -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect -# from geojson_modelica_translator.model_connectors.load_connectors.teaser import Teaser -# from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe -# from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub +from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect +from geojson_modelica_translator.model_connectors.load_connectors.teaser import Teaser +from geojson_modelica_translator.model_connectors.networks.network_2_pipe import Network2Pipe +from geojson_modelica_translator.model_connectors.plants.chp import HeatingPlantWithOptionalCHP +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase -# class TestTeaserHeating(TestCaseBase): -# def setUp(self): -# super().setUp() +class TestTeaserHeating(TestCaseBase): + def setUp(self): + super().setUp() -# project_name = "teaser_district_heating" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + project_name = "teaser_district_heating" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "teaser_geojson_two_loads.json" -# self.gj = UrbanOptGeoJson(filename) + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "teaser_geojson_two_loads.json" + self.gj = UrbanOptGeoJson(filename) -# # load system parameter data -# filename = Path(self.data_dir) / "teaser_system_params_two_loads.json" -# sys_params = SystemParameters(filename) + # load system parameter data + filename = Path(self.data_dir) / "teaser_system_params_two_loads.json" + sys_params = SystemParameters(filename) -# # create network and plant -# network = Network2Pipe(sys_params) -# heating_plant = HeatingPlantWithOptionalCHP(sys_params) + # create network and plant + network = Network2Pipe(sys_params) + heating_plant = HeatingPlantWithOptionalCHP(sys_params) -# # create our our load/ets/stubs -# all_couplings = [Coupling(network, heating_plant)] -# for geojson_load in self.gj.buildings: -# teaser_load = Teaser(sys_params, geojson_load) -# geojson_load_id = geojson_load.feature.properties["id"] -# heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) -# cold_water_stub = EtsColdWaterStub(sys_params) -# all_couplings.append(Coupling(teaser_load, heating_indirect_system)) -# all_couplings.append(Coupling(teaser_load, cold_water_stub)) -# all_couplings.append(Coupling(heating_indirect_system, network)) + # create our our load/ets/stubs + all_couplings = [Coupling(network, heating_plant)] + for geojson_load in self.gj.buildings: + teaser_load = Teaser(sys_params, geojson_load) + geojson_load_id = geojson_load.feature.properties["id"] + heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) + cold_water_stub = EtsColdWaterStub(sys_params) + all_couplings.append(Coupling(teaser_load, heating_indirect_system)) + all_couplings.append(Coupling(teaser_load, cold_water_stub)) + all_couplings.append(Coupling(heating_indirect_system, network)) -# # create the couplings and graph -# graph = CouplingGraph(all_couplings) + # create the couplings and graph + graph = CouplingGraph(all_couplings) -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) -# self.district.to_modelica() + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + self.district.to_modelica() -# def test_build_teaser_heating(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() + def test_build_teaser_heating(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() -# @pytest.mark.simulation -# @pytest.mark.skip(reason="Takes forever to run, might be crashing.") -# def test_simulate_teaser_heating(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) -# stop_time=17366400, # For 1 day duration (in seconds) -# step_size=3600, # (in seconds) -# ) + @pytest.mark.simulation + @pytest.mark.skip(reason="Takes forever to run, might be crashing.") + def test_simulate_teaser_heating(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=17280000, # Day 200 (in seconds) (Run in summer to keep chiller happy) + stop_time=17366400, # For 1 day duration (in seconds) + step_size=3600, # (in seconds) + ) diff --git a/tests/model_connectors/test_time_series_5g.py b/tests/model_connectors/test_time_series_5g.py index 93223ae6e..87defb186 100644 --- a/tests/model_connectors/test_time_series_5g.py +++ b/tests/model_connectors/test_time_series_5g.py @@ -1,77 +1,77 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest - -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# from geojson_modelica_translator.model_connectors.networks.network_ambient_water_stub import NetworkAmbientWaterStub -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class DistrictSystemTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# project_name = "time_series_5g" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) -# single_building = self.gj.buildings[0] - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_5g_sys_params.json" -# sys_params = SystemParameters(filename) - -# # Create the time series load, ets and their coupling -# time_series_load = TimeSeries(sys_params, single_building) - -# # create ambient water stub -# ambient_water_stub = NetworkAmbientWaterStub(sys_params) -# five_g_coupling = Coupling(time_series_load, ambient_water_stub, district_type="fifth_generation") - -# graph = CouplingGraph( -# [ -# five_g_coupling, -# # ts_cw_coupling, -# ] -# ) - -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) - -# self.district.to_modelica() - -# def test_build_district_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# # test_district_5g.py is this same test but with both buildings, and it works. -# @pytest.mark.skip(reason="https://github.com/urbanopt/geojson-modelica-translator/issues/572") -# def test_simulate_district_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# ) - -# @pytest.mark.dymola -# @pytest.mark.skip(reason="Structurally singular error in Dymola.") -# def test_simulate_district_system_in_dymola(self): -# # need to just pass the dir, dymola runner looks for package.mo -# self.run_and_assert_in_dymola( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.project_path, -# run_path=self.district._scaffold.project_path, -# # debug=True -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest + +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +from geojson_modelica_translator.model_connectors.networks.network_ambient_water_stub import NetworkAmbientWaterStub +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class DistrictSystemTest(TestCaseBase): + def setUp(self): + super().setUp() + + project_name = "time_series_5g" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + single_building = self.gj.buildings[0] + + # load system parameter data + filename = Path(self.data_dir) / "time_series_5g_sys_params.json" + sys_params = SystemParameters(filename) + + # Create the time series load, ets and their coupling + time_series_load = TimeSeries(sys_params, single_building) + + # create ambient water stub + ambient_water_stub = NetworkAmbientWaterStub(sys_params) + five_g_coupling = Coupling(time_series_load, ambient_water_stub, district_type="fifth_generation") + + graph = CouplingGraph( + [ + five_g_coupling, + # ts_cw_coupling, + ] + ) + + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + + self.district.to_modelica() + + def test_build_district_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + # test_district_5g.py is this same test but with both buildings, and it works. + @pytest.mark.skip(reason="https://github.com/urbanopt/geojson-modelica-translator/issues/572") + def test_simulate_district_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + ) + + @pytest.mark.dymola + @pytest.mark.skip(reason="Structurally singular error in Dymola.") + def test_simulate_district_system_in_dymola(self): + # need to just pass the dir, dymola runner looks for package.mo + self.run_and_assert_in_dymola( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.project_path, + run_path=self.district._scaffold.project_path, + # debug=True + ) diff --git a/tests/model_connectors/test_time_series_heating_indirect.py b/tests/model_connectors/test_time_series_heating_indirect.py index 31b2afd05..f98f47305 100644 --- a/tests/model_connectors/test_time_series_heating_indirect.py +++ b/tests/model_connectors/test_time_series_heating_indirect.py @@ -1,78 +1,78 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# from pathlib import Path - -# import pytest - -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub -# from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect -# from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries -# from geojson_modelica_translator.model_connectors.networks.network_heated_water_stub import NetworkHeatedWaterStub -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class DistrictSystemTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# project_name = "time_series_heating_indirect" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) -# single_building = self.gj.buildings[0] - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_ets.json" -# sys_params = SystemParameters(filename) - -# # Create the time series load, ets and their coupling -# time_series_load = TimeSeries(sys_params, single_building) -# geojson_load_id = single_building.feature.properties["id"] -# heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) -# ts_hi_coupling = Coupling(time_series_load, heating_indirect_system) - -# assert time_series_load is not None -# assert time_series_load.building is not None -# assert time_series_load.system_parameters.get_param("buildings")[0]["load_model"] == "time_series" - -# # create heated water stub for the ets -# heated_water_stub = NetworkHeatedWaterStub(sys_params) -# hi_hw_coupling = Coupling(heating_indirect_system, heated_water_stub) - -# # create cold water stub for the load -# cold_water_stub = EtsColdWaterStub(sys_params) -# ts_cw_coupling = Coupling(time_series_load, cold_water_stub) - -# graph = CouplingGraph( -# [ -# ts_hi_coupling, -# hi_hw_coupling, -# ts_cw_coupling, -# ] -# ) - -# self.district = District( -# root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph -# ) - -# self.district.to_modelica() - -# def test_build_district_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# def test_simulate_district_system(self): -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +from pathlib import Path + +import pytest + +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems.ets_cold_water_stub import EtsColdWaterStub +from geojson_modelica_translator.model_connectors.energy_transfer_systems.heating_indirect import HeatingIndirect +from geojson_modelica_translator.model_connectors.load_connectors.time_series import TimeSeries +from geojson_modelica_translator.model_connectors.networks.network_heated_water_stub import NetworkHeatedWaterStub +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class DistrictSystemTest(TestCaseBase): + def setUp(self): + super().setUp() + + project_name = "time_series_heating_indirect" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + single_building = self.gj.buildings[0] + + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_ets.json" + sys_params = SystemParameters(filename) + + # Create the time series load, ets and their coupling + time_series_load = TimeSeries(sys_params, single_building) + geojson_load_id = single_building.feature.properties["id"] + heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) + ts_hi_coupling = Coupling(time_series_load, heating_indirect_system) + + assert time_series_load is not None + assert time_series_load.building is not None + assert time_series_load.system_parameters.get_param("buildings")[0]["load_model"] == "time_series" + + # create heated water stub for the ets + heated_water_stub = NetworkHeatedWaterStub(sys_params) + hi_hw_coupling = Coupling(heating_indirect_system, heated_water_stub) + + # create cold water stub for the load + cold_water_stub = EtsColdWaterStub(sys_params) + ts_cw_coupling = Coupling(time_series_load, cold_water_stub) + + graph = CouplingGraph( + [ + ts_hi_coupling, + hi_hw_coupling, + ts_cw_coupling, + ] + ) + + self.district = District( + root_dir=self.output_dir, project_name=project_name, system_parameters=sys_params, coupling_graph=graph + ) + + self.district.to_modelica() + + def test_build_district_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + def test_simulate_district_system(self): + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + ) diff --git a/tests/model_connectors/test_time_series_mft_ets.py b/tests/model_connectors/test_time_series_mft_ets.py index effb3c625..620165485 100644 --- a/tests/model_connectors/test_time_series_mft_ets.py +++ b/tests/model_connectors/test_time_series_mft_ets.py @@ -1,144 +1,144 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import re -# from pathlib import Path - -# import pytest -# from buildingspy.io.outputfile import Reader -# from modelica_builder.model import Model - -# from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson -# from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling -# from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph -# from geojson_modelica_translator.model_connectors.districts.district import District -# from geojson_modelica_translator.model_connectors.energy_transfer_systems import CoolingIndirect, HeatingIndirect -# from geojson_modelica_translator.model_connectors.load_connectors.time_series_mft_ets_coupling import TimeSeriesMFT -# from geojson_modelica_translator.model_connectors.networks import NetworkChilledWaterStub, NetworkHeatedWaterStub -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters -# from tests.base_test_case import TestCaseBase - - -# class TimeSeriesModelConnectorSingleBuildingMFTETSTest(TestCaseBase): -# def setUp(self): -# super().setUp() - -# project_name = "time_series_massflow" -# self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) - -# # load in the example geojson with a single office building -# filename = Path(self.data_dir) / "time_series_ex1.json" -# self.gj = UrbanOptGeoJson(filename) - -# # load system parameter data -# filename = Path(self.data_dir) / "time_series_system_params_massflow_ex1.json" -# sys_params = SystemParameters(filename) - -# # create the load, ETSes and their couplings -# time_series_mft_load = TimeSeriesMFT(sys_params, self.gj.buildings[0]) -# geojson_load_id = self.gj.buildings[0].feature.properties["id"] - -# heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) -# ts_hi_coupling = Coupling(time_series_mft_load, heating_indirect_system) - -# cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) -# ts_ci_coupling = Coupling(time_series_mft_load, cooling_indirect_system) - -# # create network stubs for the ETSes -# heated_water_stub = NetworkHeatedWaterStub(sys_params) -# hi_hw_coupling = Coupling(heating_indirect_system, heated_water_stub) - -# chilled_water_stub = NetworkChilledWaterStub(sys_params) -# ci_cw_coupling = Coupling(cooling_indirect_system, chilled_water_stub) - -# # build the district system -# self.district = District( -# root_dir=self.output_dir, -# project_name=project_name, -# system_parameters=sys_params, -# coupling_graph=CouplingGraph( -# [ -# ts_hi_coupling, -# ts_ci_coupling, -# hi_hw_coupling, -# ci_cw_coupling, -# ] -# ), -# ) -# self.district.to_modelica() - -# def test_build_district_system(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# assert (root_path / "DistrictEnergySystem.mo").exists() - -# @pytest.mark.simulation -# def test_mft_time_series_to_modelica_and_run(self): -# root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() -# mo_file_name = Path(root_path) / "DistrictEnergySystem.mo" -# mofile = Model(mo_file_name) -# one_year_in_seconds = 31536000 # 1 year in seconds -# mofile.update_model_annotation({"experiment": {"StopTime": one_year_in_seconds}}) -# mofile.save() - -# self.run_and_assert_in_docker( -# f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", -# file_to_load=self.district._scaffold.package_path, -# run_path=self.district._scaffold.project_path, -# start_time=0, -# stop_time=one_year_in_seconds, -# ) - -# # Check the results -# results_dir = ( -# f"{self.district._scaffold.project_path}/time_series_massflow.Districts.DistrictEnergySystem_results" -# ) - -# mat_file = f"{results_dir}/time_series_massflow.Districts.DistrictEnergySystem_res.mat" -# mat_results = Reader(mat_file, "dymola") - -# # hack to get the name of the loads (rather the 8 character connector shas) -# timeseries_load_var = None -# coolflow_var = None -# heatflow_var = None -# for var in mat_results.varNames(): -# # search for 25 characters because that is the length of the id for the test load -# m = re.match("TimeSerMFTLoa_(.{25})", var) -# if m: -# timeseries_load_var = m[1] -# continue - -# m = re.match("cooInd_(.{8})", var) -# if m: -# coolflow_var = m[1] -# continue - -# m = re.match("heaInd_(.{8})", var) -# if m: -# heatflow_var = m[1] -# continue - -# if None not in (timeseries_load_var, coolflow_var, heatflow_var): -# break - -# (time1, ts_hea_load) = mat_results.values(f"TimeSerMFTLoa_{timeseries_load_var}.ports_aChiWat[1].m_flow") -# (_time1, ts_chi_load) = mat_results.values(f"TimeSerMFTLoa_{timeseries_load_var}.ports_aHeaWat[1].m_flow") -# (_time1, cool_q_flow) = mat_results.values(f"cooInd_{coolflow_var}.Q_flow") -# (_time1, heat_q_flow) = mat_results.values(f"heaInd_{heatflow_var}.Q_flow") - -# # if any of these assertions fail, then it is likely that the change in the timeseries massflow model -# # has been updated and we need to revalidate the models. -# assert ts_hea_load.min() == 0 -# assert ts_hea_load.max() == pytest.approx(52, rel=1) -# assert ts_hea_load.mean() == pytest.approx(4, rel=1) - -# assert ts_chi_load.min() == 0 -# assert ts_chi_load.max() == pytest.approx(67, rel=1) -# assert ts_chi_load.mean() == pytest.approx(4, rel=1) - -# assert cool_q_flow.min() == pytest.approx(-131.9, rel=10) -# assert cool_q_flow.max() == pytest.approx(512936, rel=10) -# assert cool_q_flow.mean() == pytest.approx(30210, rel=10) - -# assert heat_q_flow.min() == pytest.approx(-342201, rel=10) -# assert heat_q_flow.max() == pytest.approx(62995, rel=10) -# assert heat_q_flow.mean() == pytest.approx(-13905, rel=10) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import re +from pathlib import Path + +import pytest +from buildingspy.io.outputfile import Reader +from modelica_builder.model import Model + +from geojson_modelica_translator.geojson.urbanopt_geojson import UrbanOptGeoJson +from geojson_modelica_translator.model_connectors.couplings.coupling import Coupling +from geojson_modelica_translator.model_connectors.couplings.graph import CouplingGraph +from geojson_modelica_translator.model_connectors.districts.district import District +from geojson_modelica_translator.model_connectors.energy_transfer_systems import CoolingIndirect, HeatingIndirect +from geojson_modelica_translator.model_connectors.load_connectors.time_series_mft_ets_coupling import TimeSeriesMFT +from geojson_modelica_translator.model_connectors.networks import NetworkChilledWaterStub, NetworkHeatedWaterStub +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters +from tests.base_test_case import TestCaseBase + + +class TimeSeriesModelConnectorSingleBuildingMFTETSTest(TestCaseBase): + def setUp(self): + super().setUp() + + project_name = "time_series_massflow" + self.data_dir, self.output_dir = self.set_up(Path(__file__).parent, project_name) + + # load in the example geojson with a single office building + filename = Path(self.data_dir) / "time_series_ex1.json" + self.gj = UrbanOptGeoJson(filename) + + # load system parameter data + filename = Path(self.data_dir) / "time_series_system_params_massflow_ex1.json" + sys_params = SystemParameters(filename) + + # create the load, ETSes and their couplings + time_series_mft_load = TimeSeriesMFT(sys_params, self.gj.buildings[0]) + geojson_load_id = self.gj.buildings[0].feature.properties["id"] + + heating_indirect_system = HeatingIndirect(sys_params, geojson_load_id) + ts_hi_coupling = Coupling(time_series_mft_load, heating_indirect_system) + + cooling_indirect_system = CoolingIndirect(sys_params, geojson_load_id) + ts_ci_coupling = Coupling(time_series_mft_load, cooling_indirect_system) + + # create network stubs for the ETSes + heated_water_stub = NetworkHeatedWaterStub(sys_params) + hi_hw_coupling = Coupling(heating_indirect_system, heated_water_stub) + + chilled_water_stub = NetworkChilledWaterStub(sys_params) + ci_cw_coupling = Coupling(cooling_indirect_system, chilled_water_stub) + + # build the district system + self.district = District( + root_dir=self.output_dir, + project_name=project_name, + system_parameters=sys_params, + coupling_graph=CouplingGraph( + [ + ts_hi_coupling, + ts_ci_coupling, + hi_hw_coupling, + ci_cw_coupling, + ] + ), + ) + self.district.to_modelica() + + def test_build_district_system(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + assert (root_path / "DistrictEnergySystem.mo").exists() + + @pytest.mark.simulation + def test_mft_time_series_to_modelica_and_run(self): + root_path = Path(self.district._scaffold.districts_path.files_dir).resolve() + mo_file_name = Path(root_path) / "DistrictEnergySystem.mo" + mofile = Model(mo_file_name) + one_year_in_seconds = 31536000 # 1 year in seconds + mofile.update_model_annotation({"experiment": {"StopTime": one_year_in_seconds}}) + mofile.save() + + self.run_and_assert_in_docker( + f"{self.district._scaffold.project_name}.Districts.DistrictEnergySystem", + file_to_load=self.district._scaffold.package_path, + run_path=self.district._scaffold.project_path, + start_time=0, + stop_time=one_year_in_seconds, + ) + + # Check the results + results_dir = ( + f"{self.district._scaffold.project_path}/time_series_massflow.Districts.DistrictEnergySystem_results" + ) + + mat_file = f"{results_dir}/time_series_massflow.Districts.DistrictEnergySystem_res.mat" + mat_results = Reader(mat_file, "dymola") + + # hack to get the name of the loads (rather the 8 character connector shas) + timeseries_load_var = None + coolflow_var = None + heatflow_var = None + for var in mat_results.varNames(): + # search for 25 characters because that is the length of the id for the test load + m = re.match("TimeSerMFTLoa_(.{25})", var) + if m: + timeseries_load_var = m[1] + continue + + m = re.match("cooInd_(.{8})", var) + if m: + coolflow_var = m[1] + continue + + m = re.match("heaInd_(.{8})", var) + if m: + heatflow_var = m[1] + continue + + if None not in (timeseries_load_var, coolflow_var, heatflow_var): + break + + (time1, ts_hea_load) = mat_results.values(f"TimeSerMFTLoa_{timeseries_load_var}.ports_aChiWat[1].m_flow") + (_time1, ts_chi_load) = mat_results.values(f"TimeSerMFTLoa_{timeseries_load_var}.ports_aHeaWat[1].m_flow") + (_time1, cool_q_flow) = mat_results.values(f"cooInd_{coolflow_var}.Q_flow") + (_time1, heat_q_flow) = mat_results.values(f"heaInd_{heatflow_var}.Q_flow") + + # if any of these assertions fail, then it is likely that the change in the timeseries massflow model + # has been updated and we need to revalidate the models. + assert ts_hea_load.min() == 0 + assert ts_hea_load.max() == pytest.approx(52, rel=1) + assert ts_hea_load.mean() == pytest.approx(4, rel=1) + + assert ts_chi_load.min() == 0 + assert ts_chi_load.max() == pytest.approx(67, rel=1) + assert ts_chi_load.mean() == pytest.approx(4, rel=1) + + assert cool_q_flow.min() == pytest.approx(-131.9, rel=10) + assert cool_q_flow.max() == pytest.approx(512936, rel=10) + assert cool_q_flow.mean() == pytest.approx(30210, rel=10) + + assert heat_q_flow.min() == pytest.approx(-342201, rel=10) + assert heat_q_flow.max() == pytest.approx(62995, rel=10) + assert heat_q_flow.mean() == pytest.approx(-13905, rel=10) diff --git a/tests/modelica/test_csv_modelica.py b/tests/modelica/test_csv_modelica.py index a150b4836..09243baa5 100644 --- a/tests/modelica/test_csv_modelica.py +++ b/tests/modelica/test_csv_modelica.py @@ -1,84 +1,84 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import unittest -# from pathlib import Path - -# from geojson_modelica_translator.modelica.csv_modelica import CSVModelica - - -# class CsvModelicaTest(unittest.TestCase): -# def setUp(self): -# self.data_dir = Path(__file__).parent / 'data' -# self.output_dir = Path(__file__).parent / 'output' -# self.output_dir.mkdir(parents=True, exist_ok=True) - -# def test_csv_does_not_exist(self): -# with self.assertRaises(Exception) as context: -# input_file = Path(self.data_dir) / 'DNE.csv' -# CSVModelica(input_file) -# self.assertIn("Unable to convert CSV file because this path does not exist:", str(context.exception)) - -# def test_misshapen_csv_fails_gracefully(self): -# with self.assertRaises(Exception) as context: -# input_file = Path(self.data_dir) / 'misshapen_building_loads.csv' -# # This input file has a typo in a column name and a missing column. Each will cause the Exception. -# CSVModelica(input_file) -# self.assertIn( -# "Columns are missing or misspelled in your file:", str( -# context.exception)) - -# def test_csv_modelica_at_15_min_timestep(self): -# input_file = Path(self.data_dir) / 'building_loads_15min_snippet.csv' -# output_modelica_file_name = Path(self.output_dir) / 'modelica_timestep.csv' - -# csv_converter = CSVModelica(input_file) -# # save the updated time series to the output directory of the test folder -# csv_converter.timeseries_to_modelica_data(output_modelica_file_name) -# self.assertTrue(output_modelica_file_name.exists()) - -# # check if a string is in there -# with open(output_modelica_file_name, 'r') as f: -# data = f.read() -# self.assertTrue('14400,41.8,82.2,1.659,14.7,6.7,1.375' in data) -# self.assertTrue('28800,37.7,82.2,0.721,14.9,6.7,2.018' in data) - -# def test_csv_modelica_at_60_min_timestep(self): -# input_file = Path(self.data_dir) / 'building_loads_snippet.csv' -# output_modelica_file_name = Path(self.output_dir) / 'modelica.csv' - -# csv_converter = CSVModelica(input_file) -# # save the updated time series to the output directory of the test folder -# csv_converter.timeseries_to_modelica_data(output_modelica_file_name) -# self.assertTrue(output_modelica_file_name.exists()) - -# # check if a string is in there -# with open(output_modelica_file_name, 'r') as f: -# data = f.read() -# self.assertTrue('18000,41.9,82.2,1.392,14.6,6.7,1.648' in data) -# self.assertTrue('111600,57.2,82.2,5.784,16.2,6.7,3.062' in data) -# self.assertFalse('9900,40.1,82.2,0.879,14.9,6.7,1.512' in data) - -# def test_csv_modelica_at_60_min_timestep_with_energyplus_file(self): -# input_file = Path(self.data_dir) / 'mfrt.csv' -# output_modelica_file_name = Path(self.output_dir) / 'mfrt_output.csv' - -# csv_converter = CSVModelica(input_file) -# # save the updated time series to the output directory of the test folder -# csv_converter.timeseries_to_modelica_data(output_modelica_file_name) -# self.assertTrue(output_modelica_file_name.exists()) - -# # check if a string is in there -# with open(output_modelica_file_name, 'r') as f: -# data = f.read() -# self.assertTrue('18000,42.3,55.0,15.8,6.7,8.275,0.2' in data) -# self.assertTrue('111600,41.9,55.0,15.1,6.7,12.32,0.021' in data) - -# def test_csv_modelica_no_overwrite(self): -# with self.assertRaises(Exception) as context: -# input_file = Path(self.data_dir) / 'building_loads_snippet.csv' -# csv_converter = CSVModelica(input_file) -# csv_converter.timeseries_to_modelica_data(output_modelica_file_name, overwrite=False) -# self.assertIn( -# "Output file already exists and overwrite is False:", str( -# context.exception)) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import unittest +from pathlib import Path + +from geojson_modelica_translator.modelica.csv_modelica import CSVModelica + + +class CsvModelicaTest(unittest.TestCase): + def setUp(self): + self.data_dir = Path(__file__).parent / 'data' + self.output_dir = Path(__file__).parent / 'output' + self.output_dir.mkdir(parents=True, exist_ok=True) + + def test_csv_does_not_exist(self): + with self.assertRaises(Exception) as context: + input_file = Path(self.data_dir) / 'DNE.csv' + CSVModelica(input_file) + self.assertIn("Unable to convert CSV file because this path does not exist:", str(context.exception)) + + def test_misshapen_csv_fails_gracefully(self): + with self.assertRaises(Exception) as context: + input_file = Path(self.data_dir) / 'misshapen_building_loads.csv' + # This input file has a typo in a column name and a missing column. Each will cause the Exception. + CSVModelica(input_file) + self.assertIn( + "Columns are missing or misspelled in your file:", str( + context.exception)) + + def test_csv_modelica_at_15_min_timestep(self): + input_file = Path(self.data_dir) / 'building_loads_15min_snippet.csv' + output_modelica_file_name = Path(self.output_dir) / 'modelica_timestep.csv' + + csv_converter = CSVModelica(input_file) + # save the updated time series to the output directory of the test folder + csv_converter.timeseries_to_modelica_data(output_modelica_file_name) + self.assertTrue(output_modelica_file_name.exists()) + + # check if a string is in there + with open(output_modelica_file_name, 'r') as f: + data = f.read() + self.assertTrue('14400,41.8,82.2,1.659,14.7,6.7,1.375' in data) + self.assertTrue('28800,37.7,82.2,0.721,14.9,6.7,2.018' in data) + + def test_csv_modelica_at_60_min_timestep(self): + input_file = Path(self.data_dir) / 'building_loads_snippet.csv' + output_modelica_file_name = Path(self.output_dir) / 'modelica.csv' + + csv_converter = CSVModelica(input_file) + # save the updated time series to the output directory of the test folder + csv_converter.timeseries_to_modelica_data(output_modelica_file_name) + self.assertTrue(output_modelica_file_name.exists()) + + # check if a string is in there + with open(output_modelica_file_name, 'r') as f: + data = f.read() + self.assertTrue('18000,41.9,82.2,1.392,14.6,6.7,1.648' in data) + self.assertTrue('111600,57.2,82.2,5.784,16.2,6.7,3.062' in data) + self.assertFalse('9900,40.1,82.2,0.879,14.9,6.7,1.512' in data) + + def test_csv_modelica_at_60_min_timestep_with_energyplus_file(self): + input_file = Path(self.data_dir) / 'mfrt.csv' + output_modelica_file_name = Path(self.output_dir) / 'mfrt_output.csv' + + csv_converter = CSVModelica(input_file) + # save the updated time series to the output directory of the test folder + csv_converter.timeseries_to_modelica_data(output_modelica_file_name) + self.assertTrue(output_modelica_file_name.exists()) + + # check if a string is in there + with open(output_modelica_file_name, 'r') as f: + data = f.read() + self.assertTrue('18000,42.3,55.0,15.8,6.7,8.275,0.2' in data) + self.assertTrue('111600,41.9,55.0,15.1,6.7,12.32,0.021' in data) + + def test_csv_modelica_no_overwrite(self): + with self.assertRaises(Exception) as context: + input_file = Path(self.data_dir) / 'building_loads_snippet.csv' + csv_converter = CSVModelica(input_file) + csv_converter.timeseries_to_modelica_data(output_modelica_file_name, overwrite=False) + self.assertIn( + "Output file already exists and overwrite is False:", str( + context.exception)) diff --git a/tests/modelica/test_input_parser.py b/tests/modelica/test_input_parser.py index c7251a102..cc2b87e9a 100644 --- a/tests/modelica/test_input_parser.py +++ b/tests/modelica/test_input_parser.py @@ -1,176 +1,176 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import filecmp -# import os -# import unittest - -# from geojson_modelica_translator.modelica.input_parser import InputParser - - -# class InputParserTest(unittest.TestCase): -# def setUp(self): -# self.data_dir = os.path.join(os.path.dirname(__file__), 'data') -# self.output_dir = os.path.join(os.path.dirname(__file__), 'output') -# if not os.path.exists(self.output_dir): -# os.makedirs(self.output_dir) - -# def test_missing_file(self): -# fn = "non-existent-path" -# with self.assertRaises(Exception) as exc: -# InputParser(fn) -# self.assertEqual(f"Modelica file does not exist: {fn}", str(exc.exception)) - -# def test_roundtrip(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_1.mo") -# f = InputParser(filename) -# f.save_as(new_filename) -# # Previous file should be the same as the updated file -# self.assertTrue(filecmp.cmp(filename, new_filename)) - -# def test_remove_object(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_2.mo") -# f1 = InputParser(filename) -# f1.remove_object("ReaderTMY3") -# f1.save_as(new_filename) -# self.assertFalse(filecmp.cmp(filename, new_filename)) - -# f1.reload() -# f2 = InputParser(new_filename) -# self.assertGreater(len(f1.model["objects"]), len(f2.model["objects"])) -# # verify that it exists in f1 but not in f2 -# self.assertGreaterEqual(f1.find_model_object("ReaderTMY3")[0], 0) -# self.assertIsNone(f2.find_model_object("ReaderTMY3")[0]) - -# def test_gsub_field(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_3.mo") -# f1 = InputParser(filename) -# # This example is actually updating an annotation object, not a model, but leave it here for now. -# f1.replace_model_string( -# "Modelica.Blocks.Sources.CombiTimeTable", -# "internalGains", -# "Internals", -# "NotInternals", -# ) -# f1.save_as(new_filename) - -# f2 = InputParser(new_filename) -# index, model = f2.find_model_object( -# "Modelica.Blocks.Sources.CombiTimeTable internalGains" -# ) -# self.assertFalse(filecmp.cmp(filename, new_filename)) -# # the 5th index is the rotation... non-ideal look up -# self.assertTrue("NotInternals" in model) - -# def test_rename_filename(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_4.mo") -# f1 = InputParser(filename) -# # This example is actually updating an annotation object, not a model, but leave it here for now. -# f1.replace_model_string( -# 'Modelica.Blocks.Sources.CombiTimeTable', -# 'internalGains', -# 'modelica://Project/B5a6b99ec37f4de7f94020090/B5a6b99ec37f4de7f94020090_Models/InternalGains_B5a6b99ec37f4de7f94020090Floor.mat', # noqa -# 'modelica://a/new/path.mat' -# ) -# f1.save_as(new_filename) - -# f2 = InputParser(new_filename) -# index, model = f2.find_model_object( -# "Modelica.Blocks.Sources.CombiTimeTable internalGains" -# ) -# self.assertFalse(filecmp.cmp(filename, new_filename)) -# # the 5th index is the rotation... non-ideal look up -# self.assertTrue("a/new/path.mat" in model) - -# def test_add_model_obj(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_5.mo") -# f1 = InputParser(filename) -# data = [ -# 'annotation (Placement(transformation(extent={{-10,90},{10,110}}), iconTransformation(extent={{-10,90},{10,110}})));' # noqa -# ] -# f1.add_model_object( -# "Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a", "port_a", data -# ) -# f1.save_as(new_filename) - -# # verify in the new file that the new model object exists -# f2 = InputParser(new_filename) -# index, model = f2.find_model_object( -# "Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a" -# ) -# self.assertFalse(filecmp.cmp(filename, new_filename)) -# self.assertGreaterEqual(index, 0) - -# def test_gsub_connect(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_6.mo") -# f1 = InputParser(filename) -# f1.add_connect( -# "port_a", -# "thermalZoneTwoElements.intGainsConv", -# "annotation (Line(points={{0,100},{96,100},{96,20},{92,20}}, color={191,0,0}))", -# ) -# f1.save_as(new_filename) - -# # verify in the new file that the new model object exists -# f2 = InputParser(new_filename) -# self.assertFalse(filecmp.cmp(filename, new_filename)) -# index, c = f2.find_connect("port_a", "thermalZoneTwoElements.intGainsConv") -# self.assertGreaterEqual(index, 0) - -# def test_rename_connection(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_7.mo") -# f1 = InputParser(filename) -# # connect(weaDat.weaBus, HDifTil[3].weaBus) -# f1.replace_connect_string( -# "eqAirTemp.TEqAir", "prescribedTemperature.T", "NothingOfImportance", None -# ) -# f1.replace_connect_string("weaDat.weaBus", None, "weaBus", None, True) -# f1.save_as(new_filename) - -# f2 = InputParser(new_filename) -# self.assertFalse(filecmp.cmp(filename, new_filename)) -# index, c = f2.find_connect('weaBus', 'weaBus') -# # there should exist the new connection -# self.assertGreaterEqual(index, 0) - -# # the old one should not exist -# index, c = f2.find_connect('weaDat.weaBus', 'weaBus') -# self.assertIsNone(index) - -# def test_remove_connection(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_8.mo") -# f1 = InputParser(filename) -# f1.remove_connect_string('weaDat.weaBus', 'weaBus') -# f1.save_as(new_filename) - -# f2 = InputParser(new_filename) -# self.assertFalse(filecmp.cmp(filename, new_filename)) -# index, c = f2.find_connect('weaDat.weaBus', 'weaBus') -# # the connection should no longer exist -# self.assertIsNone(index) - -# def test_modelica_parameter(self): -# filename = os.path.join(self.data_dir, "test_1.mo") -# new_filename = os.path.join(self.output_dir, "test_1_output_9.mo") -# f1 = InputParser(filename) -# f1.add_parameter('Real', 'aVarNam', 0.8, "A description where aVarName is 0.8") -# f1.add_parameter('String', 'aVarNamStr', 'A-string-value', "A description string A-string-value") -# f1.save_as(new_filename) - -# # just read the file and ensure that the string exists -# test_strs = [ -# 'parameter String aVarNamStr="A-string-value" "A description string A-string-value";', -# 'parameter Real aVarNam=0.8 "A description where aVarName is 0.8";' -# ] -# with open(new_filename) as f: -# file_data = f.read() -# for test_str in test_strs: -# self.assertIn(test_str, file_data) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import filecmp +import os +import unittest + +from geojson_modelica_translator.modelica.input_parser import InputParser + + +class InputParserTest(unittest.TestCase): + def setUp(self): + self.data_dir = os.path.join(os.path.dirname(__file__), 'data') + self.output_dir = os.path.join(os.path.dirname(__file__), 'output') + if not os.path.exists(self.output_dir): + os.makedirs(self.output_dir) + + def test_missing_file(self): + fn = "non-existent-path" + with self.assertRaises(Exception) as exc: + InputParser(fn) + self.assertEqual(f"Modelica file does not exist: {fn}", str(exc.exception)) + + def test_roundtrip(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_1.mo") + f = InputParser(filename) + f.save_as(new_filename) + # Previous file should be the same as the updated file + self.assertTrue(filecmp.cmp(filename, new_filename)) + + def test_remove_object(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_2.mo") + f1 = InputParser(filename) + f1.remove_object("ReaderTMY3") + f1.save_as(new_filename) + self.assertFalse(filecmp.cmp(filename, new_filename)) + + f1.reload() + f2 = InputParser(new_filename) + self.assertGreater(len(f1.model["objects"]), len(f2.model["objects"])) + # verify that it exists in f1 but not in f2 + self.assertGreaterEqual(f1.find_model_object("ReaderTMY3")[0], 0) + self.assertIsNone(f2.find_model_object("ReaderTMY3")[0]) + + def test_gsub_field(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_3.mo") + f1 = InputParser(filename) + # This example is actually updating an annotation object, not a model, but leave it here for now. + f1.replace_model_string( + "Modelica.Blocks.Sources.CombiTimeTable", + "internalGains", + "Internals", + "NotInternals", + ) + f1.save_as(new_filename) + + f2 = InputParser(new_filename) + index, model = f2.find_model_object( + "Modelica.Blocks.Sources.CombiTimeTable internalGains" + ) + self.assertFalse(filecmp.cmp(filename, new_filename)) + # the 5th index is the rotation... non-ideal look up + self.assertTrue("NotInternals" in model) + + def test_rename_filename(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_4.mo") + f1 = InputParser(filename) + # This example is actually updating an annotation object, not a model, but leave it here for now. + f1.replace_model_string( + 'Modelica.Blocks.Sources.CombiTimeTable', + 'internalGains', + 'modelica://Project/B5a6b99ec37f4de7f94020090/B5a6b99ec37f4de7f94020090_Models/InternalGains_B5a6b99ec37f4de7f94020090Floor.mat', # noqa + 'modelica://a/new/path.mat' + ) + f1.save_as(new_filename) + + f2 = InputParser(new_filename) + index, model = f2.find_model_object( + "Modelica.Blocks.Sources.CombiTimeTable internalGains" + ) + self.assertFalse(filecmp.cmp(filename, new_filename)) + # the 5th index is the rotation... non-ideal look up + self.assertTrue("a/new/path.mat" in model) + + def test_add_model_obj(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_5.mo") + f1 = InputParser(filename) + data = [ + 'annotation (Placement(transformation(extent={{-10,90},{10,110}}), iconTransformation(extent={{-10,90},{10,110}})));' # noqa + ] + f1.add_model_object( + "Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a", "port_a", data + ) + f1.save_as(new_filename) + + # verify in the new file that the new model object exists + f2 = InputParser(new_filename) + index, model = f2.find_model_object( + "Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a" + ) + self.assertFalse(filecmp.cmp(filename, new_filename)) + self.assertGreaterEqual(index, 0) + + def test_gsub_connect(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_6.mo") + f1 = InputParser(filename) + f1.add_connect( + "port_a", + "thermalZoneTwoElements.intGainsConv", + "annotation (Line(points={{0,100},{96,100},{96,20},{92,20}}, color={191,0,0}))", + ) + f1.save_as(new_filename) + + # verify in the new file that the new model object exists + f2 = InputParser(new_filename) + self.assertFalse(filecmp.cmp(filename, new_filename)) + index, c = f2.find_connect("port_a", "thermalZoneTwoElements.intGainsConv") + self.assertGreaterEqual(index, 0) + + def test_rename_connection(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_7.mo") + f1 = InputParser(filename) + # connect(weaDat.weaBus, HDifTil[3].weaBus) + f1.replace_connect_string( + "eqAirTemp.TEqAir", "prescribedTemperature.T", "NothingOfImportance", None + ) + f1.replace_connect_string("weaDat.weaBus", None, "weaBus", None, True) + f1.save_as(new_filename) + + f2 = InputParser(new_filename) + self.assertFalse(filecmp.cmp(filename, new_filename)) + index, c = f2.find_connect('weaBus', 'weaBus') + # there should exist the new connection + self.assertGreaterEqual(index, 0) + + # the old one should not exist + index, c = f2.find_connect('weaDat.weaBus', 'weaBus') + self.assertIsNone(index) + + def test_remove_connection(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_8.mo") + f1 = InputParser(filename) + f1.remove_connect_string('weaDat.weaBus', 'weaBus') + f1.save_as(new_filename) + + f2 = InputParser(new_filename) + self.assertFalse(filecmp.cmp(filename, new_filename)) + index, c = f2.find_connect('weaDat.weaBus', 'weaBus') + # the connection should no longer exist + self.assertIsNone(index) + + def test_modelica_parameter(self): + filename = os.path.join(self.data_dir, "test_1.mo") + new_filename = os.path.join(self.output_dir, "test_1_output_9.mo") + f1 = InputParser(filename) + f1.add_parameter('Real', 'aVarNam', 0.8, "A description where aVarName is 0.8") + f1.add_parameter('String', 'aVarNamStr', 'A-string-value', "A description string A-string-value") + f1.save_as(new_filename) + + # just read the file and ensure that the string exists + test_strs = [ + 'parameter String aVarNamStr="A-string-value" "A description string A-string-value";', + 'parameter Real aVarNam=0.8 "A description where aVarName is 0.8";' + ] + with open(new_filename) as f: + file_data = f.read() + for test_str in test_strs: + self.assertIn(test_str, file_data) diff --git a/tests/modelica/test_modelica_runner.py b/tests/modelica/test_modelica_runner.py index b72ef273c..2c391d6a5 100644 --- a/tests/modelica/test_modelica_runner.py +++ b/tests/modelica/test_modelica_runner.py @@ -1,230 +1,230 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import os -# import shutil -# import unittest -# import logging -# import inspect -# import pytest - -# from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner -# from pathlib import Path - -# logger = logging.getLogger(__name__) - - -# class ModelicaRunnerTest(unittest.TestCase): -# def setUp(self): -# # create a run directory and copy in a project to test run -# self.data_dir = os.path.join(os.path.dirname(__file__), 'data') -# self.run_path = os.path.join(os.path.dirname(__file__), 'output', 'simdir') -# self.fmu_run_path = os.path.join(os.path.dirname(__file__), 'output', 'fmudir') -# self.mbl_run_path = os.path.join(os.path.dirname(__file__), 'output', 'mbldir') -# self.msl_run_path = os.path.join(os.path.dirname(__file__), 'output', 'msldir') - -# # remove the run directory if it exists and recreate -# for p in [self.run_path, self.fmu_run_path, self.mbl_run_path, self.msl_run_path]: -# if os.path.exists(p): -# shutil.rmtree(p) -# os.makedirs(p) - -# # copy in the test modelica file -# shutil.copyfile( -# os.path.join(self.data_dir, 'BouncingBall.mo'), -# os.path.join(self.run_path, 'BouncingBall.mo') -# ) -# shutil.copyfile( -# os.path.join(self.data_dir, 'BouncingBall.fmu'), -# os.path.join(self.fmu_run_path, 'BouncingBall.fmu') -# ) - -# @pytest.mark.docker -# def test_docker_enabled(self): -# mr = ModelicaRunner() -# self.assertTrue(mr.docker_configured, 'Docker is not running, unable to run all tests') - -# @pytest.mark.docker -# def test_invalid_action(self): -# mr = ModelicaRunner() -# with self.assertRaises(SystemExit) as excinfo: -# mr.run_in_docker('unreal', None) -# self.assertIn('unreal', str(excinfo.exception)) -# self.assertIn("must be one of ['compile'", str(excinfo.exception)) - -# @pytest.mark.simulation -# def test_run_in_docker_errors(self): -# mr = ModelicaRunner() -# file_to_run = os.path.join(self.run_path, 'no_file.mo') -# with self.assertRaises(SystemExit) as exc: -# mr.run_in_docker('compile', 'no_file', file_to_load=file_to_run) -# self.assertEqual(f'File not found to run {file_to_run}', str(exc.exception)) - -# @pytest.mark.compilation -# def test_compile_bouncing_ball_in_docker(self): -# # cleanup output path -# results_path = os.path.join(self.run_path, 'BouncingBall_results') -# shutil.rmtree(results_path, ignore_errors=True) - -# # compile the project -# mr = ModelicaRunner() -# success, _ = mr.run_in_docker('compile', 'BouncingBall', -# file_to_load = os.path.join(self.run_path, 'BouncingBall.mo'), -# run_path=self.run_path) - -# self.assertTrue(success) -# self.assertTrue(os.path.exists(os.path.join(results_path, 'BouncingBall.fmu'))) -# self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) -# # Write out the log to the logger for debugging -# # with open(os.path.join(self.run_path, 'stdout.log')) as f: -# # logger.info(f.read()) -# self.assertFalse(os.path.exists(os.path.join(results_path, 'compile_fmu.mos'))) -# self.assertFalse(os.path.exists(os.path.join(results_path, 'simulate.mos'))) - -# @pytest.mark.simulation -# def test_simulate_bouncing_ball_in_docker(self): -# mr = ModelicaRunner() -# success, _ = mr.run_in_docker('compile_and_run', 'BouncingBall', -# file_to_load = os.path.join(self.run_path, 'BouncingBall.mo'), -# run_path=self.run_path) - -# self.assertTrue(success) - -# results_path = os.path.join(self.run_path, 'BouncingBall_results') -# self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) -# self.assertTrue(os.path.exists(os.path.join(results_path, 'BouncingBall_res.mat'))) -# self.assertFalse(os.path.exists(os.path.join(results_path, 'om_docker.sh'))) - -# @pytest.mark.simulation -# @pytest.mark.skip(reason='Need to install libfortran.so.4 in docker image') -# def test_simulate_fmu_in_docker(self): -# # TODO: this breaks at the moment due to the libfortran.so.4 error. -# # cleanup output path -# results_path = os.path.join(self.fmu_run_path, 'BouncingBall_results') -# shutil.rmtree(results_path, ignore_errors=True) - -# # run the project -# mr = ModelicaRunner() -# mr.run_in_docker('run', 'BouncingBall', -# file_to_load = os.path.join(self.fmu_run_path, 'BouncingBall.fmu'), -# run_path = self.fmu_run_path) - -# self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) -# self.assertTrue(os.path.exists(os.path.join(results_path, 'BouncingBall_result.mat'))) -# self.assertFalse(os.path.exists(os.path.join(results_path, 'om_docker.sh'))) - -# @pytest.mark.compilation -# def test_compile_msl_in_docker(self): -# model_name = 'Modelica.Blocks.Examples.PID_Controller' -# results_path = os.path.join(self.msl_run_path, f"{model_name}_results") -# shutil.rmtree(results_path, ignore_errors=True) - -# mr = ModelicaRunner() -# success, _ = mr.run_in_docker('compile', model_name, run_path=self.msl_run_path, project_in_library=True) - -# self.assertTrue(success) -# self.assertTrue((Path(results_path) / 'stdout.log').exists()) -# fmu_basename = model_name.split('.')[-1] -# self.assertTrue((Path(results_path).parent / f'{fmu_basename}.fmu').exists()) - -# @pytest.mark.simulation -# def test_simulate_msl_in_docker(self): -# model_name = 'Modelica.Blocks.Examples.PID_Controller' -# results_path = os.path.join(self.msl_run_path, f"{model_name}_results") -# shutil.rmtree(results_path, ignore_errors=True) - -# mr = ModelicaRunner() -# success, _ = mr.run_in_docker('compile_and_run', model_name, run_path=self.msl_run_path, project_in_library=True) - -# self.assertTrue(success) -# self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) -# self.assertTrue(os.path.exists(os.path.join(results_path, f'{model_name}_res.mat'))) - -# @pytest.mark.simulation -# def test_simulate_msl_with_start_times_in_docker(self): -# model_name = 'Modelica.Blocks.Examples.PID_Controller' -# results_path = os.path.join(self.msl_run_path, f"{model_name}_results") -# shutil.rmtree(results_path, ignore_errors=True) - -# mr = ModelicaRunner() -# success, _ = mr.run_in_docker('compile_and_run', model_name, -# run_path=self.msl_run_path, project_in_library=True, -# start_time=0, stop_time=60, step_size=0.1) - -# self.assertTrue(success) -# self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) -# self.assertTrue(os.path.exists(os.path.join(results_path, f'{model_name}_res.mat'))) - -# @pytest.mark.simulation -# def test_simulate_msl_with_intervals_in_docker(self): -# model_name = 'Modelica.Blocks.Examples.PID_Controller' -# results_path = Path(self.msl_run_path) / f"{model_name}_results" -# shutil.rmtree(results_path, ignore_errors=True) - -# mr = ModelicaRunner() -# success, _ = mr.run_in_docker('compile_and_run', model_name, -# run_path=self.msl_run_path, project_in_library=True, -# start_time=0, stop_time=60, number_of_intervals=6) - -# self.assertTrue(success) -# self.assertTrue((results_path / 'stdout.log').exists()) -# self.assertTrue((results_path / f'{model_name}_res.mat').exists()) - -# @pytest.mark.simulation -# def test_simulate_mbl_pid_in_docker(self): -# model_name = 'Buildings.Controls.OBC.CDL.Reals.Validation.PID' - -# mr = ModelicaRunner() -# success, _ = mr.run_in_docker( -# 'compile_and_run', model_name, run_path=self.mbl_run_path, project_in_library=True -# ) -# self.assertTrue(success) - -# @pytest.mark.dymola -# def test_simulate_msl_in_dymola(self): -# model_name = 'Modelica.Blocks.Examples.PID_Controller' -# results_path = Path(self.msl_run_path) / f"{inspect.currentframe().f_code.co_name}_results" -# if results_path.exists(): -# shutil.rmtree(results_path, ignore_errors=True) -# results_path.mkdir(parents=True) - -# # shutil.rmtree(results_path, ignore_errors=True) - -# mr = ModelicaRunner() -# success, _ = mr.run_in_dymola( -# 'simulate', model_name, run_path=results_path, file_to_load=None -# ) - -# self.assertTrue(success) -# # self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) -# # self.assertTrue(os.path.exists(os.path.join(results_path, f'{model_name}.fmu'))) - -# @pytest.mark.dymola -# def test_simulate_mbl_pid_in_dymola(self): -# results_path = Path(self.mbl_run_path) / f"{inspect.currentframe().f_code.co_name}_results" -# if results_path.exists(): -# shutil.rmtree(results_path, ignore_errors=True) -# results_path.mkdir(parents=True) - -# model_name = 'Buildings.Controls.OBC.CDL.Reals.Validation.PID' - -# mr = ModelicaRunner() -# success, _ = mr.run_in_dymola( -# 'simulate', model_name, run_path=results_path, file_to_load=None # , debug=True -# ) -# self.assertTrue(success) - -# @pytest.mark.dymola -# def test_compile_mbl_pid_in_dymola(self): -# results_path = Path(self.mbl_run_path) / f"{inspect.currentframe().f_code.co_name}_results" -# if results_path.exists(): -# shutil.rmtree(results_path, ignore_errors=True) -# results_path.mkdir(parents=True) - -# model_name = 'Buildings.Controls.OBC.CDL.Reals.Validation.PID' - -# mr = ModelicaRunner() -# success, _ = mr.run_in_dymola( -# 'compile', model_name, run_path=results_path, file_to_load=None, debug=True -# ) -# self.assertTrue(success) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import os +import shutil +import unittest +import logging +import inspect +import pytest + +from geojson_modelica_translator.modelica.modelica_runner import ModelicaRunner +from pathlib import Path + +logger = logging.getLogger(__name__) + + +class ModelicaRunnerTest(unittest.TestCase): + def setUp(self): + # create a run directory and copy in a project to test run + self.data_dir = os.path.join(os.path.dirname(__file__), 'data') + self.run_path = os.path.join(os.path.dirname(__file__), 'output', 'simdir') + self.fmu_run_path = os.path.join(os.path.dirname(__file__), 'output', 'fmudir') + self.mbl_run_path = os.path.join(os.path.dirname(__file__), 'output', 'mbldir') + self.msl_run_path = os.path.join(os.path.dirname(__file__), 'output', 'msldir') + + # remove the run directory if it exists and recreate + for p in [self.run_path, self.fmu_run_path, self.mbl_run_path, self.msl_run_path]: + if os.path.exists(p): + shutil.rmtree(p) + os.makedirs(p) + + # copy in the test modelica file + shutil.copyfile( + os.path.join(self.data_dir, 'BouncingBall.mo'), + os.path.join(self.run_path, 'BouncingBall.mo') + ) + shutil.copyfile( + os.path.join(self.data_dir, 'BouncingBall.fmu'), + os.path.join(self.fmu_run_path, 'BouncingBall.fmu') + ) + + @pytest.mark.docker + def test_docker_enabled(self): + mr = ModelicaRunner() + self.assertTrue(mr.docker_configured, 'Docker is not running, unable to run all tests') + + @pytest.mark.docker + def test_invalid_action(self): + mr = ModelicaRunner() + with self.assertRaises(SystemExit) as excinfo: + mr.run_in_docker('unreal', None) + self.assertIn('unreal', str(excinfo.exception)) + self.assertIn("must be one of ['compile'", str(excinfo.exception)) + + @pytest.mark.simulation + def test_run_in_docker_errors(self): + mr = ModelicaRunner() + file_to_run = os.path.join(self.run_path, 'no_file.mo') + with self.assertRaises(SystemExit) as exc: + mr.run_in_docker('compile', 'no_file', file_to_load=file_to_run) + self.assertEqual(f'File not found to run {file_to_run}', str(exc.exception)) + + @pytest.mark.compilation + def test_compile_bouncing_ball_in_docker(self): + # cleanup output path + results_path = os.path.join(self.run_path, 'BouncingBall_results') + shutil.rmtree(results_path, ignore_errors=True) + + # compile the project + mr = ModelicaRunner() + success, _ = mr.run_in_docker('compile', 'BouncingBall', + file_to_load = os.path.join(self.run_path, 'BouncingBall.mo'), + run_path=self.run_path) + + self.assertTrue(success) + self.assertTrue(os.path.exists(os.path.join(results_path, 'BouncingBall.fmu'))) + self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) + # Write out the log to the logger for debugging + # with open(os.path.join(self.run_path, 'stdout.log')) as f: + # logger.info(f.read()) + self.assertFalse(os.path.exists(os.path.join(results_path, 'compile_fmu.mos'))) + self.assertFalse(os.path.exists(os.path.join(results_path, 'simulate.mos'))) + + @pytest.mark.simulation + def test_simulate_bouncing_ball_in_docker(self): + mr = ModelicaRunner() + success, _ = mr.run_in_docker('compile_and_run', 'BouncingBall', + file_to_load = os.path.join(self.run_path, 'BouncingBall.mo'), + run_path=self.run_path) + + self.assertTrue(success) + + results_path = os.path.join(self.run_path, 'BouncingBall_results') + self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) + self.assertTrue(os.path.exists(os.path.join(results_path, 'BouncingBall_res.mat'))) + self.assertFalse(os.path.exists(os.path.join(results_path, 'om_docker.sh'))) + + @pytest.mark.simulation + @pytest.mark.skip(reason='Need to install libfortran.so.4 in docker image') + def test_simulate_fmu_in_docker(self): + # TODO: this breaks at the moment due to the libfortran.so.4 error. + # cleanup output path + results_path = os.path.join(self.fmu_run_path, 'BouncingBall_results') + shutil.rmtree(results_path, ignore_errors=True) + + # run the project + mr = ModelicaRunner() + mr.run_in_docker('run', 'BouncingBall', + file_to_load = os.path.join(self.fmu_run_path, 'BouncingBall.fmu'), + run_path = self.fmu_run_path) + + self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) + self.assertTrue(os.path.exists(os.path.join(results_path, 'BouncingBall_result.mat'))) + self.assertFalse(os.path.exists(os.path.join(results_path, 'om_docker.sh'))) + + @pytest.mark.compilation + def test_compile_msl_in_docker(self): + model_name = 'Modelica.Blocks.Examples.PID_Controller' + results_path = os.path.join(self.msl_run_path, f"{model_name}_results") + shutil.rmtree(results_path, ignore_errors=True) + + mr = ModelicaRunner() + success, _ = mr.run_in_docker('compile', model_name, run_path=self.msl_run_path, project_in_library=True) + + self.assertTrue(success) + self.assertTrue((Path(results_path) / 'stdout.log').exists()) + fmu_basename = model_name.split('.')[-1] + self.assertTrue((Path(results_path).parent / f'{fmu_basename}.fmu').exists()) + + @pytest.mark.simulation + def test_simulate_msl_in_docker(self): + model_name = 'Modelica.Blocks.Examples.PID_Controller' + results_path = os.path.join(self.msl_run_path, f"{model_name}_results") + shutil.rmtree(results_path, ignore_errors=True) + + mr = ModelicaRunner() + success, _ = mr.run_in_docker('compile_and_run', model_name, run_path=self.msl_run_path, project_in_library=True) + + self.assertTrue(success) + self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) + self.assertTrue(os.path.exists(os.path.join(results_path, f'{model_name}_res.mat'))) + + @pytest.mark.simulation + def test_simulate_msl_with_start_times_in_docker(self): + model_name = 'Modelica.Blocks.Examples.PID_Controller' + results_path = os.path.join(self.msl_run_path, f"{model_name}_results") + shutil.rmtree(results_path, ignore_errors=True) + + mr = ModelicaRunner() + success, _ = mr.run_in_docker('compile_and_run', model_name, + run_path=self.msl_run_path, project_in_library=True, + start_time=0, stop_time=60, step_size=0.1) + + self.assertTrue(success) + self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) + self.assertTrue(os.path.exists(os.path.join(results_path, f'{model_name}_res.mat'))) + + @pytest.mark.simulation + def test_simulate_msl_with_intervals_in_docker(self): + model_name = 'Modelica.Blocks.Examples.PID_Controller' + results_path = Path(self.msl_run_path) / f"{model_name}_results" + shutil.rmtree(results_path, ignore_errors=True) + + mr = ModelicaRunner() + success, _ = mr.run_in_docker('compile_and_run', model_name, + run_path=self.msl_run_path, project_in_library=True, + start_time=0, stop_time=60, number_of_intervals=6) + + self.assertTrue(success) + self.assertTrue((results_path / 'stdout.log').exists()) + self.assertTrue((results_path / f'{model_name}_res.mat').exists()) + + @pytest.mark.simulation + def test_simulate_mbl_pid_in_docker(self): + model_name = 'Buildings.Controls.OBC.CDL.Reals.Validation.PID' + + mr = ModelicaRunner() + success, _ = mr.run_in_docker( + 'compile_and_run', model_name, run_path=self.mbl_run_path, project_in_library=True + ) + self.assertTrue(success) + + @pytest.mark.dymola + def test_simulate_msl_in_dymola(self): + model_name = 'Modelica.Blocks.Examples.PID_Controller' + results_path = Path(self.msl_run_path) / f"{inspect.currentframe().f_code.co_name}_results" + if results_path.exists(): + shutil.rmtree(results_path, ignore_errors=True) + results_path.mkdir(parents=True) + + # shutil.rmtree(results_path, ignore_errors=True) + + mr = ModelicaRunner() + success, _ = mr.run_in_dymola( + 'simulate', model_name, run_path=results_path, file_to_load=None + ) + + self.assertTrue(success) + # self.assertTrue(os.path.exists(os.path.join(results_path, 'stdout.log'))) + # self.assertTrue(os.path.exists(os.path.join(results_path, f'{model_name}.fmu'))) + + @pytest.mark.dymola + def test_simulate_mbl_pid_in_dymola(self): + results_path = Path(self.mbl_run_path) / f"{inspect.currentframe().f_code.co_name}_results" + if results_path.exists(): + shutil.rmtree(results_path, ignore_errors=True) + results_path.mkdir(parents=True) + + model_name = 'Buildings.Controls.OBC.CDL.Reals.Validation.PID' + + mr = ModelicaRunner() + success, _ = mr.run_in_dymola( + 'simulate', model_name, run_path=results_path, file_to_load=None # , debug=True + ) + self.assertTrue(success) + + @pytest.mark.dymola + def test_compile_mbl_pid_in_dymola(self): + results_path = Path(self.mbl_run_path) / f"{inspect.currentframe().f_code.co_name}_results" + if results_path.exists(): + shutil.rmtree(results_path, ignore_errors=True) + results_path.mkdir(parents=True) + + model_name = 'Buildings.Controls.OBC.CDL.Reals.Validation.PID' + + mr = ModelicaRunner() + success, _ = mr.run_in_dymola( + 'compile', model_name, run_path=results_path, file_to_load=None, debug=True + ) + self.assertTrue(success) diff --git a/tests/system_parameters/test_system_parameters.py b/tests/system_parameters/test_system_parameters.py index b3df65513..cc96345e3 100644 --- a/tests/system_parameters/test_system_parameters.py +++ b/tests/system_parameters/test_system_parameters.py @@ -1,484 +1,484 @@ -# # :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. -# # See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md - -# import json -# import os -# import unittest -# from pathlib import Path -# from shutil import rmtree - -# import pytest - -# from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters - - -# class SystemParametersTest(unittest.TestCase): -# def setUp(self): -# self.data_dir = Path(__file__).parent / "data" -# self.output_dir = Path(__file__).parent / "output" -# self.weather_dir = self.output_dir / "weatherfiles" -# self.scenario_dir = self.data_dir / "sdk_output_skeleton" / "run" / "baseline_15min" -# self.microgrid_scenario_dir = self.data_dir / "sdk_microgrid_output_skeleton" / "run" / "reopt_scenario" -# self.microgrid_feature_file = self.data_dir / "sdk_microgrid_output_skeleton" / "example_project.json" -# self.microgrid_output_dir = Path(__file__).parent / "microgrid_output" -# self.feature_file = self.data_dir / "sdk_output_skeleton" / "example_project.json" -# self.sys_param_template = ( -# Path(__file__).parent.parent.parent -# / "geojson_modelica_translator" -# / "system_parameters" -# / "time_series_template.json" -# ) -# if self.output_dir.exists(): -# rmtree(self.output_dir) -# self.output_dir.mkdir(parents=True) -# if self.weather_dir.exists(): -# rmtree(self.weather_dir) -# self.weather_dir.mkdir(parents=True) -# if self.microgrid_output_dir.exists(): -# rmtree(self.microgrid_output_dir) -# self.microgrid_output_dir.mkdir(parents=True) - -# def test_expanded_paths(self): -# filename = self.data_dir / "system_params_1.json" -# sdp = SystemParameters(filename) -# for s in sdp.validate(): -# print(s) -# value = sdp.get_param_by_id("ijk678", "load_model_parameters.spawn.idf_filename") -# assert Path(value) == Path(filename).parent / "example_model.idf" -# value = sdp.get_param("$.weather") -# assert Path(value) == Path(filename).parent / "../../data_shared/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos" - -# # verify that the second spawn paths resolve too. -# value = sdp.get_param_by_id("lmn000", "load_model_parameters.spawn.idf_filename") -# assert Path(value) == Path(filename).parent / "example_model_2.idf" - -# def test_load_system_parameters_1(self): -# filename = self.data_dir / "system_params_1.json" -# sdp = SystemParameters(filename) -# assert sdp.param_template["buildings"][1]["load_model_parameters"]["rc"]["order"] == 2 - -# def test_load_system_parameters_2(self): -# filename = self.data_dir / "system_params_2.json" -# sdp = SystemParameters(filename) -# assert sdp is not None - -# def test_valid_system_parameters_ghe(self): -# filename = self.data_dir / "system_params_ghe.json" -# sdp = SystemParameters(filename) -# assert sdp is not None -# assert len(sdp.validate()) == 0 -# assert sdp.validate() == [] - -# def test_error_system_parameters_ghe(self): -# filename = self.data_dir / "system_params_ghe_invalid.json" -# with pytest.raises(ValueError, match="Invalid"): -# SystemParameters(filename) - -# def test_missing_file(self): -# fn = "non-existent-path" -# with pytest.raises(FileNotFoundError, match=f"System design parameters file does not exist: {fn}"): -# SystemParameters(fn) - -# def test_errors(self): -# incomplete_teaser_params = { -# "buildings": [ -# { -# "geojson_id": "asdf", -# "ets_model": "None", -# "load_model": "rc", -# "load_model_parameters": {"rc": {"order": 5}}, -# } -# ] -# } - -# with pytest.raises(ValueError, match="Invalid system parameter"): -# SystemParameters.loadd(incomplete_teaser_params) - -# sp = SystemParameters.loadd(incomplete_teaser_params, validate_on_load=False) -# assert "'None' is not one of ['Indirect Heating and Cooling', 'Fifth Gen Heat Pump']" in sp.validate() -# assert "'fraction_latent_person' is a required property" in sp.validate() -# assert "'temp_hw_supply' is a required property" in sp.validate() -# assert "'temp_setpoint_cooling' is a required property" in sp.validate() -# assert "'temp_setpoint_heating' is a required property" in sp.validate() -# assert "5 is not one of [1, 2, 3, 4]" in sp.validate() -# assert len(sp.validate()) == 8 - -# def test_get_param(self): -# data = { -# "weather": "path/to/weatherfile.mos", -# "buildings": [ -# { -# "geojson_id": "asdf", -# "ets_model": "Indirect Heating and Cooling", -# "ets_indirect_parameters": { -# "heat_flow_nominal": 8000, -# "heat_exchanger_efficiency": 0.8, -# "nominal_mass_flow_district": 0.5, -# "nominal_mass_flow_building": 0.5, -# "valve_pressure_drop": 6000, -# "heat_exchanger_secondary_pressure_drop": 500, -# "heat_exchanger_primary_pressure_drop": 500, -# "cooling_supply_water_temperature_building": 7, -# "heating_supply_water_temperature_building": 50, -# "delta_temp_chw_building": 5, -# "delta_temp_chw_district": 8, -# "delta_temp_hw_building": 15, -# "delta_temp_hw_district": 20, -# "cooling_controller_y_max": 1, -# "cooling_controller_y_min": 0, -# "heating_controller_y_max": 1, -# "heating_controller_y_min": 0, -# }, -# "load_model": "rc", -# "load_model_parameters": { -# "rc": { -# "order": 4, -# "fraction_latent_person": 1.25, -# "temp_hw_supply": 40, -# "temp_setpoint_heating": 40, -# "temp_setpoint_cooling": 24, -# } -# }, -# } -# ], -# } -# sp = SystemParameters.loadd(data) -# value = sp.get_param("$.buildings.[*].load_model_parameters.rc.order") -# assert value == 4 - -# value = sp.get_param("buildings.[*].load_model") -# assert value == "rc" - -# value = sp.get_param("buildings") -# assert value == [ -# { -# "geojson_id": "asdf", -# "ets_model": "Indirect Heating and Cooling", -# "ets_indirect_parameters": { -# "heat_flow_nominal": 8000, -# "heat_exchanger_efficiency": 0.8, -# "nominal_mass_flow_district": 0.5, -# "nominal_mass_flow_building": 0.5, -# "valve_pressure_drop": 6000, -# "heat_exchanger_secondary_pressure_drop": 500, -# "heat_exchanger_primary_pressure_drop": 500, -# "cooling_supply_water_temperature_building": 7, -# "heating_supply_water_temperature_building": 50, -# "delta_temp_chw_building": 5, -# "delta_temp_chw_district": 8, -# "delta_temp_hw_building": 15, -# "delta_temp_hw_district": 20, -# "cooling_controller_y_max": 1, -# "cooling_controller_y_min": 0, -# "heating_controller_y_max": 1, -# "heating_controller_y_min": 0, -# }, -# "load_model": "rc", -# "load_model_parameters": { -# "rc": { -# "order": 4, -# "fraction_latent_person": 1.25, -# "temp_hw_supply": 40, -# "temp_setpoint_heating": 40, -# "temp_setpoint_cooling": 24, -# } -# }, -# } -# ] - -# value = sp.get_param("") -# assert value is None - -# value = sp.get_param("not.a.real.path") -# assert value is None - -# def test_get_param_with_two(self): -# data = { -# "weather": "path/to/weatherfile.mos", -# "buildings": [ -# { -# "geojson_id": "asdf", -# "ets_model": "Indirect Heating and Cooling", -# "ets_indirect_parameters": { -# "heat_flow_nominal": 8000, -# }, -# "load_model": "rc", -# "load_model_parameters": { -# "rc": { -# "order": 4, -# "fraction_latent_person": 1.25, -# "temp_hw_supply": 40, -# "temp_setpoint_heating": 40, -# "temp_setpoint_cooling": 24, -# } -# }, -# }, -# { -# "geojson_id": "qwer", -# "ets_model": "Fifth Gen Heat Pump", -# "ets_indirect_parameters": { -# "heat_flow_nominal": 10000, -# }, -# "load_model": "rc", -# "load_model_parameters": { -# "rc": { -# "order": 4, -# "fraction_latent_person": 1.25, -# "temp_hw_supply": 40, -# "temp_setpoint_heating": 40, -# "temp_setpoint_cooling": 24, -# } -# }, -# }, -# ], -# } -# sp = SystemParameters.loadd(data) -# value = sp.get_param("$.buildings.[*].ets_indirect_parameters.heat_flow_nominal") -# assert value == [8000, 10000] - -# def test_get_param_with_building_id(self): -# filename = self.data_dir / "system_params_1.json" -# sdp = SystemParameters(filename) -# self.maxDiff = None -# value = sdp.get_param_by_id("abcd1234", "ets_model") -# assert value == "Indirect Heating and Cooling" - -# # grab the schema default -# value = sdp.get_param_by_id("defgh2345", "ets_model") -# assert value == "Indirect Heating and Cooling" -# value = sdp.get_param_by_id("defgh2345", "ets_indirect_parameters") -# assert value == { -# "heat_flow_nominal": 8000, -# "heat_exchanger_efficiency": 0.8, -# "nominal_mass_flow_district": 0.5, -# "nominal_mass_flow_building": 0.5, -# "valve_pressure_drop": 6000, -# "heat_exchanger_secondary_pressure_drop": 500, -# "heat_exchanger_primary_pressure_drop": 500, -# "cooling_supply_water_temperature_building": 7, -# "heating_supply_water_temperature_building": 50, -# "delta_temp_chw_building": 5, -# "delta_temp_chw_district": 8, -# "delta_temp_hw_building": 15, -# "delta_temp_hw_district": 20, -# "cooling_controller_y_max": 1, -# "cooling_controller_y_min": 0, -# "heating_controller_y_max": 1, -# "heating_controller_y_min": 0, -# } - -# def test_get_param_with_ghe_id(self): -# # Setup -# filename = self.data_dir / "system_params_ghe.json" -# sdp = SystemParameters(filename) -# self.maxDiff = None - -# # Act -# value = sdp.get_param_by_id("c432cb11-4813-40df-8dd4-e88f5de40033", "borehole") - -# # Assert -# assert value == {"buried_depth": 2.0, "diameter": 0.15} - -# # Act -# second_ghe_borehole = sdp.get_param_by_id("c432cb11-4813-40df-8dd4-e88f5de40034", "borehole") -# # Assert -# assert second_ghe_borehole["buried_depth"] == 10.0 - -# def test_get_param_with_none_building_id(self): -# # Setup -# filename = self.data_dir / "system_params_1.json" -# sdp = SystemParameters(filename) -# self.maxDiff = None - -# # Act -# with pytest.raises(SystemExit) as context: -# sdp.get_param_by_id(None, "ets_model") - -# # Assert -# assert "No id submitted. Please retry and include the appropriate id" in str(context.value) - -# def test_missing_files(self): -# output_sys_param_file = self.output_dir / "going_to_fail_first.json" -# missing_scenario_dir = self.scenario_dir / "foobar" -# sp = SystemParameters() -# with pytest.raises(SystemExit) as context: -# sp.csv_to_sys_param( -# model_type="time_series", -# scenario_dir=missing_scenario_dir, -# feature_file=self.feature_file, -# district_type="4G", -# sys_param_filename=output_sys_param_file, -# ) -# assert f"Unable to find your scenario. The path you provided was: {missing_scenario_dir}" in str(context.value) -# missing_feature_file = self.data_dir / "sdk_output_skeleton" / "foobar.json" -# sp = SystemParameters() -# with pytest.raises(SystemExit) as context: -# sp.csv_to_sys_param( -# model_type="time_series", -# scenario_dir=self.scenario_dir, -# feature_file=missing_feature_file, -# district_type="4G", -# sys_param_filename=output_sys_param_file, -# ) -# assert f"Unable to find your feature file. The path you provided was: {missing_feature_file}" in str( -# context.value -# ) - -# def test_csv_to_sys_param_does_not_overwrite(self): -# output_sys_param_file = self.output_dir / "test_overwriting_sys_param.json" -# sp = SystemParameters() -# sp.csv_to_sys_param( -# model_type="time_series", -# scenario_dir=self.scenario_dir, -# feature_file=self.feature_file, -# district_type="4G", -# sys_param_filename=output_sys_param_file, -# overwrite=True, -# ) -# with pytest.raises(SystemExit) as context: -# sp.csv_to_sys_param( -# model_type="time_series", -# scenario_dir=self.scenario_dir, -# feature_file=self.feature_file, -# sys_param_filename=output_sys_param_file, -# overwrite=False, -# ) -# assert "Output file already exists and overwrite is False:" in str(context.value) - -# def test_csv_to_sys_param(self): -# output_sys_param_file = self.output_dir / "test_sys_param.json" -# sp = SystemParameters() -# sp.csv_to_sys_param( -# model_type="time_series", -# scenario_dir=self.scenario_dir, -# feature_file=self.feature_file, -# sys_param_filename=output_sys_param_file, -# ) - -# # debug -# # with open(output_sys_param_file, "r") as f: -# # sys_param_data = json.load(f) -# # print(sys_param_data) - -# assert output_sys_param_file.is_file() - -# def test_csv_to_sys_param_ghe(self): -# output_sys_param_file = self.output_dir / "test_sys_param.json" -# sp = SystemParameters() -# sp.csv_to_sys_param( -# model_type="time_series", -# scenario_dir=self.scenario_dir, -# feature_file=self.feature_file, -# district_type="5G_ghe", -# sys_param_filename=output_sys_param_file, -# ) - -# assert output_sys_param_file.is_file() -# with open(output_sys_param_file) as f: -# sys_param_data = json.load(f) - -# # ghe -# assert sys_param_data["district_system"]["fifth_generation"]["ghe_parameters"] is not False - -# def test_csv_to_sys_param_microgrid(self): -# output_sys_param_file = self.microgrid_output_dir / "test_sys_param_microgrid.json" -# sp = SystemParameters() -# sp.csv_to_sys_param( -# model_type="time_series", -# scenario_dir=self.microgrid_scenario_dir, -# feature_file=self.microgrid_feature_file, -# district_type="4G", -# sys_param_filename=output_sys_param_file, -# microgrid=True, -# ) -# assert output_sys_param_file.exists() - -# with open(output_sys_param_file) as f: -# sys_param_data = json.load(f) - -# # pv on a building -# assert len(sys_param_data["buildings"][0]["photovoltaic_panels"]) > 0 -# # pv for the district -# assert len(sys_param_data["photovoltaic_panels"]) > 0 -# assert len(sys_param_data["wind_turbines"]) > 0 -# assert sys_param_data["electrical_grid"]["frequency"] is not False - -# # assert that a building has a 'photovoltaic_panels' section (exists and nonempty) -# assert sys_param_data["buildings"][0]["photovoltaic_panels"] is not False - -# # assert that building_id 7 (number 1 in the list) has an electrical load -# # Building 1 (number 0 in the list) does not have an electrical load as of 2023-03-07 -# assert sys_param_data["buildings"][1]["load_model_parameters"]["time_series"]["max_electrical_load"] > 0 - -# def test_validate_sys_param_template(self): -# output_sys_param_file = self.output_dir / "bogus_sys_param.json" -# sp = SystemParameters() -# with pytest.raises(TypeError) as context: -# sp.csv_to_sys_param( -# scenario_dir=self.scenario_dir, -# feature_file=self.feature_file, -# district_type="4G", -# sys_param_filename=output_sys_param_file, -# ) -# assert "missing 1 required positional argument: 'model_type'" in str(context.value) -# bogus_template_type = "openstudio" -# sp = SystemParameters() -# with pytest.raises(SystemExit) as context: -# sp.csv_to_sys_param( -# model_type=bogus_template_type, -# scenario_dir=self.scenario_dir, -# feature_file=self.feature_file, -# district_type="4G", -# sys_param_filename=output_sys_param_file, -# ) -# assert f"No template found. {bogus_template_type} is not a valid template" in str(context.value) - -# def test_download_usa_mos(self): -# sdp = SystemParameters() -# print(f"saving results to f{self.weather_dir}") - -# weather_filename = "USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.mos" -# sdp.download_weatherfile(weather_filename, self.weather_dir) -# assert (Path(self.weather_dir) / weather_filename).exists() - -# def test_download_usa_epw(self): -# sdp = SystemParameters() -# print(f"saving results to f{self.weather_dir}") -# weather_filename = "USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.epw" -# sdp.download_weatherfile(weather_filename, self.weather_dir) -# assert (Path(self.weather_dir) / weather_filename).exists() - -# def test_download_german_epw(self): -# sdp = SystemParameters() -# print(f"saving results to f{self.weather_dir}") -# weather_filename = "DEU_Stuttgart.107380_IWEC.epw" -# sdp.download_weatherfile(weather_filename, self.weather_dir) -# assert (Path(self.weather_dir) / weather_filename).exists() - -# def test_download_german_mos(self): -# sdp = SystemParameters() -# print(f"saving results to f{self.weather_dir}") -# weather_filename = "DEU_Stuttgart.107380_IWEC.mos" -# sdp.download_weatherfile(weather_filename, self.weather_dir) -# assert (Path(self.weather_dir) / weather_filename).exists() - -# def test_download_invalid_savepath(self): -# sdp = SystemParameters() -# weather_filename = "irrelevant weather file" -# local_path = os.path.join("not", "a", "real", "path") -# with pytest.raises(IndexError) as context: -# sdp.download_weatherfile(weather_filename, local_path) -# assert ( -# str(context.value) == "Malformed location, needs underscores of location " -# "(e.g., USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.mos)" -# ) - -# def test_download_invalid_epw(self): -# sdp = SystemParameters() -# weather_filename = "invalid-location.epw" -# with pytest.raises(IndexError) as context: -# sdp.download_weatherfile(weather_filename, self.weather_dir) -# assert ( -# str(context.value) == "Malformed location, needs underscores of location " -# "(e.g., USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.mos)" -# ) +# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors. +# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md + +import json +import os +import unittest +from pathlib import Path +from shutil import rmtree + +import pytest + +from geojson_modelica_translator.system_parameters.system_parameters import SystemParameters + + +class SystemParametersTest(unittest.TestCase): + def setUp(self): + self.data_dir = Path(__file__).parent / "data" + self.output_dir = Path(__file__).parent / "output" + self.weather_dir = self.output_dir / "weatherfiles" + self.scenario_dir = self.data_dir / "sdk_output_skeleton" / "run" / "baseline_15min" + self.microgrid_scenario_dir = self.data_dir / "sdk_microgrid_output_skeleton" / "run" / "reopt_scenario" + self.microgrid_feature_file = self.data_dir / "sdk_microgrid_output_skeleton" / "example_project.json" + self.microgrid_output_dir = Path(__file__).parent / "microgrid_output" + self.feature_file = self.data_dir / "sdk_output_skeleton" / "example_project.json" + self.sys_param_template = ( + Path(__file__).parent.parent.parent + / "geojson_modelica_translator" + / "system_parameters" + / "time_series_template.json" + ) + if self.output_dir.exists(): + rmtree(self.output_dir) + self.output_dir.mkdir(parents=True) + if self.weather_dir.exists(): + rmtree(self.weather_dir) + self.weather_dir.mkdir(parents=True) + if self.microgrid_output_dir.exists(): + rmtree(self.microgrid_output_dir) + self.microgrid_output_dir.mkdir(parents=True) + + def test_expanded_paths(self): + filename = self.data_dir / "system_params_1.json" + sdp = SystemParameters(filename) + for s in sdp.validate(): + print(s) + value = sdp.get_param_by_id("ijk678", "load_model_parameters.spawn.idf_filename") + assert Path(value) == Path(filename).parent / "example_model.idf" + value = sdp.get_param("$.weather") + assert Path(value) == Path(filename).parent / "../../data_shared/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos" + + # verify that the second spawn paths resolve too. + value = sdp.get_param_by_id("lmn000", "load_model_parameters.spawn.idf_filename") + assert Path(value) == Path(filename).parent / "example_model_2.idf" + + def test_load_system_parameters_1(self): + filename = self.data_dir / "system_params_1.json" + sdp = SystemParameters(filename) + assert sdp.param_template["buildings"][1]["load_model_parameters"]["rc"]["order"] == 2 + + def test_load_system_parameters_2(self): + filename = self.data_dir / "system_params_2.json" + sdp = SystemParameters(filename) + assert sdp is not None + + def test_valid_system_parameters_ghe(self): + filename = self.data_dir / "system_params_ghe.json" + sdp = SystemParameters(filename) + assert sdp is not None + assert len(sdp.validate()) == 0 + assert sdp.validate() == [] + + def test_error_system_parameters_ghe(self): + filename = self.data_dir / "system_params_ghe_invalid.json" + with pytest.raises(ValueError, match="Invalid"): + SystemParameters(filename) + + def test_missing_file(self): + fn = "non-existent-path" + with pytest.raises(FileNotFoundError, match=f"System design parameters file does not exist: {fn}"): + SystemParameters(fn) + + def test_errors(self): + incomplete_teaser_params = { + "buildings": [ + { + "geojson_id": "asdf", + "ets_model": "None", + "load_model": "rc", + "load_model_parameters": {"rc": {"order": 5}}, + } + ] + } + + with pytest.raises(ValueError, match="Invalid system parameter"): + SystemParameters.loadd(incomplete_teaser_params) + + sp = SystemParameters.loadd(incomplete_teaser_params, validate_on_load=False) + assert "'None' is not one of ['Indirect Heating and Cooling', 'Fifth Gen Heat Pump']" in sp.validate() + assert "'fraction_latent_person' is a required property" in sp.validate() + assert "'temp_hw_supply' is a required property" in sp.validate() + assert "'temp_setpoint_cooling' is a required property" in sp.validate() + assert "'temp_setpoint_heating' is a required property" in sp.validate() + assert "5 is not one of [1, 2, 3, 4]" in sp.validate() + assert len(sp.validate()) == 8 + + def test_get_param(self): + data = { + "weather": "path/to/weatherfile.mos", + "buildings": [ + { + "geojson_id": "asdf", + "ets_model": "Indirect Heating and Cooling", + "ets_indirect_parameters": { + "heat_flow_nominal": 8000, + "heat_exchanger_efficiency": 0.8, + "nominal_mass_flow_district": 0.5, + "nominal_mass_flow_building": 0.5, + "valve_pressure_drop": 6000, + "heat_exchanger_secondary_pressure_drop": 500, + "heat_exchanger_primary_pressure_drop": 500, + "cooling_supply_water_temperature_building": 7, + "heating_supply_water_temperature_building": 50, + "delta_temp_chw_building": 5, + "delta_temp_chw_district": 8, + "delta_temp_hw_building": 15, + "delta_temp_hw_district": 20, + "cooling_controller_y_max": 1, + "cooling_controller_y_min": 0, + "heating_controller_y_max": 1, + "heating_controller_y_min": 0, + }, + "load_model": "rc", + "load_model_parameters": { + "rc": { + "order": 4, + "fraction_latent_person": 1.25, + "temp_hw_supply": 40, + "temp_setpoint_heating": 40, + "temp_setpoint_cooling": 24, + } + }, + } + ], + } + sp = SystemParameters.loadd(data) + value = sp.get_param("$.buildings.[*].load_model_parameters.rc.order") + assert value == 4 + + value = sp.get_param("buildings.[*].load_model") + assert value == "rc" + + value = sp.get_param("buildings") + assert value == [ + { + "geojson_id": "asdf", + "ets_model": "Indirect Heating and Cooling", + "ets_indirect_parameters": { + "heat_flow_nominal": 8000, + "heat_exchanger_efficiency": 0.8, + "nominal_mass_flow_district": 0.5, + "nominal_mass_flow_building": 0.5, + "valve_pressure_drop": 6000, + "heat_exchanger_secondary_pressure_drop": 500, + "heat_exchanger_primary_pressure_drop": 500, + "cooling_supply_water_temperature_building": 7, + "heating_supply_water_temperature_building": 50, + "delta_temp_chw_building": 5, + "delta_temp_chw_district": 8, + "delta_temp_hw_building": 15, + "delta_temp_hw_district": 20, + "cooling_controller_y_max": 1, + "cooling_controller_y_min": 0, + "heating_controller_y_max": 1, + "heating_controller_y_min": 0, + }, + "load_model": "rc", + "load_model_parameters": { + "rc": { + "order": 4, + "fraction_latent_person": 1.25, + "temp_hw_supply": 40, + "temp_setpoint_heating": 40, + "temp_setpoint_cooling": 24, + } + }, + } + ] + + value = sp.get_param("") + assert value is None + + value = sp.get_param("not.a.real.path") + assert value is None + + def test_get_param_with_two(self): + data = { + "weather": "path/to/weatherfile.mos", + "buildings": [ + { + "geojson_id": "asdf", + "ets_model": "Indirect Heating and Cooling", + "ets_indirect_parameters": { + "heat_flow_nominal": 8000, + }, + "load_model": "rc", + "load_model_parameters": { + "rc": { + "order": 4, + "fraction_latent_person": 1.25, + "temp_hw_supply": 40, + "temp_setpoint_heating": 40, + "temp_setpoint_cooling": 24, + } + }, + }, + { + "geojson_id": "qwer", + "ets_model": "Fifth Gen Heat Pump", + "ets_indirect_parameters": { + "heat_flow_nominal": 10000, + }, + "load_model": "rc", + "load_model_parameters": { + "rc": { + "order": 4, + "fraction_latent_person": 1.25, + "temp_hw_supply": 40, + "temp_setpoint_heating": 40, + "temp_setpoint_cooling": 24, + } + }, + }, + ], + } + sp = SystemParameters.loadd(data) + value = sp.get_param("$.buildings.[*].ets_indirect_parameters.heat_flow_nominal") + assert value == [8000, 10000] + + def test_get_param_with_building_id(self): + filename = self.data_dir / "system_params_1.json" + sdp = SystemParameters(filename) + self.maxDiff = None + value = sdp.get_param_by_id("abcd1234", "ets_model") + assert value == "Indirect Heating and Cooling" + + # grab the schema default + value = sdp.get_param_by_id("defgh2345", "ets_model") + assert value == "Indirect Heating and Cooling" + value = sdp.get_param_by_id("defgh2345", "ets_indirect_parameters") + assert value == { + "heat_flow_nominal": 8000, + "heat_exchanger_efficiency": 0.8, + "nominal_mass_flow_district": 0.5, + "nominal_mass_flow_building": 0.5, + "valve_pressure_drop": 6000, + "heat_exchanger_secondary_pressure_drop": 500, + "heat_exchanger_primary_pressure_drop": 500, + "cooling_supply_water_temperature_building": 7, + "heating_supply_water_temperature_building": 50, + "delta_temp_chw_building": 5, + "delta_temp_chw_district": 8, + "delta_temp_hw_building": 15, + "delta_temp_hw_district": 20, + "cooling_controller_y_max": 1, + "cooling_controller_y_min": 0, + "heating_controller_y_max": 1, + "heating_controller_y_min": 0, + } + + def test_get_param_with_ghe_id(self): + # Setup + filename = self.data_dir / "system_params_ghe.json" + sdp = SystemParameters(filename) + self.maxDiff = None + + # Act + value = sdp.get_param_by_id("c432cb11-4813-40df-8dd4-e88f5de40033", "borehole") + + # Assert + assert value == {"buried_depth": 2.0, "diameter": 0.15} + + # Act + second_ghe_borehole = sdp.get_param_by_id("c432cb11-4813-40df-8dd4-e88f5de40034", "borehole") + # Assert + assert second_ghe_borehole["buried_depth"] == 10.0 + + def test_get_param_with_none_building_id(self): + # Setup + filename = self.data_dir / "system_params_1.json" + sdp = SystemParameters(filename) + self.maxDiff = None + + # Act + with pytest.raises(SystemExit) as context: + sdp.get_param_by_id(None, "ets_model") + + # Assert + assert "No id submitted. Please retry and include the appropriate id" in str(context.value) + + def test_missing_files(self): + output_sys_param_file = self.output_dir / "going_to_fail_first.json" + missing_scenario_dir = self.scenario_dir / "foobar" + sp = SystemParameters() + with pytest.raises(SystemExit) as context: + sp.csv_to_sys_param( + model_type="time_series", + scenario_dir=missing_scenario_dir, + feature_file=self.feature_file, + district_type="4G", + sys_param_filename=output_sys_param_file, + ) + assert f"Unable to find your scenario. The path you provided was: {missing_scenario_dir}" in str(context.value) + missing_feature_file = self.data_dir / "sdk_output_skeleton" / "foobar.json" + sp = SystemParameters() + with pytest.raises(SystemExit) as context: + sp.csv_to_sys_param( + model_type="time_series", + scenario_dir=self.scenario_dir, + feature_file=missing_feature_file, + district_type="4G", + sys_param_filename=output_sys_param_file, + ) + assert f"Unable to find your feature file. The path you provided was: {missing_feature_file}" in str( + context.value + ) + + def test_csv_to_sys_param_does_not_overwrite(self): + output_sys_param_file = self.output_dir / "test_overwriting_sys_param.json" + sp = SystemParameters() + sp.csv_to_sys_param( + model_type="time_series", + scenario_dir=self.scenario_dir, + feature_file=self.feature_file, + district_type="4G", + sys_param_filename=output_sys_param_file, + overwrite=True, + ) + with pytest.raises(SystemExit) as context: + sp.csv_to_sys_param( + model_type="time_series", + scenario_dir=self.scenario_dir, + feature_file=self.feature_file, + sys_param_filename=output_sys_param_file, + overwrite=False, + ) + assert "Output file already exists and overwrite is False:" in str(context.value) + + def test_csv_to_sys_param(self): + output_sys_param_file = self.output_dir / "test_sys_param.json" + sp = SystemParameters() + sp.csv_to_sys_param( + model_type="time_series", + scenario_dir=self.scenario_dir, + feature_file=self.feature_file, + sys_param_filename=output_sys_param_file, + ) + + # debug + # with open(output_sys_param_file, "r") as f: + # sys_param_data = json.load(f) + # print(sys_param_data) + + assert output_sys_param_file.is_file() + + def test_csv_to_sys_param_ghe(self): + output_sys_param_file = self.output_dir / "test_sys_param.json" + sp = SystemParameters() + sp.csv_to_sys_param( + model_type="time_series", + scenario_dir=self.scenario_dir, + feature_file=self.feature_file, + district_type="5G_ghe", + sys_param_filename=output_sys_param_file, + ) + + assert output_sys_param_file.is_file() + with open(output_sys_param_file) as f: + sys_param_data = json.load(f) + + # ghe + assert sys_param_data["district_system"]["fifth_generation"]["ghe_parameters"] is not False + + def test_csv_to_sys_param_microgrid(self): + output_sys_param_file = self.microgrid_output_dir / "test_sys_param_microgrid.json" + sp = SystemParameters() + sp.csv_to_sys_param( + model_type="time_series", + scenario_dir=self.microgrid_scenario_dir, + feature_file=self.microgrid_feature_file, + district_type="4G", + sys_param_filename=output_sys_param_file, + microgrid=True, + ) + assert output_sys_param_file.exists() + + with open(output_sys_param_file) as f: + sys_param_data = json.load(f) + + # pv on a building + assert len(sys_param_data["buildings"][0]["photovoltaic_panels"]) > 0 + # pv for the district + assert len(sys_param_data["photovoltaic_panels"]) > 0 + assert len(sys_param_data["wind_turbines"]) > 0 + assert sys_param_data["electrical_grid"]["frequency"] is not False + + # assert that a building has a 'photovoltaic_panels' section (exists and nonempty) + assert sys_param_data["buildings"][0]["photovoltaic_panels"] is not False + + # assert that building_id 7 (number 1 in the list) has an electrical load + # Building 1 (number 0 in the list) does not have an electrical load as of 2023-03-07 + assert sys_param_data["buildings"][1]["load_model_parameters"]["time_series"]["max_electrical_load"] > 0 + + def test_validate_sys_param_template(self): + output_sys_param_file = self.output_dir / "bogus_sys_param.json" + sp = SystemParameters() + with pytest.raises(TypeError) as context: + sp.csv_to_sys_param( + scenario_dir=self.scenario_dir, + feature_file=self.feature_file, + district_type="4G", + sys_param_filename=output_sys_param_file, + ) + assert "missing 1 required positional argument: 'model_type'" in str(context.value) + bogus_template_type = "openstudio" + sp = SystemParameters() + with pytest.raises(SystemExit) as context: + sp.csv_to_sys_param( + model_type=bogus_template_type, + scenario_dir=self.scenario_dir, + feature_file=self.feature_file, + district_type="4G", + sys_param_filename=output_sys_param_file, + ) + assert f"No template found. {bogus_template_type} is not a valid template" in str(context.value) + + def test_download_usa_mos(self): + sdp = SystemParameters() + print(f"saving results to f{self.weather_dir}") + + weather_filename = "USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.mos" + sdp.download_weatherfile(weather_filename, self.weather_dir) + assert (Path(self.weather_dir) / weather_filename).exists() + + def test_download_usa_epw(self): + sdp = SystemParameters() + print(f"saving results to f{self.weather_dir}") + weather_filename = "USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.epw" + sdp.download_weatherfile(weather_filename, self.weather_dir) + assert (Path(self.weather_dir) / weather_filename).exists() + + def test_download_german_epw(self): + sdp = SystemParameters() + print(f"saving results to f{self.weather_dir}") + weather_filename = "DEU_Stuttgart.107380_IWEC.epw" + sdp.download_weatherfile(weather_filename, self.weather_dir) + assert (Path(self.weather_dir) / weather_filename).exists() + + def test_download_german_mos(self): + sdp = SystemParameters() + print(f"saving results to f{self.weather_dir}") + weather_filename = "DEU_Stuttgart.107380_IWEC.mos" + sdp.download_weatherfile(weather_filename, self.weather_dir) + assert (Path(self.weather_dir) / weather_filename).exists() + + def test_download_invalid_savepath(self): + sdp = SystemParameters() + weather_filename = "irrelevant weather file" + local_path = os.path.join("not", "a", "real", "path") + with pytest.raises(IndexError) as context: + sdp.download_weatherfile(weather_filename, local_path) + assert ( + str(context.value) == "Malformed location, needs underscores of location " + "(e.g., USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.mos)" + ) + + def test_download_invalid_epw(self): + sdp = SystemParameters() + weather_filename = "invalid-location.epw" + with pytest.raises(IndexError) as context: + sdp.download_weatherfile(weather_filename, self.weather_dir) + assert ( + str(context.value) == "Malformed location, needs underscores of location " + "(e.g., USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.mos)" + )