rtc-tools 2.7.0.dev2__py3-none-any.whl → 2.8.0a1__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.
- rtc_tools-2.8.0a1.dist-info/METADATA +279 -0
- rtc_tools-2.8.0a1.dist-info/RECORD +52 -0
- {rtc_tools-2.7.0.dev2.dist-info → rtc_tools-2.8.0a1.dist-info}/WHEEL +1 -2
- rtc_tools-2.8.0a1.dist-info/licenses/AUTHORS +10 -0
- rtc_tools-2.8.0a1.dist-info/licenses/COPYING +674 -0
- rtctools/__init__.py +2 -4
- rtctools/_internal/casadi_helpers.py +13 -5
- rtctools/_internal/ensemble_bounds_decorator.py +71 -0
- rtctools/data/netcdf.py +16 -15
- rtctools/data/pi.py +5 -2
- rtctools/data/rtc.py +3 -3
- rtctools/optimization/collocated_integrated_optimization_problem.py +75 -29
- rtctools/optimization/control_tree_mixin.py +9 -6
- rtctools/optimization/csv_lookup_table_mixin.py +5 -3
- rtctools/optimization/csv_mixin.py +3 -0
- rtctools/optimization/goal_programming_mixin.py +11 -5
- rtctools/optimization/goal_programming_mixin_base.py +29 -4
- rtctools/optimization/io_mixin.py +11 -5
- rtctools/optimization/min_abs_goal_programming_mixin.py +9 -3
- rtctools/optimization/modelica_mixin.py +23 -10
- rtctools/optimization/optimization_problem.py +55 -13
- rtctools/optimization/pi_mixin.py +3 -3
- rtctools/optimization/single_pass_goal_programming_mixin.py +9 -3
- rtctools/rtctoolsapp.py +15 -13
- rtctools/simulation/io_mixin.py +1 -1
- rtctools/simulation/pi_mixin.py +3 -3
- rtctools/simulation/simulation_problem.py +25 -12
- rtctools/util.py +1 -0
- rtctools/version.py +51 -0
- rtc_tools-2.7.0.dev2.dist-info/METADATA +0 -51
- rtc_tools-2.7.0.dev2.dist-info/RECORD +0 -50
- rtc_tools-2.7.0.dev2.dist-info/top_level.txt +0 -1
- rtctools/_version.py +0 -21
- {rtc_tools-2.7.0.dev2.dist-info → rtc_tools-2.8.0a1.dist-info}/entry_points.txt +0 -0
- {rtc_tools-2.7.0.dev2.dist-info → rtc_tools-2.8.0a1.dist-info/licenses}/COPYING.LESSER +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import itertools
|
|
3
|
-
from typing import List
|
|
3
|
+
from typing import List, Optional
|
|
4
4
|
|
|
5
5
|
import casadi as ca
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
|
+
from rtctools._internal.ensemble_bounds_decorator import ensemble_bounds_check
|
|
9
|
+
|
|
8
10
|
from .goal_programming_mixin import GoalProgrammingMixin
|
|
9
11
|
from .goal_programming_mixin_base import (
|
|
10
12
|
Goal,
|
|
@@ -86,8 +88,12 @@ class MinAbsGoalProgrammingMixin(_GoalProgrammingMixinBase):
|
|
|
86
88
|
def path_variables(self):
|
|
87
89
|
return super().path_variables + self.__problem_path_vars
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
@ensemble_bounds_check
|
|
92
|
+
def bounds(self, ensemble_member: Optional[int] = None):
|
|
93
|
+
bounds = (
|
|
94
|
+
super().bounds(ensemble_member) if self.ensemble_specific_bounds else super().bounds()
|
|
95
|
+
)
|
|
96
|
+
|
|
91
97
|
for abs_var in self.__problem_vars + self.__problem_path_vars:
|
|
92
98
|
bounds[abs_var.name()] = (0.0, np.inf)
|
|
93
99
|
return bounds
|
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
import importlib.resources
|
|
1
2
|
import itertools
|
|
2
3
|
import logging
|
|
3
|
-
|
|
4
|
+
import sys
|
|
5
|
+
from typing import Dict, Optional, Union
|
|
6
|
+
|
|
7
|
+
# Python 3.9's importlib.metadata does not support the "group" parameter to
|
|
8
|
+
# entry_points yet.
|
|
9
|
+
if sys.version_info < (3, 10):
|
|
10
|
+
import importlib_metadata
|
|
11
|
+
else:
|
|
12
|
+
from importlib import metadata as importlib_metadata
|
|
4
13
|
|
|
5
14
|
import casadi as ca
|
|
6
15
|
import numpy as np
|
|
7
|
-
import pkg_resources
|
|
8
16
|
import pymoca
|
|
9
17
|
import pymoca.backends.casadi.api
|
|
10
18
|
|
|
11
19
|
from rtctools._internal.alias_tools import AliasDict
|
|
12
20
|
from rtctools._internal.caching import cached
|
|
13
21
|
from rtctools._internal.casadi_helpers import substitute_in_external
|
|
22
|
+
from rtctools._internal.ensemble_bounds_decorator import ensemble_bounds_check
|
|
14
23
|
|
|
15
24
|
from .optimization_problem import OptimizationProblem
|
|
16
25
|
from .timeseries import Timeseries
|
|
@@ -174,9 +183,9 @@ class ModelicaMixin(OptimizationProblem):
|
|
|
174
183
|
# Where imported model libraries are located.
|
|
175
184
|
library_folders = self.modelica_library_folders.copy()
|
|
176
185
|
|
|
177
|
-
for ep in
|
|
186
|
+
for ep in importlib_metadata.entry_points(group="rtctools.libraries.modelica"):
|
|
178
187
|
if ep.name == "library_folder":
|
|
179
|
-
library_folders.append(
|
|
188
|
+
library_folders.append(str(importlib.resources.files(ep.module).joinpath(ep.attr)))
|
|
180
189
|
|
|
181
190
|
compiler_options["library_folders"] = library_folders
|
|
182
191
|
|
|
@@ -307,12 +316,16 @@ class ModelicaMixin(OptimizationProblem):
|
|
|
307
316
|
return self.__initial_residual
|
|
308
317
|
|
|
309
318
|
@cached
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
bounds =
|
|
319
|
+
@ensemble_bounds_check
|
|
320
|
+
def bounds(self, ensemble_member: Optional[int] = None):
|
|
321
|
+
bounds = (
|
|
322
|
+
super().bounds(ensemble_member) if self.ensemble_specific_bounds else super().bounds()
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
ensemble_member = ensemble_member if self.ensemble_specific_bounds else 0
|
|
313
326
|
|
|
314
327
|
# Parameter values
|
|
315
|
-
parameters = self.parameters(
|
|
328
|
+
parameters = self.parameters(ensemble_member)
|
|
316
329
|
parameter_values = [
|
|
317
330
|
parameters.get(param.name(), param) for param in self.__mx["parameters"]
|
|
318
331
|
]
|
|
@@ -326,7 +339,7 @@ class ModelicaMixin(OptimizationProblem):
|
|
|
326
339
|
try:
|
|
327
340
|
(m, M) = bounds[sym_name]
|
|
328
341
|
except KeyError:
|
|
329
|
-
if self.__python_types.get(sym_name, float)
|
|
342
|
+
if self.__python_types.get(sym_name, float) is bool:
|
|
330
343
|
(m, M) = (0, 1)
|
|
331
344
|
else:
|
|
332
345
|
(m, M) = (-np.inf, np.inf)
|
|
@@ -400,7 +413,7 @@ class ModelicaMixin(OptimizationProblem):
|
|
|
400
413
|
return seed
|
|
401
414
|
|
|
402
415
|
def variable_is_discrete(self, variable):
|
|
403
|
-
return self.__python_types.get(variable, float)
|
|
416
|
+
return self.__python_types.get(variable, float) is not float
|
|
404
417
|
|
|
405
418
|
@property
|
|
406
419
|
@cached
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from abc import ABCMeta, abstractmethod, abstractproperty
|
|
3
|
-
from typing import Any, Dict, Iterator, List, Tuple, Union
|
|
3
|
+
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
|
|
4
4
|
|
|
5
5
|
import casadi as ca
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
8
|
from rtctools._internal.alias_tools import AliasDict
|
|
9
9
|
from rtctools._internal.debug_check_helpers import DebugLevel, debug_check
|
|
10
|
+
from rtctools._internal.ensemble_bounds_decorator import ensemble_bounds_check
|
|
10
11
|
from rtctools.data.storage import DataStoreAccessor
|
|
11
12
|
|
|
12
13
|
from .timeseries import Timeseries
|
|
@@ -46,6 +47,9 @@ class OptimizationProblem(DataStoreAccessor, metaclass=ABCMeta):
|
|
|
46
47
|
_debug_check_level = DebugLevel.MEDIUM
|
|
47
48
|
_debug_check_options = {}
|
|
48
49
|
|
|
50
|
+
#: Enable ensemble-specific bounds functionality
|
|
51
|
+
ensemble_specific_bounds = False
|
|
52
|
+
|
|
49
53
|
def __init__(self, **kwargs):
|
|
50
54
|
# Call parent class first for default behaviour.
|
|
51
55
|
super().__init__(**kwargs)
|
|
@@ -199,12 +203,12 @@ class OptimizationProblem(DataStoreAccessor, metaclass=ABCMeta):
|
|
|
199
203
|
log_level = logging.INFO
|
|
200
204
|
logger.log(
|
|
201
205
|
log_level,
|
|
202
|
-
"Solver
|
|
206
|
+
"Solver failed with status {} ({}).".format(return_status, wall_clock_time),
|
|
203
207
|
)
|
|
204
208
|
except (AttributeError, ValueError):
|
|
205
209
|
logger.log(
|
|
206
210
|
log_level,
|
|
207
|
-
"Solver
|
|
211
|
+
"Solver failed with status {} ({}).".format(return_status, wall_clock_time),
|
|
208
212
|
)
|
|
209
213
|
|
|
210
214
|
# Do any postprocessing
|
|
@@ -221,14 +225,23 @@ class OptimizationProblem(DataStoreAccessor, metaclass=ABCMeta):
|
|
|
221
225
|
def __check_bounds_control_input(self) -> None:
|
|
222
226
|
# Checks if at the control inputs have bounds, log warning when a control input is not
|
|
223
227
|
# bounded.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
if self.ensemble_specific_bounds:
|
|
229
|
+
bounds_list = [
|
|
230
|
+
self.bounds(ensemble_member) for ensemble_member in range(self.ensemble_size)
|
|
231
|
+
]
|
|
232
|
+
else:
|
|
233
|
+
bounds_list = [self.bounds()]
|
|
234
|
+
|
|
235
|
+
for ensemble_member, bounds in enumerate(bounds_list):
|
|
236
|
+
for variable in self.dae_variables["control_inputs"]:
|
|
237
|
+
variable = variable.name()
|
|
238
|
+
if variable not in bounds:
|
|
239
|
+
logger.warning(
|
|
240
|
+
"OptimizationProblem: control input {} has no bounds{}.".format(
|
|
241
|
+
variable,
|
|
242
|
+
f" ({ensemble_member=})" if self.ensemble_specific_bounds else "",
|
|
243
|
+
)
|
|
244
|
+
)
|
|
232
245
|
|
|
233
246
|
@abstractmethod
|
|
234
247
|
def transcribe(
|
|
@@ -314,6 +327,24 @@ class OptimizationProblem(DataStoreAccessor, metaclass=ABCMeta):
|
|
|
314
327
|
if log_level == logging.ERROR and not log_solver_failure_as_error:
|
|
315
328
|
log_level = logging.INFO
|
|
316
329
|
|
|
330
|
+
if self.solver_options()["solver"].lower() == "knitro":
|
|
331
|
+
list_feas_flags = [
|
|
332
|
+
"KN_RC_OPTIMAL_OR_SATISFACTORY",
|
|
333
|
+
"KN_RC_ITER_LIMIT_FEAS",
|
|
334
|
+
"KN_RC_NEAR_OPT",
|
|
335
|
+
"KN_RC_FEAS_XTOL",
|
|
336
|
+
"KN_RC_FEAS_NO_IMPROVE",
|
|
337
|
+
"KN_RC_FEAS_FTOL",
|
|
338
|
+
"KN_RC_TIME_LIMIT_FEAS",
|
|
339
|
+
"KN_RC_FEVAL_LIMIT_FEAS",
|
|
340
|
+
"KN_RC_MIP_EXH_FEAS",
|
|
341
|
+
"KN_RC_MIP_TERM_FEAS",
|
|
342
|
+
"KN_RC_MIP_SOLVE_LIMIT_FEAS",
|
|
343
|
+
"KN_RC_MIP_NODE_LIMIT_FEAS",
|
|
344
|
+
]
|
|
345
|
+
if solver_stats["return_status"] in list_feas_flags:
|
|
346
|
+
success = True
|
|
347
|
+
|
|
317
348
|
return success, log_level
|
|
318
349
|
|
|
319
350
|
@abstractproperty
|
|
@@ -589,19 +620,30 @@ class OptimizationProblem(DataStoreAccessor, metaclass=ABCMeta):
|
|
|
589
620
|
|
|
590
621
|
return m, M
|
|
591
622
|
|
|
592
|
-
|
|
623
|
+
@ensemble_bounds_check
|
|
624
|
+
def bounds(self, ensemble_member: Optional[int] = None) -> AliasDict[str, Tuple[BT, BT]]:
|
|
593
625
|
"""
|
|
594
626
|
Returns variable bounds as a dictionary mapping variable names to a pair of bounds.
|
|
595
627
|
A bound may be a constant, or a time series.
|
|
596
628
|
|
|
629
|
+
:param ensemble_member: The ensemble member index. Must be None (or not provided) when
|
|
630
|
+
ensemble_specific_bounds is False. Must be an integer when
|
|
631
|
+
ensemble_specific_bounds is True.
|
|
632
|
+
|
|
597
633
|
:returns: A dictionary of variable names and ``(upper, lower)`` bound pairs.
|
|
598
634
|
The bounds may be numbers or :class:`.Timeseries` objects.
|
|
599
635
|
|
|
600
636
|
Example::
|
|
601
|
-
|
|
637
|
+
# ensemble_specific_bounds is False
|
|
602
638
|
def bounds(self):
|
|
603
639
|
return {'x': (1.0, 2.0), 'y': (2.0, 3.0)}
|
|
604
640
|
|
|
641
|
+
# ensemble_specific_bounds is True
|
|
642
|
+
def bounds(self, ensemble_member: int):
|
|
643
|
+
if ensemble_member == 0:
|
|
644
|
+
return {'x': (1.0, 2.0), 'y': (2.0, 3.0)}
|
|
645
|
+
else:
|
|
646
|
+
return {'x': (0.0, 3.0), 'y': (1.0, 4.0)}
|
|
605
647
|
"""
|
|
606
648
|
return AliasDict(self.alias_relation)
|
|
607
649
|
|
|
@@ -285,8 +285,8 @@ class PIMixin(IOMixin):
|
|
|
285
285
|
:param variable: Time series ID.
|
|
286
286
|
:param unit: Unit.
|
|
287
287
|
"""
|
|
288
|
-
assert hasattr(
|
|
289
|
-
|
|
290
|
-
)
|
|
288
|
+
assert hasattr(self, "_PIMixin__timeseries_import"), (
|
|
289
|
+
"set_unit can only be called after read() in pre() has finished."
|
|
290
|
+
)
|
|
291
291
|
self.__timeseries_import.set_unit(variable, unit, 0)
|
|
292
292
|
self.__timeseries_export.set_unit(variable, unit, 0)
|
|
@@ -2,11 +2,13 @@ import itertools
|
|
|
2
2
|
import logging
|
|
3
3
|
from collections import OrderedDict
|
|
4
4
|
from enum import Enum
|
|
5
|
-
from typing import Dict, Union
|
|
5
|
+
from typing import Dict, Optional, Union
|
|
6
6
|
|
|
7
7
|
import casadi as ca
|
|
8
8
|
import numpy as np
|
|
9
9
|
|
|
10
|
+
from rtctools._internal.ensemble_bounds_decorator import ensemble_bounds_check
|
|
11
|
+
|
|
10
12
|
from .goal_programming_mixin import GoalProgrammingMixin
|
|
11
13
|
from .goal_programming_mixin_base import ( # noqa: F401
|
|
12
14
|
Goal,
|
|
@@ -109,8 +111,12 @@ class SinglePassGoalProgrammingMixin(_GoalProgrammingMixinBase):
|
|
|
109
111
|
def path_variables(self):
|
|
110
112
|
return self.__problem_path_epsilons
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
@ensemble_bounds_check
|
|
115
|
+
def bounds(self, ensemble_member: Optional[int] = None):
|
|
116
|
+
bounds = (
|
|
117
|
+
super().bounds(ensemble_member) if self.ensemble_specific_bounds else super().bounds()
|
|
118
|
+
)
|
|
119
|
+
|
|
114
120
|
for epsilon in self.__problem_epsilons + self.__problem_path_epsilons:
|
|
115
121
|
bounds[epsilon.name()] = (0.0, 1.0)
|
|
116
122
|
return bounds
|
rtctools/rtctoolsapp.py
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
import importlib.resources
|
|
1
2
|
import logging
|
|
2
3
|
import os
|
|
3
4
|
import shutil
|
|
4
5
|
import sys
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
|
|
8
|
+
# Python 3.9's importlib.metadata does not support the "group" parameter to
|
|
9
|
+
# entry_points yet.
|
|
10
|
+
if sys.version_info < (3, 10):
|
|
11
|
+
import importlib_metadata
|
|
12
|
+
else:
|
|
13
|
+
from importlib import metadata as importlib_metadata
|
|
14
|
+
|
|
7
15
|
import rtctools
|
|
8
16
|
|
|
9
17
|
logging.basicConfig(format="%(asctime)s %(levelname)s %(message)s")
|
|
@@ -23,9 +31,6 @@ def copy_libraries(*args):
|
|
|
23
31
|
if not os.path.exists(path):
|
|
24
32
|
sys.exit("Folder '{}' does not exist".format(path))
|
|
25
33
|
|
|
26
|
-
# pkg_resources can be quite a slow import, so we do it here
|
|
27
|
-
import pkg_resources
|
|
28
|
-
|
|
29
34
|
def _copytree(src, dst, symlinks=False, ignore=None):
|
|
30
35
|
if not os.path.exists(dst):
|
|
31
36
|
os.makedirs(dst)
|
|
@@ -56,11 +61,10 @@ def copy_libraries(*args):
|
|
|
56
61
|
dst = Path(path)
|
|
57
62
|
|
|
58
63
|
library_folders = []
|
|
59
|
-
|
|
64
|
+
|
|
65
|
+
for ep in importlib_metadata.entry_points(group="rtctools.libraries.modelica"):
|
|
60
66
|
if ep.name == "library_folder":
|
|
61
|
-
library_folders.append(
|
|
62
|
-
Path(pkg_resources.resource_filename(ep.module_name, ep.attrs[0]))
|
|
63
|
-
)
|
|
67
|
+
library_folders.append(Path(importlib.resources.files(ep.module).joinpath(ep.attr)))
|
|
64
68
|
|
|
65
69
|
tlds = {}
|
|
66
70
|
for lf in library_folders:
|
|
@@ -100,11 +104,8 @@ def download_examples(*args):
|
|
|
100
104
|
from zipfile import ZipFile
|
|
101
105
|
|
|
102
106
|
version = rtctools.__version__
|
|
103
|
-
rtc_full_name = "rtc-tools-{}".format(version)
|
|
104
107
|
try:
|
|
105
|
-
url = "https://
|
|
106
|
-
version, rtc_full_name
|
|
107
|
-
)
|
|
108
|
+
url = "https://github.com/deltares/rtc-tools/zipball/{}".format(version)
|
|
108
109
|
|
|
109
110
|
opener = urllib.request.build_opener()
|
|
110
111
|
urllib.request.install_opener(opener)
|
|
@@ -115,11 +116,12 @@ def download_examples(*args):
|
|
|
115
116
|
|
|
116
117
|
with ZipFile(local_filename, "r") as z:
|
|
117
118
|
target = path / "rtc-tools-examples"
|
|
118
|
-
|
|
119
|
+
zip_folder_name = next(x for x in z.namelist() if x.startswith("Deltares-rtc-tools-"))
|
|
120
|
+
prefix = "{}/examples/".format(zip_folder_name.rstrip("/"))
|
|
119
121
|
members = [x for x in z.namelist() if x.startswith(prefix)]
|
|
120
122
|
z.extractall(members=members)
|
|
121
123
|
shutil.move(prefix, target)
|
|
122
|
-
shutil.rmtree(
|
|
124
|
+
shutil.rmtree(zip_folder_name)
|
|
123
125
|
|
|
124
126
|
sys.exit("Succesfully downloaded the RTC-Tools examples to '{}'".format(target.resolve()))
|
|
125
127
|
|
rtctools/simulation/io_mixin.py
CHANGED
|
@@ -94,7 +94,7 @@ class IOMixin(SimulationProblem, metaclass=ABCMeta):
|
|
|
94
94
|
self.__cache_loop_timeseries = {}
|
|
95
95
|
|
|
96
96
|
timeseries_names = set(self.io.get_timeseries_names(0))
|
|
97
|
-
for v in self.
|
|
97
|
+
for v in self.get_input_variables():
|
|
98
98
|
if v in timeseries_names:
|
|
99
99
|
_, values = self.io.get_timeseries_sec(v)
|
|
100
100
|
self.__cache_loop_timeseries[v] = values
|
rtctools/simulation/pi_mixin.py
CHANGED
|
@@ -248,8 +248,8 @@ class PIMixin(IOMixin):
|
|
|
248
248
|
:param variable: Time series ID.
|
|
249
249
|
:param unit: Unit.
|
|
250
250
|
"""
|
|
251
|
-
assert hasattr(
|
|
252
|
-
|
|
253
|
-
)
|
|
251
|
+
assert hasattr(self, "_PIMixin__timeseries_import"), (
|
|
252
|
+
"set_unit can only be called after read() in pre() has finished."
|
|
253
|
+
)
|
|
254
254
|
self.__timeseries_import.set_unit(variable, unit, 0)
|
|
255
255
|
self.__timeseries_export.set_unit(variable, unit, 0)
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import copy
|
|
2
|
+
import importlib.resources
|
|
2
3
|
import itertools
|
|
3
4
|
import logging
|
|
4
5
|
import math
|
|
6
|
+
import sys
|
|
5
7
|
from collections import OrderedDict
|
|
6
8
|
from typing import List, Union
|
|
7
9
|
|
|
10
|
+
# Python 3.9's importlib.metadata does not support the "group" parameter to
|
|
11
|
+
# entry_points yet.
|
|
12
|
+
if sys.version_info < (3, 10):
|
|
13
|
+
import importlib_metadata
|
|
14
|
+
else:
|
|
15
|
+
from importlib import metadata as importlib_metadata
|
|
16
|
+
|
|
8
17
|
import casadi as ca
|
|
9
18
|
import numpy as np
|
|
10
|
-
import pkg_resources
|
|
11
19
|
import pymoca
|
|
12
20
|
import pymoca.backends.casadi.api
|
|
13
21
|
|
|
@@ -492,8 +500,9 @@ class SimulationProblem(DataStoreAccessor):
|
|
|
492
500
|
self.set_var(var_name, numeric_start_val)
|
|
493
501
|
except KeyError:
|
|
494
502
|
logger.warning(
|
|
495
|
-
"Initialize: {} not found in state vector. "
|
|
496
|
-
|
|
503
|
+
"Initialize: {} not found in state vector. Initial value of {} not set.".format(
|
|
504
|
+
var_name, numeric_start_val
|
|
505
|
+
)
|
|
497
506
|
)
|
|
498
507
|
|
|
499
508
|
# Add a residual for the difference between the state and its starting expression
|
|
@@ -517,10 +526,14 @@ class SimulationProblem(DataStoreAccessor):
|
|
|
517
526
|
# Check that the start_value is in between the variable bounds.
|
|
518
527
|
if start_is_numeric and not min_is_symbolic and not max_is_symbolic:
|
|
519
528
|
if not (var.min <= start_val and start_val <= var.max):
|
|
520
|
-
logger.
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
529
|
+
logger.log(
|
|
530
|
+
(
|
|
531
|
+
logging.WARNING
|
|
532
|
+
if source_description != "modelica file or default value"
|
|
533
|
+
else logging.DEBUG
|
|
534
|
+
),
|
|
535
|
+
f"Initialize: start value {var_name} = {start_val} "
|
|
536
|
+
f"is not in between bounds {var.min} and {var.max} and will be adjusted.",
|
|
524
537
|
)
|
|
525
538
|
|
|
526
539
|
# Default start var for ders is zero
|
|
@@ -1059,9 +1072,9 @@ class SimulationProblem(DataStoreAccessor):
|
|
|
1059
1072
|
:param dt: Timestep size of the simulation.
|
|
1060
1073
|
"""
|
|
1061
1074
|
if self._dt_is_fixed:
|
|
1062
|
-
assert math.isclose(
|
|
1063
|
-
|
|
1064
|
-
)
|
|
1075
|
+
assert math.isclose(self.__dt, dt), (
|
|
1076
|
+
"Timestep size dt is marked as constant and cannot be changed."
|
|
1077
|
+
)
|
|
1065
1078
|
else:
|
|
1066
1079
|
self.__dt = dt
|
|
1067
1080
|
|
|
@@ -1244,9 +1257,9 @@ class SimulationProblem(DataStoreAccessor):
|
|
|
1244
1257
|
# Where imported model libraries are located.
|
|
1245
1258
|
library_folders = self.modelica_library_folders.copy()
|
|
1246
1259
|
|
|
1247
|
-
for ep in
|
|
1260
|
+
for ep in importlib_metadata.entry_points(group="rtctools.libraries.modelica"):
|
|
1248
1261
|
if ep.name == "library_folder":
|
|
1249
|
-
library_folders.append(
|
|
1262
|
+
library_folders.append(str(importlib.resources.files(ep.module).joinpath(ep.attr)))
|
|
1250
1263
|
|
|
1251
1264
|
compiler_options["library_folders"] = library_folders
|
|
1252
1265
|
|
rtctools/util.py
CHANGED
rtctools/version.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Compute the version number and store it in the `__version__` variable.
|
|
2
|
+
|
|
3
|
+
Based on <https://github.com/maresb/hatch-vcs-footgun-example>.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _get_hatch_version():
|
|
8
|
+
"""Compute the most up-to-date version number in a development environment.
|
|
9
|
+
|
|
10
|
+
Returns `None` if Hatchling is not installed, e.g. in a production environment.
|
|
11
|
+
|
|
12
|
+
For more details, see <https://github.com/maresb/hatch-vcs-footgun-example/>.
|
|
13
|
+
"""
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
import hatch_vcs # noqa: F401
|
|
18
|
+
from hatchling.metadata.core import ProjectMetadata
|
|
19
|
+
from hatchling.plugin.manager import PluginManager
|
|
20
|
+
from hatchling.utils.fs import locate_file
|
|
21
|
+
except ImportError:
|
|
22
|
+
# Hatchling and/or hatch-vcs are not installed, so probably we are not
|
|
23
|
+
# in a development environment.
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
pyproject_toml = locate_file(__file__, "pyproject.toml")
|
|
27
|
+
if pyproject_toml is None:
|
|
28
|
+
raise RuntimeError("pyproject.toml not found although hatchling is installed")
|
|
29
|
+
root = os.path.dirname(pyproject_toml)
|
|
30
|
+
metadata = ProjectMetadata(root=root, plugin_manager=PluginManager())
|
|
31
|
+
# Version can be either statically set in pyproject.toml or computed dynamically:
|
|
32
|
+
return metadata.core.version or metadata.hatch.version.cached
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _get_importlib_metadata_version():
|
|
36
|
+
"""Compute the version number using importlib.metadata.
|
|
37
|
+
|
|
38
|
+
This is the official Pythonic way to get the version number of an installed
|
|
39
|
+
package. However, it is only updated when a package is installed. Thus, if a
|
|
40
|
+
package is installed in editable mode, and a different version is checked out,
|
|
41
|
+
then the version number will not be updated.
|
|
42
|
+
"""
|
|
43
|
+
from importlib.metadata import version
|
|
44
|
+
|
|
45
|
+
# NOTE: We cannot use `__package__` here, because our folder name is
|
|
46
|
+
# "rtctools", with our package name "rtc-tools" (with a dash).
|
|
47
|
+
__version__ = version("rtc-tools")
|
|
48
|
+
return __version__
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
__version__ = _get_hatch_version() or _get_importlib_metadata_version()
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: rtc-tools
|
|
3
|
-
Version: 2.7.0.dev2
|
|
4
|
-
Summary: Toolbox for control and optimization of water systems.
|
|
5
|
-
Home-page: https://oss.deltares.nl/web/rtc-tools/home
|
|
6
|
-
Download-URL: http://gitlab.com/deltares/rtc-tools/
|
|
7
|
-
Author: Deltares
|
|
8
|
-
Maintainer: Deltares
|
|
9
|
-
Platform: Windows
|
|
10
|
-
Platform: Linux
|
|
11
|
-
Platform: Mac OS-X
|
|
12
|
-
Platform: Unix
|
|
13
|
-
Classifier: Development Status :: 4 - Beta
|
|
14
|
-
Classifier: Intended Audience :: Science/Research
|
|
15
|
-
Classifier: Intended Audience :: Information Technology
|
|
16
|
-
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
|
|
17
|
-
Classifier: Programming Language :: Python
|
|
18
|
-
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
20
|
-
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
21
|
-
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
22
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
23
|
-
Classifier: Operating System :: POSIX
|
|
24
|
-
Classifier: Operating System :: Unix
|
|
25
|
-
Classifier: Operating System :: MacOS
|
|
26
|
-
Requires-Python: >=3.9
|
|
27
|
-
License-File: COPYING.LESSER
|
|
28
|
-
Requires-Dist: casadi!=3.6.6,==3.6.*,>=3.6.3
|
|
29
|
-
Requires-Dist: numpy>=1.16.0
|
|
30
|
-
Requires-Dist: scipy>=1.0.0
|
|
31
|
-
Requires-Dist: pymoca==0.9.*,>=0.9.1
|
|
32
|
-
Requires-Dist: rtc-tools-channel-flow>=1.2.0
|
|
33
|
-
Requires-Dist: defusedxml>=0.7.0
|
|
34
|
-
Provides-Extra: netcdf
|
|
35
|
-
Requires-Dist: netCDF4; extra == "netcdf"
|
|
36
|
-
Provides-Extra: all
|
|
37
|
-
Requires-Dist: netCDF4; extra == "all"
|
|
38
|
-
Dynamic: author
|
|
39
|
-
Dynamic: classifier
|
|
40
|
-
Dynamic: description
|
|
41
|
-
Dynamic: download-url
|
|
42
|
-
Dynamic: home-page
|
|
43
|
-
Dynamic: maintainer
|
|
44
|
-
Dynamic: platform
|
|
45
|
-
Dynamic: provides-extra
|
|
46
|
-
Dynamic: requires-dist
|
|
47
|
-
Dynamic: requires-python
|
|
48
|
-
Dynamic: summary
|
|
49
|
-
|
|
50
|
-
RTC-Tools is the Deltares toolbox for control and optimization of water systems.
|
|
51
|
-
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
rtctools/__init__.py,sha256=91hvS2-ryd2Pvw0COpsUzTwJwSnTZ035REiej-1hNI4,107
|
|
2
|
-
rtctools/_version.py,sha256=MKiTFKmzZzk3ruW9CeIqZv3Ttm1g0-MB9CDCLpfrPnw,502
|
|
3
|
-
rtctools/rtctoolsapp.py,sha256=UnkuiJhv0crEEVs8H6PYvMuc2y_q6V_xLuyKEgXj9GM,4200
|
|
4
|
-
rtctools/util.py,sha256=PaeKfDUA174ODZbY5fZjCTf-F-TdhW7yEuP189Ro190,9075
|
|
5
|
-
rtctools/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
rtctools/_internal/alias_tools.py,sha256=XuQSAhhFuVtwn0yrAObZWIKPsSF4j2axXRtEmitIFPs,5310
|
|
7
|
-
rtctools/_internal/caching.py,sha256=p4gqSL7kCI7Hff-KjMEP7mhJCQSiU_lYm2MR7E18gBM,905
|
|
8
|
-
rtctools/_internal/casadi_helpers.py,sha256=oAf5zyFkZbaMhvhgMnQkOi2A6dBOzj-VAUkYwBf-Jxk,1410
|
|
9
|
-
rtctools/_internal/debug_check_helpers.py,sha256=UgQTEPw4PyR7MbYLewSSWQqTwQj7xr5yUBk820O9Kk4,1084
|
|
10
|
-
rtctools/data/__init__.py,sha256=EllgSmCdrlvQZSd1VilvjPaeYJGhY9ErPiQtedmuFoA,157
|
|
11
|
-
rtctools/data/csv.py,sha256=hEpoTH3nhZaAvRN4r-9-nYeAjaFiNDRoiZWg8GxM3yo,5539
|
|
12
|
-
rtctools/data/netcdf.py,sha256=xpk4Ggl7gItNG6lO7p3OJPR-elK8_CiCtxUI7cX0gwk,19109
|
|
13
|
-
rtctools/data/pi.py,sha256=5w50zWgI79Vu5EMMz-MKoManXYqsjxfFgcZN6Z3eeiQ,46638
|
|
14
|
-
rtctools/data/rtc.py,sha256=1yGJZGq2Z36MYLiLuZaHnxupL4mgw-Wuu54PAG05kcM,9077
|
|
15
|
-
rtctools/data/storage.py,sha256=67J4BRTl0AMEzlKNZ8Xdpy_4cGtwx8Lo_tL2n0G4S9w,13206
|
|
16
|
-
rtctools/data/interpolation/__init__.py,sha256=GBubCIT5mFoSTV-lOk7cpwvZekNMEe5bvqSQJ9HE34M,73
|
|
17
|
-
rtctools/data/interpolation/bspline.py,sha256=qevB842XWCH3fWlWMBqKMy1mw37ust-0YtSnb9PKCEc,948
|
|
18
|
-
rtctools/data/interpolation/bspline1d.py,sha256=HAh7m5xLBuiFKzMzuYEqZX_GmCPChKjV7ynTS6iRZOc,6166
|
|
19
|
-
rtctools/data/interpolation/bspline2d.py,sha256=ScmX0fPDxbUVtj3pbUE0L7UJocqroD_6fUT-4cvdRMc,1693
|
|
20
|
-
rtctools/optimization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
rtctools/optimization/collocated_integrated_optimization_problem.py,sha256=Bv1a1O4QTAdIpe9SOA9_oEDDph-oj-9q5yfN4SFMdW8,131343
|
|
22
|
-
rtctools/optimization/control_tree_mixin.py,sha256=CC6TWp3kFQgMokx6213pRLx9iY17Fd0VcwG4Wpwa0Uo,8974
|
|
23
|
-
rtctools/optimization/csv_lookup_table_mixin.py,sha256=h4WKuPR1BJbYuJfQ9lx4rXalB6yYK-zajINabRL7BrA,17298
|
|
24
|
-
rtctools/optimization/csv_mixin.py,sha256=sRp5paHWfCw2bz-23Nw-HdFLS3CZTpVwaBdFo98DbvE,12252
|
|
25
|
-
rtctools/optimization/goal_programming_mixin.py,sha256=r2pPzcqi-VlstPx4CdtUT0JeemduiYBV5zeH4kA9QGs,33301
|
|
26
|
-
rtctools/optimization/goal_programming_mixin_base.py,sha256=IvA3cfJmUW9SaDGATD7r4Rrjku9T4oI2H68imPTlq2A,43816
|
|
27
|
-
rtctools/optimization/homotopy_mixin.py,sha256=Kh0kMfxB-Fo1FBGW5tPOQk24Xx_Mmw_p0YuSQotdkMU,6905
|
|
28
|
-
rtctools/optimization/initial_state_estimation_mixin.py,sha256=74QYfG-VYYTNVg-kAnCG6QoY3_sUmaID0ideF7bPkkY,3116
|
|
29
|
-
rtctools/optimization/io_mixin.py,sha256=AsZQ7YOUcUbWoczmjTXaSje5MUEsPNbQyZBJ6qzSjzU,11821
|
|
30
|
-
rtctools/optimization/linearization_mixin.py,sha256=mG5S7uwvwDydw-eBPyQKnLyKoy08EBjQh25vu97afhY,1049
|
|
31
|
-
rtctools/optimization/linearized_order_goal_programming_mixin.py,sha256=LQ2qpYt0YGLpEoerif4FJ5wwzq16q--27bsRjcqIU5A,9087
|
|
32
|
-
rtctools/optimization/min_abs_goal_programming_mixin.py,sha256=WMOv9EF8cfDJgTunzXfI_cUmBSQK26u1HJB_9EAarfM,14031
|
|
33
|
-
rtctools/optimization/modelica_mixin.py,sha256=9MnZ2tz9WWMeUg7UuS7TNOuqvfZhuTDvZsDfS6HcBIo,17796
|
|
34
|
-
rtctools/optimization/netcdf_mixin.py,sha256=-zkXh3sMYE50c3kHsrmUVGWMSFm-0cXQpGrCm0yn-Tc,7563
|
|
35
|
-
rtctools/optimization/optimization_problem.py,sha256=qzpc81NaZMeoXKuayFmBF15iXYuNAk5yxmaER_Gcz_A,44131
|
|
36
|
-
rtctools/optimization/pi_mixin.py,sha256=n_ZyifuNPxcRoJXKR6Ks7DgK_b7-EToYJ23_khOwpzo,11786
|
|
37
|
-
rtctools/optimization/planning_mixin.py,sha256=O_Y74X8xZmaNZR4iYOe7BR06s9hnmcapbuHYHQTBPPQ,724
|
|
38
|
-
rtctools/optimization/single_pass_goal_programming_mixin.py,sha256=Zb9szg3PGT2o6gkGsXluSfEaAswkw3TKfPQDzUrj_Y4,25784
|
|
39
|
-
rtctools/optimization/timeseries.py,sha256=nCrsGCJThBMh9lvngEpbBDa834_QvklVvkxJqwX4a1M,1734
|
|
40
|
-
rtctools/simulation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
-
rtctools/simulation/csv_mixin.py,sha256=rGDUFPsqGHmF0_dWdXeWzWzMpkPmwCNweTBVrwSh31g,6704
|
|
42
|
-
rtctools/simulation/io_mixin.py,sha256=SJasNGI--OQ9Y-Z61oeeaGCxSrNddYz4AOVfJYbmf74,6209
|
|
43
|
-
rtctools/simulation/pi_mixin.py,sha256=vcizArZsOn7tGlSFCsUmkjmRFA1A1kMNqUllLlkVc9Y,9831
|
|
44
|
-
rtctools/simulation/simulation_problem.py,sha256=8k3MjznzvFIut04NAiu7UAhfndAvNTkQFsO9vbmNd-0,49567
|
|
45
|
-
rtc_tools-2.7.0.dev2.dist-info/COPYING.LESSER,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
|
|
46
|
-
rtc_tools-2.7.0.dev2.dist-info/METADATA,sha256=MKSiD7EB2VvL5lozEHyI4TSLh5tvIVAhgxr-6_QQkAw,1691
|
|
47
|
-
rtc_tools-2.7.0.dev2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
48
|
-
rtc_tools-2.7.0.dev2.dist-info/entry_points.txt,sha256=DVS8sWf3b9ph9h8srEr6zmQ7ZKGwblwgZgGPZg-jRNQ,150
|
|
49
|
-
rtc_tools-2.7.0.dev2.dist-info/top_level.txt,sha256=pnBrb58PFPd1kp1dqa-JHU7R55h3alDNJIJnF3Jf9Dw,9
|
|
50
|
-
rtc_tools-2.7.0.dev2.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
rtctools
|
rtctools/_version.py
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# This file was generated by 'versioneer.py' (0.29) from
|
|
3
|
-
# revision-control system data, or from the parent directory name of an
|
|
4
|
-
# unpacked source archive. Distribution tarballs contain a pre-generated copy
|
|
5
|
-
# of this file.
|
|
6
|
-
|
|
7
|
-
import json
|
|
8
|
-
|
|
9
|
-
version_json = '''
|
|
10
|
-
{
|
|
11
|
-
"date": "2025-02-04T13:27:11+0100",
|
|
12
|
-
"dirty": false,
|
|
13
|
-
"error": null,
|
|
14
|
-
"full-revisionid": "3bdb1fdfd01f5ae5e4dff117abe8862d9316352a",
|
|
15
|
-
"version": "2.7.0.dev2"
|
|
16
|
-
}
|
|
17
|
-
''' # END VERSION_JSON
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def get_versions():
|
|
21
|
-
return json.loads(version_json)
|
|
File without changes
|
|
File without changes
|