rtc-tools 2.5.2rc3__py3-none-any.whl → 2.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rtc-tools might be problematic. Click here for more details.

Files changed (47) hide show
  1. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/METADATA +7 -7
  2. rtc_tools-2.6.0.dist-info/RECORD +50 -0
  3. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/WHEEL +1 -1
  4. rtctools/__init__.py +2 -1
  5. rtctools/_internal/alias_tools.py +12 -10
  6. rtctools/_internal/caching.py +5 -3
  7. rtctools/_internal/casadi_helpers.py +11 -32
  8. rtctools/_internal/debug_check_helpers.py +1 -1
  9. rtctools/_version.py +3 -3
  10. rtctools/data/__init__.py +2 -2
  11. rtctools/data/csv.py +54 -33
  12. rtctools/data/interpolation/bspline.py +3 -3
  13. rtctools/data/interpolation/bspline1d.py +42 -29
  14. rtctools/data/interpolation/bspline2d.py +10 -4
  15. rtctools/data/netcdf.py +137 -93
  16. rtctools/data/pi.py +304 -210
  17. rtctools/data/rtc.py +64 -53
  18. rtctools/data/storage.py +91 -51
  19. rtctools/optimization/collocated_integrated_optimization_problem.py +1244 -696
  20. rtctools/optimization/control_tree_mixin.py +68 -66
  21. rtctools/optimization/csv_lookup_table_mixin.py +107 -74
  22. rtctools/optimization/csv_mixin.py +83 -52
  23. rtctools/optimization/goal_programming_mixin.py +239 -148
  24. rtctools/optimization/goal_programming_mixin_base.py +204 -111
  25. rtctools/optimization/homotopy_mixin.py +36 -27
  26. rtctools/optimization/initial_state_estimation_mixin.py +8 -8
  27. rtctools/optimization/io_mixin.py +48 -43
  28. rtctools/optimization/linearization_mixin.py +3 -1
  29. rtctools/optimization/linearized_order_goal_programming_mixin.py +57 -28
  30. rtctools/optimization/min_abs_goal_programming_mixin.py +72 -29
  31. rtctools/optimization/modelica_mixin.py +135 -81
  32. rtctools/optimization/netcdf_mixin.py +32 -18
  33. rtctools/optimization/optimization_problem.py +181 -127
  34. rtctools/optimization/pi_mixin.py +68 -36
  35. rtctools/optimization/planning_mixin.py +19 -0
  36. rtctools/optimization/single_pass_goal_programming_mixin.py +159 -112
  37. rtctools/optimization/timeseries.py +4 -6
  38. rtctools/rtctoolsapp.py +18 -18
  39. rtctools/simulation/csv_mixin.py +37 -30
  40. rtctools/simulation/io_mixin.py +9 -5
  41. rtctools/simulation/pi_mixin.py +62 -32
  42. rtctools/simulation/simulation_problem.py +471 -180
  43. rtctools/util.py +84 -56
  44. rtc_tools-2.5.2rc3.dist-info/RECORD +0 -49
  45. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/COPYING.LESSER +0 -0
  46. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/entry_points.txt +0 -0
  47. {rtc_tools-2.5.2rc3.dist-info → rtc_tools-2.6.0.dist-info}/top_level.txt +0 -0
@@ -20,7 +20,8 @@ class CSVMixin(IOMixin):
20
20
  During preprocessing, files named ``timeseries_import.csv``, ``initial_state.csv``,
21
21
  and ``parameters.csv`` are read from the ``input`` subfolder.
22
22
 
23
- During postprocessing, a file named ``timeseries_export.csv`` is written to the ``output`` subfolder.
23
+ During postprocessing, a file named ``timeseries_export.csv`` is written to the ``output``
24
+ subfolder.
24
25
 
25
26
  In ensemble mode, a file named ``ensemble.csv`` is read from the ``input`` folder. This file
26
27
  contains two columns. The first column gives the name of the ensemble member, and the second
