flixopt 2.1.0__tar.gz → 2.1.1__tar.gz

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 flixopt might be problematic. Click here for more details.

Files changed (97) hide show
  1. {flixopt-2.1.0 → flixopt-2.1.1}/PKG-INFO +1 -1
  2. flixopt-2.1.1/docs/release-notes/v2.1.1.md +11 -0
  3. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/components.py +4 -1
  4. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/elements.py +4 -3
  5. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/results.py +1 -1
  6. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt.egg-info/PKG-INFO +1 -1
  7. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt.egg-info/SOURCES.txt +1 -0
  8. {flixopt-2.1.0 → flixopt-2.1.1}/tests/conftest.py +1 -1
  9. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_flow.py +137 -2
  10. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_storage.py +1 -1
  11. {flixopt-2.1.0 → flixopt-2.1.1}/.github/workflows/deploy-docs.yaml +0 -0
  12. {flixopt-2.1.0 → flixopt-2.1.1}/.github/workflows/python-app.yaml +0 -0
  13. {flixopt-2.1.0 → flixopt-2.1.1}/.gitignore +0 -0
  14. {flixopt-2.1.0 → flixopt-2.1.1}/LICENSE +0 -0
  15. {flixopt-2.1.0 → flixopt-2.1.1}/README.md +0 -0
  16. {flixopt-2.1.0 → flixopt-2.1.1}/docs/SUMMARY.md +0 -0
  17. {flixopt-2.1.0 → flixopt-2.1.1}/docs/contribute.md +0 -0
  18. {flixopt-2.1.0 → flixopt-2.1.1}/docs/examples/00-Minimal Example.md +0 -0
  19. {flixopt-2.1.0 → flixopt-2.1.1}/docs/examples/01-Basic Example.md +0 -0
  20. {flixopt-2.1.0 → flixopt-2.1.1}/docs/examples/02-Complex Example.md +0 -0
  21. {flixopt-2.1.0 → flixopt-2.1.1}/docs/examples/03-Calculation Modes.md +0 -0
  22. {flixopt-2.1.0 → flixopt-2.1.1}/docs/examples/index.md +0 -0
  23. {flixopt-2.1.0 → flixopt-2.1.1}/docs/faq/contribute.md +0 -0
  24. {flixopt-2.1.0 → flixopt-2.1.1}/docs/faq/index.md +0 -0
  25. {flixopt-2.1.0 → flixopt-2.1.1}/docs/getting-started.md +0 -0
  26. {flixopt-2.1.0 → flixopt-2.1.1}/docs/images/architecture_flixOpt-pre2.0.0.png +0 -0
  27. {flixopt-2.1.0 → flixopt-2.1.1}/docs/images/architecture_flixOpt.png +0 -0
  28. {flixopt-2.1.0 → flixopt-2.1.1}/docs/images/flixopt-icon.svg +0 -0
  29. {flixopt-2.1.0 → flixopt-2.1.1}/docs/index.md +0 -0
  30. {flixopt-2.1.0 → flixopt-2.1.1}/docs/javascripts/mathjax.js +0 -0
  31. {flixopt-2.1.0 → flixopt-2.1.1}/docs/release-notes/_template.txt +0 -0
  32. {flixopt-2.1.0 → flixopt-2.1.1}/docs/release-notes/index.md +0 -0
  33. {flixopt-2.1.0 → flixopt-2.1.1}/docs/release-notes/v2.0.0.md +0 -0
  34. {flixopt-2.1.0 → flixopt-2.1.1}/docs/release-notes/v2.0.1.md +0 -0
  35. {flixopt-2.1.0 → flixopt-2.1.1}/docs/release-notes/v2.1.0.md +0 -0
  36. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/Bus.md +0 -0
  37. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md +0 -0
  38. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/Flow.md +0 -0
  39. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/LinearConverter.md +0 -0
  40. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/Piecewise.md +0 -0
  41. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/Storage.md +0 -0
  42. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/index.md +0 -0
  43. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/Mathematical Notation/others.md +0 -0
  44. {flixopt-2.1.0 → flixopt-2.1.1}/docs/user-guide/index.md +0 -0
  45. {flixopt-2.1.0 → flixopt-2.1.1}/examples/00_Minmal/minimal_example.py +0 -0
  46. {flixopt-2.1.0 → flixopt-2.1.1}/examples/01_Simple/simple_example.py +0 -0
  47. {flixopt-2.1.0 → flixopt-2.1.1}/examples/02_Complex/complex_example.py +0 -0
  48. {flixopt-2.1.0 → flixopt-2.1.1}/examples/02_Complex/complex_example_results.py +0 -0
  49. {flixopt-2.1.0 → flixopt-2.1.1}/examples/03_Calculation_types/Zeitreihen2020.csv +0 -0
  50. {flixopt-2.1.0 → flixopt-2.1.1}/examples/03_Calculation_types/example_calculation_types.py +0 -0
  51. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/__init__.py +0 -0
  52. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/aggregation.py +0 -0
  53. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/calculation.py +0 -0
  54. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/commons.py +0 -0
  55. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/config.py +0 -0
  56. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/config.yaml +0 -0
  57. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/core.py +0 -0
  58. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/effects.py +0 -0
  59. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/features.py +0 -0
  60. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/flow_system.py +0 -0
  61. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/interface.py +0 -0
  62. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/io.py +0 -0
  63. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/linear_converters.py +0 -0
  64. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/plotting.py +0 -0
  65. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/solvers.py +0 -0
  66. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/structure.py +0 -0
  67. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt/utils.py +0 -0
  68. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt.egg-info/dependency_links.txt +0 -0
  69. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt.egg-info/requires.txt +0 -0
  70. {flixopt-2.1.0 → flixopt-2.1.1}/flixopt.egg-info/top_level.txt +0 -0
  71. {flixopt-2.1.0 → flixopt-2.1.1}/mkdocs.yml +0 -0
  72. {flixopt-2.1.0 → flixopt-2.1.1}/pics/architecture_flixOpt-pre2.0.0.png +0 -0
  73. {flixopt-2.1.0 → flixopt-2.1.1}/pics/architecture_flixOpt.png +0 -0
  74. {flixopt-2.1.0 → flixopt-2.1.1}/pics/flixOpt_plotting.jpg +0 -0
  75. {flixopt-2.1.0 → flixopt-2.1.1}/pics/flixopt-icon.svg +0 -0
  76. {flixopt-2.1.0 → flixopt-2.1.1}/pics/pics.pptx +0 -0
  77. {flixopt-2.1.0 → flixopt-2.1.1}/pyproject.toml +0 -0
  78. {flixopt-2.1.0 → flixopt-2.1.1}/scripts/gen_ref_pages.py +0 -0
  79. {flixopt-2.1.0 → flixopt-2.1.1}/setup.cfg +0 -0
  80. {flixopt-2.1.0 → flixopt-2.1.1}/site/release-notes/_template.txt +0 -0
  81. {flixopt-2.1.0 → flixopt-2.1.1}/tests/__init__.py +0 -0
  82. {flixopt-2.1.0 → flixopt-2.1.1}/tests/ressources/Zeitreihen2020.csv +0 -0
  83. {flixopt-2.1.0 → flixopt-2.1.1}/tests/run_all_tests.py +0 -0
  84. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_bus.py +0 -0
  85. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_component.py +0 -0
  86. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_dataconverter.py +0 -0
  87. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_effect.py +0 -0
  88. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_examples.py +0 -0
  89. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_functional.py +0 -0
  90. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_integration.py +0 -0
  91. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_io.py +0 -0
  92. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_linear_converter.py +0 -0
  93. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_on_hours_computation.py +0 -0
  94. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_plots.py +0 -0
  95. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_results_plots.py +0 -0
  96. {flixopt-2.1.0 → flixopt-2.1.1}/tests/test_timeseries.py +0 -0
  97. {flixopt-2.1.0 → flixopt-2.1.1}/tests/todos.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flixopt
