Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RWTH-EBC
GitHub Repository: RWTH-EBC/ebcpy
Path: blob/master/examples/e3_dymola_example.py
505 views
1
"""
2
Goals of this part of the examples:
3
1. Learn how to use the `DymolaAPI`
4
2. Learn the different result options of the simulation
5
3. Learn how to convert inputs into the Dymola format
6
"""
7
# Start by importing all relevant packages
8
import pathlib
9
import time
10
import numpy as np
11
import matplotlib.pyplot as plt
12
import pandas as pd
13
14
# Imports from ebcpy
15
from ebcpy import DymolaAPI, load_time_series_data, FMU_API
16
from ebcpy.utils.conversion import convert_tsd_to_modelica_txt
17
18
19
def main(
20
aixlib_mo,
21
working_directory=None,
22
n_cpu=1,
23
with_plot=True
24
):
25
"""
26
Arguments of this example:
27
:param str aixlib_mo:
28
Path to the package.mo of the AixLib.
29
This example was tested for AixLib version 3.0.0.
30
:param str working_directory:
31
Path in which to store the output.
32
Default is the examples\results folder
33
:param int n_cpu:
34
Number of processes to use
35
:param bool with_plot:
36
Show the plot at the end of the script. Default is True.
37
"""
38
39
# General settings
40
if working_directory is None:
41
working_directory = pathlib.Path(__file__).parent.joinpath("results")
42
43
# ######################### Simulation API Instantiation ##########################
44
# %% Setup the Dymola-API:
45
model_name = "AixLib.Fluid.HeatPumps.ModularReversible.Examples.AirToWater2D_OneRoomRadiator"
46
dym_api = DymolaAPI(
47
model_name=model_name,
48
working_directory=working_directory,
49
n_cpu=n_cpu,
50
packages=[aixlib_mo],
51
show_window=True,
52
n_restart=-1,
53
equidistant_output=False,
54
# Only necessary if you need a specific dymola version
55
#dymola_path=None,
56
#dymola_version=None
57
)
58
print("Number of variables:", len(dym_api.variables))
59
print("Number of outputs:", len(dym_api.outputs))
60
print("Number of inputs:", len(dym_api.inputs))
61
print("Number of parameters:", len(dym_api.parameters))
62
print("Number of states:", len(dym_api.states))
63
64
# ######################### Settings ##########################
65
# To understand what is happening here we refer to fmu_example.py
66
# As both simulation_apis are based on the same class, most interfaces are equal.
67
# Only difference is the simulation setup:
68
print("Fields of DymolaAPISetup", DymolaAPI.get_simulation_setup_fields())
69
print("Fields of FMU_APISetup", FMU_API.get_simulation_setup_fields())
70
71
simulation_setup = {"start_time": 0,
72
"stop_time": 3600,
73
"output_interval": 100}
74
dym_api.set_sim_setup(sim_setup=simulation_setup)
75
p_el_name = "heaPum.sigBus.PEleMea"
76
dym_api.result_names = [p_el_name]
77
78
# ######################### Inputs ##########################
79
# Sadly, setting inputs directly is not supported in Dymola.
80
# Hence, you have to use the model `Modelica.Blocks.Sources.CombiTimeTable`.
81
# In the model "AixLib.Systems.HeatPumpSystems.Examples.HeatPumpSystem" we
82
# already use this model to simulate heat gains into the room
83
# We called the instance of the model `timTab`.
84
# To get the output of the table, let's add it to the result names:
85
dym_api.result_names = [p_el_name, 'timTab.y[1]']
86
# In order to change the inputs, you have to change the model in Dymola.
87
# You can either do this manually in Dymola or by using a modifier, see e5.
88
# If you did not change the model yourself, set use_modifier=True below for the API
89
# to automatically change the model instance for you.
90
#
91
# To change the model:
92
# 1. Double-click on timTab
93
# 2. Set tableOnFile = true
94
# 3. Set tableName = "myCustomInput" (or any other nice string)
95
# 4. Enter the fileName where you want to store your input. This can be any filepath.
96
# For this tutorial to work, set
97
# fileName=Modelica.Utilities.Files.loadResource("modelica://AixLib/Resources/my_custom_input.txt")
98
table_name = "myCustomInput"
99
file_name = pathlib.Path(aixlib_mo).parent.joinpath("Resources", "my_custom_input.txt")
100
# This input generate is re-used from the fmu_example.py file.
101
time_index = np.arange(
102
dym_api.sim_setup.start_time,
103
dym_api.sim_setup.stop_time,
104
dym_api.sim_setup.output_interval
105
)
106
# Apply some sinus function for the outdoor air temperature
107
internal_gains = np.sin(time_index/3600*np.pi) * 1000
108
tsd_input = pd.DataFrame({"InternalGains": internal_gains}, index=time_index)
109
# To generate the input in the correct format, use the convert_tsd_to_modelica_txt function:
110
filepath = convert_tsd_to_modelica_txt(
111
tsd=tsd_input,
112
table_name=table_name,
113
save_path_file=file_name
114
)
115
print("Successfully created Dymola input file at", filepath)
116
117
use_modifier = True
118
if use_modifier:
119
dym_api.model_name = (
120
f'{model_name}(\n' # This work like an "extend". You may use \n for pretty display
121
f'timTab(tableOnFile=true,\n' # Apply the steps listed above
122
f'tableName="{table_name}",\n' # Important to use ' for string as " is needed in the modifier
123
f'fileName="{file_name.as_posix()}"))' # as_posix helps to keep the path without backlashes
124
)
125
print(dym_api.model_name)
126
# Setting the model name again overrides the previously set result_names,
127
# which are not standard outputs in our example.
128
# Thus, we have to set them again for return option "time_series"
129
dym_api.result_names = [p_el_name, 'timTab.y[1]']
130
131
# ######################### Simulation options ##########################
132
# Look at the doc of simulate() in the website
133
# Besides parameters (explained in fmu_example), return_option is important
134
result_time_series = dym_api.simulate(
135
return_option="time_series",
136
# Info: You would not need these following keyword-arguments,
137
# as we've already created our file above.
138
# However, you can also pass the arguments
139
# from above directly into the function call and the API
140
# generates the files for you. Still, you need to change the
141
# model yourself or using a modifier.
142
inputs=tsd_input,
143
table_name=table_name,
144
file_name=file_name
145
)
146
print(type(result_time_series))
147
print(result_time_series)
148
result_last_point = dym_api.simulate(
149
return_option="last_point"
150
)
151
print(type(result_last_point))
152
print(result_last_point)
153
result_sp = dym_api.simulate(
154
return_option="savepath"
155
)
156
print(result_sp)
157
# Or change the savepath by using two keyword arguments.
158
result_sp_2 = dym_api.simulate(
159
return_option="savepath",
160
savepath=r"D:\00_temp",
161
result_file_name="anotherResultFile"
162
)
163
print(result_sp_2)
164
165
# Save the data for later reproduction
166
file = dym_api.save_for_reproduction(
167
title="MyDymolaStudy",
168
files=[result_sp, result_sp_2],
169
log_message="This is just an example."
170
)
171
print("ZIP-File to reproduce all this:", file)
172
173
# ######################### Closing ##########################
174
# Close Dymola. If you forget to do so,
175
# we call this function at the exit of your script.
176
dym_api.close()
177
178
# ######################### Simulation analysis ##########################
179
# Now let's load the time series data
180
tsd_1 = load_time_series_data(result_sp)
181
tsd_2 = load_time_series_data(result_sp_2)
182
print("Both .mat's are equal:", all(tsd_1 == tsd_2))
183
# Let's look at both results. The .mat-file contains more indexes as events are stored as well.
184
# The return_option 'time_series' omits these events (as does fmpy). Thus, it's less accurate.
185
# But, it's much faster!
186
print("Number of points for return option 'time_series':", len(result_time_series.index))
187
print("Number of points for return option 'savepath':", len(tsd_1.index))
188
plt.plot(tsd_1[p_el_name], color="blue", label="savepath", marker="^")
189
plt.plot(result_time_series[p_el_name], color="red", label="time_series", marker="^")
190
plt.scatter(result_last_point["Time"], result_last_point[p_el_name],
191
color="black", label="last_point", marker="s", s=100)
192
plt.legend()
193
plt.title("Difference in output for different return_options")
194
plt.figure()
195
plt.plot(tsd_1['timTab.y[1]'], color="blue")
196
plt.title("Input of CombiTimeTable 'timTab'")
197
if with_plot:
198
plt.show()
199
200
201
if __name__ == '__main__':
202
# TODO-User: Change the AixLib path!
203
main(
204
aixlib_mo=r"D:\04_git\AixLib\AixLib\package.mo",
205
n_cpu=1
206
)
207
208