@@ -44,16 +45,16 @@ class CSVMixin(IOMixin):
44
45
  """
45
46
 
46
47
  #: Initial state file basename
47
- csv_initial_state_basename = 'initial_state'
48
+ csv_initial_state_basename = "initial_state"
48
49
 
49
50
  #: Parameters file basename
50
- csv_parameters_basename = 'parameters'
51
+ csv_parameters_basename = "parameters"
51
52
 
52
53
  #: Ensemble file basename
53
- csv_ensemble_basename = 'ensemble'
54
+ csv_ensemble_basename = "ensemble"
54
55
 
55
56
  #: Column delimiter used in CSV files
56
- csv_delimiter = ','
57
+ csv_delimiter = ","
57
58
 
58
59
  #: Whether or not the timeseries data is equidistant
59
60
  csv_equidistant = True
@@ -80,20 +81,27 @@ class CSVMixin(IOMixin):
80
81
  """
81
82
  if initial_state.shape:
82
83
  raise Exception(
83
- 'CSVMixin: Initial state file {} contains more than one row of data. '
84
- 'Please remove the data row(s) that do not describe the initial state.'.format(
85
- os.path.join(self._input_folder, self.csv_initial_state_basename + '.csv')))
84
+ "CSVMixin: Initial state file {} contains more than one row of data. "
85
+ "Please remove the data row(s) that do not describe the initial state.".format(
86
+ os.path.join(self._input_folder, self.csv_initial_state_basename + ".csv")
87
+ )
88
+ )
86
89
 
87
90
  # Read CSV files
88
91
  self.__initial_state = []
89
92
  if self.csv_ensemble_mode:
90
93
  self.__ensemble = np.genfromtxt(
91
- os.path.join(self._input_folder, self.csv_ensemble_basename + '.csv'),
92
- delimiter=",", deletechars='', dtype=None, names=True, encoding=None)
94
+ os.path.join(self._input_folder, self.csv_ensemble_basename + ".csv"),
95
+ delimiter=",",
96
+ deletechars="",
97
+ dtype=None,
98
+ names=True,
99
+ encoding=None,
100
+ )
93
101
 
94
102
  logger.debug("CSVMixin: Read ensemble description")
95
103
 