3
- Version: 2.1.0
3
+ Version: 2.1.1
4
4
  Summary: Vector based energy and material flow optimization framework in Python.
5
5
  Author-email: "Chair of Building Energy Systems and Heat Supply, TU Dresden" <peter.stange@tu-dresden.de>, Felix Bumann <felixbumann387@gmail.com>, Felix Panitz <baumbude@googlemail.com>, Peter Stange <peter.stange@tu-dresden.de>
6
6
  Maintainer-email: Felix Bumann <felixbumann387@gmail.com>, Peter Stange <peter.stange@tu-dresden.de>
@@ -0,0 +1,11 @@
1
+ # Release v2.1.1
2
+
3
+ **Release Date:** 2025-05-08
4
+
5
+ ## Improvements
6
+
7
+ * Improving docstring and tests
8
+
9
+ ## Bug Fixes
10
+
11
+ * Fixing bug in the `_ElementResults.constraints` not returning the constraints but rather the variables
@@ -43,7 +43,10 @@ class LinearConverter(Component):
43
43
  label: The label of the Element. Used to identify it in the FlowSystem
44
44
  inputs: The input Flows
45
45
  outputs: The output Flows
46
- on_off_parameters: Information about on and off states. See class OnOffParameters.
46
+ on_off_parameters: Information about on and off state of LinearConverter.
47
+ Component is On/Off, if all connected Flows are On/Off. This induces an On-Variable (binary) in all Flows!
48
+ If possible, use OnOffParameters in a single Flow instead to keep the number of binary variables low.
49
+ See class OnOffParameters.
47
50
  conversion_factors: linear relation between flows.
