rtc-tools 2.7.0.dev2__py3-none-any.whl → 2.8.0a0__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 (35) hide show
  1. rtc_tools-2.8.0a0.dist-info/METADATA +279 -0
  2. rtc_tools-2.8.0a0.dist-info/RECORD +52 -0
  3. {rtc_tools-2.7.0.dev2.dist-info → rtc_tools-2.8.0a0.dist-info}/WHEEL +1 -2
  4. rtc_tools-2.8.0a0.dist-info/licenses/AUTHORS +10 -0
  5. rtc_tools-2.8.0a0.dist-info/licenses/COPYING +674 -0
  6. rtctools/__init__.py +2 -4
  7. rtctools/_internal/casadi_helpers.py +13 -5
  8. rtctools/_internal/ensemble_bounds_decorator.py +71 -0
  9. rtctools/data/netcdf.py +16 -15
  10. rtctools/data/pi.py +5 -2
  11. rtctools/data/rtc.py +3 -3
  12. rtctools/optimization/collocated_integrated_optimization_problem.py +75 -29
  13. rtctools/optimization/control_tree_mixin.py +9 -6
  14. rtctools/optimization/csv_lookup_table_mixin.py +5 -3
  15. rtctools/optimization/csv_mixin.py +3 -0
  16. rtctools/optimization/goal_programming_mixin.py +11 -5
  17. rtctools/optimization/goal_programming_mixin_base.py +29 -4
  18. rtctools/optimization/io_mixin.py +11 -5
  19. rtctools/optimization/min_abs_goal_programming_mixin.py +9 -3
  20. rtctools/optimization/modelica_mixin.py +23 -10
  21. rtctools/optimization/optimization_problem.py +53 -11
  22. rtctools/optimization/pi_mixin.py +3 -3
  23. rtctools/optimization/single_pass_goal_programming_mixin.py +9 -3
  24. rtctools/rtctoolsapp.py +15 -13
  25. rtctools/simulation/io_mixin.py +1 -1
  26. rtctools/simulation/pi_mixin.py +3 -3
  27. rtctools/simulation/simulation_problem.py +25 -12
  28. rtctools/util.py +1 -0
  29. rtctools/version.py +51 -0
  30. rtc_tools-2.7.0.dev2.dist-info/METADATA +0 -51
  31. rtc_tools-2.7.0.dev2.dist-info/RECORD +0 -50
  32. rtc_tools-2.7.0.dev2.dist-info/top_level.txt +0 -1
  33. rtctools/_version.py +0 -21
  34. {rtc_tools-2.7.0.dev2.dist-info → rtc_tools-2.8.0a0.dist-info}/entry_points.txt +0 -0
  35. {rtc_tools-2.7.0.dev2.dist-info → rtc_tools-2.8.0a0.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
- def bounds(self):
90
- bounds = super().bounds()
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
- from typing import Dict, Union
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 pkg_resources.iter_entry_points(group="rtctools.libraries.modelica"):
186
+ for ep in importlib_metadata.entry_points(group="rtctools.libraries.modelica"):
178
187
  if ep.name == "library_folder":
179
- library_folders.append(pkg_resources.resource_filename(ep.module_name, ep.attrs[0]))
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
- def bounds(self):
311
- # Call parent class first for default values.
312
- bounds = super().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(0)
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) == bool:
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) != 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)
@@ -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
- bounds = self.bounds()
225
-
226
- for variable in self.dae_variables["control_inputs"]:
227
- variable = variable.name()
228
- if variable not in bounds:
229
- logger.warning(
230
- "OptimizationProblem: control input {} has no bounds.".format(variable)
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
- def bounds(self) -> AliasDict[str, Tuple[BT, BT]]:
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
- self, "_PIMixin__timeseries_import"
290
- ), "set_unit can only be called after read() in pre() has finished."
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
- def bounds(self):
113
- bounds = super().bounds()
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
- for ep in pkg_resources.iter_entry_points(group="rtctools.libraries.modelica"):
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://gitlab.com/deltares/rtc-tools/-/archive/{}/{}.zip".format(
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
- prefix = "{}/examples/".format(rtc_full_name)
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(rtc_full_name)
124
+ shutil.rmtree(zip_folder_name)
123
125
 
124
126
  sys.exit("Succesfully downloaded the RTC-Tools examples to '{}'".format(target.resolve()))
125
127
 
@@ -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.get_variables():
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
@@ -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
- self, "_PIMixin__timeseries_import"
253
- ), "set_unit can only be called after read() in pre() has finished."
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
- "Initial value of {} not set.".format(var_name, numeric_start_val)
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.warning(
521
- "Initialize: start value {} = {}".format(var_name, start_val)
522
- + " is not in between bounds {} and {}".format(var.min, var.max)
523
- + " and will be adjusted."
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
- self.__dt, dt
1064
- ), "Timestep size dt is marked as constant and cannot be changed."
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 pkg_resources.iter_entry_points(group="rtctools.libraries.modelica"):
1260
+ for ep in importlib_metadata.entry_points(group="rtctools.libraries.modelica"):
1248
1261
  if ep.name == "library_folder":
1249
- library_folders.append(pkg_resources.resource_filename(ep.module_name, ep.attrs[0]))
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
@@ -110,6 +110,7 @@ def run_optimization_problem(
110
110
  "GoalProgrammingMixin",
111
111
  "PIMixin",
112
112
  "CSVMixin",
113
+ "IOMixin",
113
114
  "ModelicaMixin",
114
115
  "PlanningMixin",
115
116
  "ControlTreeMixin",
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)