96
- for ensemble_member_index, ensemble_member_name in enumerate(self.__ensemble['name']):
104
+ for ensemble_member_index, ensemble_member_name in enumerate(self.__ensemble["name"]):
97
105
  _timeseries = csv.load(
98
106
  os.path.join(
99
107
  self._input_folder,
@@ -112,37 +120,47 @@ class CSVMixin(IOMixin):
112
120
  key,
113
121
  self.__timeseries_times,
114
122
  np.asarray(_timeseries[key], dtype=np.float64),
115
- ensemble_member_index
123
+ ensemble_member_index,
116
124
  )
117
125
  logger.debug("CSVMixin: Read timeseries")
118
126
 
119
- for ensemble_member_index, ensemble_member_name in enumerate(self.__ensemble['name']):
127
+ for ensemble_member_index, ensemble_member_name in enumerate(self.__ensemble["name"]):
120
128
  try:
121
- _parameters = csv.load(os.path.join(
122
- self._input_folder, ensemble_member_name, self.csv_parameters_basename + '.csv'),
123
- delimiter=self.csv_delimiter)
129
+ _parameters = csv.load(
130
+ os.path.join(
131
+ self._input_folder,
132
+ ensemble_member_name,
133
+ self.csv_parameters_basename + ".csv",
134
+ ),
135
+ delimiter=self.csv_delimiter,
136
+ )
124
137
  for key in _parameters.dtype.names:
125
138
  self.io.set_parameter(key, float(_parameters[key]), ensemble_member_index)
126
139
  except IOError:
127
140
  pass
128
141
  logger.debug("CSVMixin: Read parameters.")
129
142
 
130
- for ensemble_member_name in self.__ensemble['name']:
143
+ for ensemble_member_name in self.__ensemble["name"]:
131
144
  try:
132
- _initial_state = csv.load(os.path.join(
133
- self._input_folder, ensemble_member_name, self.csv_initial_state_basename + '.csv'),
134
- delimiter=self.csv_delimiter)
145
+ _initial_state = csv.load(
146
+ os.path.join(
147
+ self._input_folder,
148
+ ensemble_member_name,
149
+ self.csv_initial_state_basename + ".csv",
150
+ ),
151
+ delimiter=self.csv_delimiter,
152
+ )
135
153
  check_initial_state_array(_initial_state)
136
- _initial_state = {key: float(_initial_state[key]) for key in _initial_state.dtype.names}
154
+ _initial_state = {
155
+ key: float(_initial_state[key]) for key in _initial_state.dtype.names
156
+ }
137
157
  except IOError:
138
158
  _initial_state = {}
139
159
  self.__initial_state.append(AliasDict(self.alias_relation, _initial_state))
140
160
  logger.debug("CSVMixin: Read initial state.")
141
161
  else:
142
162
  _timeseries = csv.load(
143
- os.path.join(
144
- self._input_folder, self.timeseries_import_basename + ".csv"
145
- ),
163
+ os.path.join(self._input_folder, self.timeseries_import_basename + ".csv"),
146
164
  delimiter=self.csv_delimiter,
147
165
  with_time=True,
148
166
  )
@@ -151,12 +169,16 @@ class CSVMixin(IOMixin):
151
169
  self.io.reference_datetime = self.__timeseries_times[0]
152
170
 
153
171
  for key in _timeseries.dtype.names[1:]:
154
- self.io.set_timeseries(key, self.__timeseries_times, np.asarray(_timeseries[key], dtype=np.float64))
172
+ self.io.set_timeseries(
173
+ key, self.__timeseries_times, np.asarray(_timeseries[key], dtype=np.float64)
174
+ )
155
175
  logger.debug("CSVMixin: Read timeseries.")
156
176
 
157
177
  try:
158
- _parameters = csv.load(os.path.join(
159
- self._input_folder, self.csv_parameters_basename + '.csv'), delimiter=self.csv_delimiter)
178
+ _parameters = csv.load(
179
+ os.path.join(self._input_folder, self.csv_parameters_basename + ".csv"),
180
+ delimiter=self.csv_delimiter,
181
+ )
160
182
  logger.debug("CSVMixin: Read parameters.")
161
183
  for key in _parameters.dtype.names:
162
184
  self.io.set_parameter(key, float(_parameters[key]))
@@ -164,11 +186,15 @@ class CSVMixin(IOMixin):
164
186
  pass
165
187
 
166
188
  try:
167
- _initial_state = csv.load(os.path.join(
168
- self._input_folder, self.csv_initial_state_basename + '.csv'), delimiter=self.csv_delimiter)
189
+ _initial_state = csv.load(
190
+ os.path.join(self._input_folder, self.csv_initial_state_basename + ".csv"),
191
+ delimiter=self.csv_delimiter,
192
+ )
169
193
  logger.debug("CSVMixin: Read initial state.")
170
194
  check_initial_state_array(_initial_state)
171
- _initial_state = {key: float(_initial_state[key]) for key in _initial_state.dtype.names}
195
+ _initial_state = {
196
+ key: float(_initial_state[key]) for key in _initial_state.dtype.names
197
+ }
172
198
  except IOError:
173
199
  _initial_state = {}
174
200
  self.__initial_state.append(AliasDict(self.alias_relation, _initial_state))
@@ -178,8 +204,7 @@ class CSVMixin(IOMixin):
178
204
  times = self.__timeseries_times
179
205
  for i in range(len(times) - 1):
180
206
  if times[i] >= times[i + 1]:
181
- raise Exception(
182
- 'CSVMixin: Time stamps must be strictly increasing.')
207
+ raise Exception("CSVMixin: Time stamps must be strictly increasing.")
183
208
 
184
209
  if self.csv_equidistant:
185
210
  # Check if the timeseries are truly equidistant
@@ -189,13 +214,14 @@ class CSVMixin(IOMixin):
189
214
  for i in range(len(times) - 1):
190
215
  if times[i + 1] - times[i] != dt:
191
216
  raise Exception(
192
- 'CSVMixin: Expecting equidistant timeseries, the time step towards '
193
- '{} is not the same as the time step(s) before. Set csv_equidistant = False '
194
- 'if this is intended.'.format(times[i + 1]))
217
+ "CSVMixin: Expecting equidistant timeseries, the time step towards "
218
+ "{} is not the same as the time step(s) before. "
219
+ "Set csv_equidistant = False if this is intended.".format(times[i + 1])
220
+ )
195
221
 