48
51
  Either 'conversion_factors' or 'piecewise_conversion' can be used!
49
52
  piecewise_conversion: Define a piecewise linear relation between flow rates of different flows.
@@ -47,8 +47,8 @@ class Component(Element):
47
47
  inputs: input flows.
48
48
  outputs: output flows.
49
49
  on_off_parameters: Information about on and off state of Component.
50
- Component is On/Off, if all connected Flows are On/Off.
51
- Induces On-Variable in all FLows!
50
+ Component is On/Off, if all connected Flows are On/Off. This induces an On-Variable (binary) in all Flows!
51
+ If possible, use OnOffParameters in a single Flow instead to keep the number of binary variables low.
52
52
  See class OnOffParameters.
53
53
  prevent_simultaneous_flows: Define a Group of Flows. Only one them can be on at a time.
54
54
  Induces On-Variable in all Flows! If possible, use OnOffParameters in a single Flow instead.
@@ -193,7 +193,8 @@ class Flow(Element):
193
193
  (relative_minimum and relative_maximum are ignored)
194
194
  used for fixed load or supply profiles, i.g. heat demand, wind-power, solarthermal
195
195
  If the load-profile is just an upper limit, use relative_maximum instead.
196
- previous_flow_rate: previous flow rate of the component.
196
+ previous_flow_rate: previous flow rate of the flow. Used to determine if and how long the
197
+ flow is already on / off. If None, the flow is considered to be off for one timestep.
197
198
  meta_data: used to store more information about the Element. Is not used internally, but saved in the results. Only use python native types.
198
199
  """
199
200
  super().__init__(label, meta_data=meta_data)
@@ -343,7 +343,7 @@ class _ElementResults:
343
343
  """
344
344
  if self._calculation_results.model is None:
345
345
  raise ValueError('The linopy model is not available.')
346
- return self._calculation_results.model.constraints[self._variable_names]
346
+ return self._calculation_results.model.constraints[self._constraint_names]
347
347
 
348
348
  def filter_solution(self, variable_dims: Optional[Literal['scalar', 'time']] = None) -> xr.Dataset:
349
349
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flixopt
3
- Version: 2.1.0
3
+ Version: 2.1.1
4
4
  Summary: Vector based energy and material flow optimization framework in Python.
5
5
  Author-email: "Chair of Building Energy Systems and Heat Supply, TU Dresden" <peter.stange@tu-dresden.de>, Felix Bumann <felixbumann387@gmail.com>, Felix Panitz <baumbude@googlemail.com>, Peter Stange <peter.stange@tu-dresden.de>
6
6
  Maintainer-email: Felix Bumann <felixbumann387@gmail.com>, Peter Stange <peter.stange@tu-dresden.de>
@@ -25,6 +25,7 @@ docs/release-notes/index.md
25
25
  docs/release-notes/v2.0.0.md
26
26
  docs/release-notes/v2.0.1.md
27
27
  docs/release-notes/v2.1.0.md
28
+ docs/release-notes/v2.1.1.md
28
29
  docs/user-guide/index.md
29
30
  docs/user-guide/Mathematical Notation/Bus.md
30
31
  docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md
@@ -432,7 +432,7 @@ def timesteps_linopy(request):
432
432
  @pytest.fixture
433
433
  def basic_flow_system_linopy(timesteps_linopy) -> fx.FlowSystem:
434
434
  """Create basic elements for component testing"""
435
- flow_system = fx.FlowSystem(pd.date_range('2020-01-01', periods=10, freq='h', name='time'))
435
+ flow_system = fx.FlowSystem(timesteps_linopy)
436
436
  thermal_load = np.array([np.random.random() for _ in range(10)]) * 180
437
437
  p_el = (np.array([np.random.random() for _ in range(10)]) + 0.5) / 1.5 * 50
438
438
 
@@ -616,6 +616,73 @@ class TestFlowOnModel:
616
616
  >= (model.variables['Sink(Wärme)|on'].isel(time=slice(None, -1)) - model.variables['Sink(Wärme)|on'].isel(time=slice(1, None))) * 2
617
617
  )
618
618
 
619
+ def test_consecutive_on_hours_previous(self, basic_flow_system_linopy):
620
+ """Test flow with minimum and maximum consecutive on hours."""
621
+ flow_system = basic_flow_system_linopy
622
+ timesteps = flow_system.time_series_collection.timesteps
623
+
624
+ flow = fx.Flow(
625
+ 'Wärme',
626
+ bus='Fernwärme',
627
+ size=100,
628
+ on_off_parameters=fx.OnOffParameters(
629
+ consecutive_on_hours_min=2, # Must run for at least 2 hours when turned on
630
+ consecutive_on_hours_max=8, # Can't run more than 8 consecutive hours
631
+ ),
632
+ previous_flow_rate=np.array([10, 20, 30, 0, 20, 20, 30]) # Previously on for 3 steps
633
+ )
634
+
635
+ flow_system.add_elements( fx.Sink('Sink', sink=flow))
636
+ model = create_linopy_model(flow_system)
637
+
638
+ assert {'Sink(Wärme)|ConsecutiveOn|hours', 'Sink(Wärme)|on'}.issubset(set(flow.model.variables))
639
+
640
+ assert {'Sink(Wärme)|ConsecutiveOn|con1',
641
+ 'Sink(Wärme)|ConsecutiveOn|con2a',
642
+ 'Sink(Wärme)|ConsecutiveOn|con2b',
643
+ 'Sink(Wärme)|ConsecutiveOn|initial',
644
+ 'Sink(Wärme)|ConsecutiveOn|minimum',
645
+ }.issubset(set(flow.model.constraints))
646
+
647
+ assert_var_equal(
648
+ model.variables['Sink(Wärme)|ConsecutiveOn|hours'],
649
+ model.add_variables(lower=0, upper=8, coords=(timesteps,))
650
+ )
651
+
652
+ mega = model.hours_per_step.sum('time') + model.hours_per_step.isel(time=0) * 3
653
+
654
+ assert_conequal(
655
+ model.constraints['Sink(Wärme)|ConsecutiveOn|con1'],
656
+ model.variables['Sink(Wärme)|ConsecutiveOn|hours'] <= model.variables['Sink(Wärme)|on'] * mega
657
+ )
658
+
659
+ assert_conequal(
660
+ model.constraints['Sink(Wärme)|ConsecutiveOn|con2a'],
661
+ model.variables['Sink(Wärme)|ConsecutiveOn|hours'].isel(time=slice(1, None))
662
+ <= model.variables['Sink(Wärme)|ConsecutiveOn|hours'].isel(time=slice(None, -1)) + model.hours_per_step.isel(time=slice(None, -1))
663
+ )
664
+
665
+ # eq: duration(t) >= duration(t - 1) + dt(t) + (On(t) - 1) * BIG
666
+ assert_conequal(
667
+ model.constraints['Sink(Wärme)|ConsecutiveOn|con2b'],
668
+ model.variables['Sink(Wärme)|ConsecutiveOn|hours'].isel(time=slice(1, None))
669
+ >= model.variables['Sink(Wärme)|ConsecutiveOn|hours'].isel(time=slice(None, -1))
670
+ + model.hours_per_step.isel(time=slice(None, -1))
671
+ + (model.variables['Sink(Wärme)|on'].isel(time=slice(1, None)) - 1) * mega
672
+ )
673
+
674
+ assert_conequal(
675
+ model.constraints['Sink(Wärme)|ConsecutiveOn|initial'],
676
+ model.variables['Sink(Wärme)|ConsecutiveOn|hours'].isel(time=0)
677
+ == model.variables['Sink(Wärme)|on'].isel(time=0) * (model.hours_per_step.isel(time=0) * (1 + 3)),
678
+ )
679
+
680
+ assert_conequal(
681
+ model.constraints['Sink(Wärme)|ConsecutiveOn|minimum'],
682
+ model.variables['Sink(Wärme)|ConsecutiveOn|hours']
683
+ >= (model.variables['Sink(Wärme)|on'].isel(time=slice(None, -1)) - model.variables['Sink(Wärme)|on'].isel(time=slice(1, None))) * 2
684
+ )
685
+
619
686
  def test_consecutive_off_hours(self, basic_flow_system_linopy):