196
222
  def ensemble_member_probability(self, ensemble_member):
197
223
  if self.csv_ensemble_mode:
198
- return self.__ensemble['probability'][ensemble_member]
224
+ return self.__ensemble["probability"][ensemble_member]
199
225
  else:
200
226
  return 1.0
201
227
 
@@ -207,11 +233,12 @@ class CSVMixin(IOMixin):
207
233
  initial_time = np.array([self.initial_time])
208
234
 
209
235
  # Load parameters from parameter config
210
- for variable in self.dae_variables['free_variables']:
236
+ for variable in self.dae_variables["free_variables"]:
211
237
  variable = variable.name()
212
238
  try:
213
- history[variable] = Timeseries(initial_time,
214
- self.__initial_state[ensemble_member][variable])
239
+ history[variable] = Timeseries(
240
+ initial_time, self.__initial_state[ensemble_member][variable]
241
+ )
215
242
  except (KeyError, ValueError):
216
243
  pass
217
244
  else:
@@ -228,30 +255,33 @@ class CSVMixin(IOMixin):
228
255
 
229
256
  def write_output(ensemble_member, folder):
230
257
  results = self.extract_results(ensemble_member)
231
- names = ['time'] + sorted({sym.name() for sym in self.output_variables})
232
- formats = ['O'] + (len(names) - 1) * ['f8']
233
- dtype = {'names': names, 'formats': formats}
258
+ names = ["time"] + sorted({sym.name() for sym in self.output_variables})
259
+ formats = ["O"] + (len(names) - 1) * ["f8"]
260
+ dtype = {"names": names, "formats": formats}
234
261
  data = np.zeros(len(times), dtype=dtype)
235
- data['time'] = [self.io.reference_datetime + timedelta(seconds=s) for s in times]
262
+ data["time"] = [self.io.reference_datetime + timedelta(seconds=s) for s in times]
236
263
  for output_variable in self.output_variables:
237
264
  output_variable = output_variable.name()
238
265
  try:
239
266
  values = results[output_variable]
240
267
  if len(values) != len(times):
241
268
  values = self.interpolate(
242
- times, self.times(output_variable), values, self.interpolation_method(output_variable))
269
+ times,
270
+ self.times(output_variable),
271
+ values,
272
+ self.interpolation_method(output_variable),
273
+ )
243
274
  except KeyError:
244
275
  try:
245
- ts = self.get_timeseries(
246
- output_variable, ensemble_member)
276
+ ts = self.get_timeseries(output_variable, ensemble_member)
247
277
  if len(ts.times) != len(times):
248
- values = self.interpolate(
249
- times, ts.times, ts.values)
278
+ values = self.interpolate(times, ts.times, ts.values)
250
279
  else:
251
280
  values = ts.values
252
281
  except KeyError:
253
282
  logger.error(
254
- "Output requested for non-existent variable {}".format(output_variable))
283
+ "Output requested for non-existent variable {}".format(output_variable)
284
+ )
255
285
  continue
256
286
  data[output_variable] = values
257
287
 
@@ -259,8 +289,9 @@ class CSVMixin(IOMixin):
259
289
  csv.save(fname, data, delimiter=self.csv_delimiter, with_time=True)
260
290
 
261
291
  if self.csv_ensemble_mode:
262
- for ensemble_member, ensemble_member_name in enumerate(self.__ensemble['name']):
263
- write_output(ensemble_member, os.path.join(
264
- self._output_folder, ensemble_member_name))
292
+ for ensemble_member, ensemble_member_name in enumerate(self.__ensemble["name"]):
293
+ write_output(
294
+ ensemble_member, os.path.join(self._output_folder, ensemble_member_name)
295
+ )
265
296
  else:
266
297
  write_output(0, self._output_folder)