620
687
  """Test flow with minimum and maximum consecutive off hours."""
621
688
  flow_system = basic_flow_system_linopy
@@ -649,7 +716,75 @@ class TestFlowOnModel:
649
716
  model.add_variables(lower=0, upper=12, coords=(timesteps,))
650
717
  )
651
718
 
652
- mega = model.hours_per_step.sum('time') + 1 # previously off for 1h
719
+ mega = model.hours_per_step.sum('time') + model.hours_per_step.isel(time=0) * 1 # previously off for 1h
720
+
721
+ assert_conequal(
722
+ model.constraints['Sink(Wärme)|ConsecutiveOff|con1'],
723
+ model.variables['Sink(Wärme)|ConsecutiveOff|hours'] <= model.variables['Sink(Wärme)|off'] * mega
724
+ )
725
+
726
+ assert_conequal(
727
+ model.constraints['Sink(Wärme)|ConsecutiveOff|con2a'],
728
+ model.variables['Sink(Wärme)|ConsecutiveOff|hours'].isel(time=slice(1, None))
729
+ <= model.variables['Sink(Wärme)|ConsecutiveOff|hours'].isel(time=slice(None, -1)) + model.hours_per_step.isel(time=slice(None, -1))
730
+ )
731
+
732
+ # eq: duration(t) >= duration(t - 1) + dt(t) + (On(t) - 1) * BIG
733
+ assert_conequal(
734
+ model.constraints['Sink(Wärme)|ConsecutiveOff|con2b'],
735
+ model.variables['Sink(Wärme)|ConsecutiveOff|hours'].isel(time=slice(1, None))
736
+ >= model.variables['Sink(Wärme)|ConsecutiveOff|hours'].isel(time=slice(None, -1))
737
+ + model.hours_per_step.isel(time=slice(None, -1))
738
+ + (model.variables['Sink(Wärme)|off'].isel(time=slice(1, None)) - 1) * mega
739
+ )
740
+
741
+ assert_conequal(
742
+ model.constraints['Sink(Wärme)|ConsecutiveOff|initial'],
743
+ model.variables['Sink(Wärme)|ConsecutiveOff|hours'].isel(time=0)
744
+ == model.variables['Sink(Wärme)|off'].isel(time=0) * (model.hours_per_step.isel(time=0) * (1 + 1)),
745
+ )
746
+
747
+ assert_conequal(
748
+ model.constraints['Sink(Wärme)|ConsecutiveOff|minimum'],
749
+ model.variables['Sink(Wärme)|ConsecutiveOff|hours']
750
+ >= (model.variables['Sink(Wärme)|off'].isel(time=slice(None, -1)) - model.variables['Sink(Wärme)|off'].isel(time=slice(1, None))) * 4
751
+ )
752
+
753
+ def test_consecutive_off_hours_previous(self, basic_flow_system_linopy):
754
+ """Test flow with minimum and maximum consecutive off hours."""
755
+ flow_system = basic_flow_system_linopy
756
+ timesteps = flow_system.time_series_collection.timesteps
757
+
758
+ flow = fx.Flow(
759
+ 'Wärme',
760
+ bus='Fernwärme',
761
+ size=100,
762
+ on_off_parameters=fx.OnOffParameters(
763
+ consecutive_off_hours_min=4, # Must stay off for at least 4 hours when shut down
764
+ consecutive_off_hours_max=12, # Can't be off for more than 12 consecutive hours
765
+ ),
766
+ previous_flow_rate=np.array([10, 20, 30, 0, 20, 0, 0]) # Previously off for 2 steps
767
+ )
768
+
769
+ flow_system.add_elements( fx.Sink('Sink', sink=flow))
770
+ model = create_linopy_model(flow_system)
771
+
772
+ assert {'Sink(Wärme)|ConsecutiveOff|hours', 'Sink(Wärme)|off'}.issubset(set(flow.model.variables))
773
+
774
+ assert {
775
+ 'Sink(Wärme)|ConsecutiveOff|con1',
776
+ 'Sink(Wärme)|ConsecutiveOff|con2a',
777
+ 'Sink(Wärme)|ConsecutiveOff|con2b',
778
+ 'Sink(Wärme)|ConsecutiveOff|initial',
779
+ 'Sink(Wärme)|ConsecutiveOff|minimum'
780
+ }.issubset(set(flow.model.constraints))
781
+
782
+ assert_var_equal(
783
+ model.variables['Sink(Wärme)|ConsecutiveOff|hours'],
784
+ model.add_variables(lower=0, upper=12, coords=(timesteps,))
785
+ )
786
+
787
+ mega = model.hours_per_step.sum('time') + model.hours_per_step.isel(time=0) * 2
653
788
 
654
789
  assert_conequal(
655
790
  model.constraints['Sink(Wärme)|ConsecutiveOff|con1'],
@@ -674,7 +809,7 @@ class TestFlowOnModel:
674
809
  assert_conequal(
675
810
  model.constraints['Sink(Wärme)|ConsecutiveOff|initial'],
676
811
  model.variables['Sink(Wärme)|ConsecutiveOff|hours'].isel(time=0)
677
- == model.variables['Sink(Wärme)|off'].isel(time=0) * (model.hours_per_step.isel(time=0)+1),
812
+ == model.variables['Sink(Wärme)|off'].isel(time=0) * (model.hours_per_step.isel(time=0) * (1+2)),
678
813
  )
679
814
 
680
815
  assert_conequal(
@@ -78,7 +78,7 @@ class TestStorageModel:
78
78
  assert_conequal(
79
79
  model.constraints['TestStorage|charge_state'],
80
80
  charge_state.isel(time=slice(1, None))
81
- == charge_state.isel(time=slice(None, -1)) * model.hours_per_step
81
+ == charge_state.isel(time=slice(None, -1))
82
82
  + model.variables['TestStorage(Q_th_in)|flow_rate'] * model.hours_per_step
83
83
  - model.variables['TestStorage(Q_th_out)|flow_rate'] * model.hours_per_step,
84
84
  )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes