.. _residual-loads-label: ============== Residual loads ============== Negative residual loads might lead to an unsolvable EMPS problem, or even cause a crash when executing the model. There is no hard limit for when negative residual loads will cause these kinds of trouble, but a few rules of thumb exist: If it is negative for just one price segment in one week for one scenario, that will work just fine. And if it is always negative, it will fail for sure. A short period of time will probaly work, but the longer the period then higher is the risk of failure. The residual load is calculated for each :ref:`market-calibration-areas-label`. .. note:: The residual load will always be calculated and it will be checked if it's negative when executing/writing the model to disk. The internal check uses 1 hour as sampling rate, and 52 weeks as group by. If the validation fails, LTM-API will refuse to continue. To force LTM-API to continue, set ``global_settings.allow_validation_failures`` to ``true``. Definition ========== Residual load is the difference between loads (ENMD group 16) and unregulated energy production (wind, solar, aggregated hydro modules). .. math:: \sum_{i=1}^{timesteps}\Biggl( \sum_{n=1}^{num loads}(\text{loads(n)}) ) - \biggl( \sum_{n=1}^{num wind}(\text{wind(n)}) + \sum_{n=1}^{num solar}(\text{solar(n)}) + \sum_{n=1}^{num unreg}(\text{unreg_agg_inflow(n)} \biggl) \Biggl) If there is more unregulated production than consumtion, there is a negative residual load. Residual load results ===================== The results are grouped by *market calibration area* name. If there are no explicit groups defined, a group named ``default`` is used and all applicable objects are used to calculate the residual load. Example results --------------- With 2 market calibration area names, there are two groups, ``market_area_1`` and ``market_area_2``. Each area contains 2 :ref:`Txy ` variables with a total average for all scenarios, and one average per scenario. .. collapse:: Listing with JSON-like results All results are intentionally 0.0. .. code-block:: JSON :caption: JSON-ified results :linenos: { "market_area_1": { "total": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 0.0, 0.0, 0.0 ] ] }, "scenario": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 0.0, 0.0, 0.0 ], [ 0.0, 0.0, 0.0 ] ] } }, "market_area_2": { "total": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 0.0, 0.0, 0.0 ] ] }, "scenario": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 0.0, 0.0, 0.0 ], [ 0.0, 0.0, 0.0 ] ] } } } Example model with a load specified, with only differences to :ref:`market calibration areas ` shown. Download :download:`residual_loads.json <../../../../tests/residual_loads.json>`. .. literalinclude:: ../../../../tests/residual_loads.json :diff: ../../../../tests/market_calibration_areas.json :language: JSON :linenos: ``market_area_1`` is assigned a constant load ``FLAT`` with 1 scenario. ``market_area_2`` is assigned a constant load ``FLAT_SCENARIO``, with different values for each scenario. This example model has 2 scenarios (``historical_period`` spans 2 years). .. collapse:: Listing with constant load results .. code-block:: JSON :linenos: { "market_area_1": { "total": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 100.0000000000046, 100.0000000000046, 100.0000000000046 ] ] }, "scenario": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 100.0000000000046, 100.0000000000046, 100.0000000000046 ], [ 100.0000000000046, 100.0000000000046, 100.0000000000046 ] ] } }, "market_area_2": { "total": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 300.0000000000373, 300.0000000000373, 300.0000000000373 ] ] }, "scenario": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 100.0000000000046, 100.0000000000046, 100.0000000000046 ], [ 500.00000000007, 500.00000000007, 500.00000000007 ] ] } } } Negative residual loads ======================= Expanding the above model with exaggerated values for ``wind``, ``solar`` and ``aggregated_hydro_modules``, the residual becomes negative. Only showing the differences between residual_loads and negative_residual_loads. Download complete :download:`negative_residual_loads.json <../../../../tests/negative_residual_loads.json>`. .. collapse:: Negative residual loads model file differences .. literalinclude:: ../../../../tests/negative_residual_loads.json :diff: ../../../../tests/residual_loads.json :language: JSON :linenos: .. collapse:: Negative residual loads example results .. code-block:: json { "market_area_1": { "total": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ -672.9000000000501, -672.9000000000501, -672.9000000000501 ] ] }, "scenario": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ -200.80000000003793, -200.80000000003793, -200.80000000003793 ], [ -1145.0000000000623, -1145.0000000000623, -1145.0000000000623 ] ] } }, "market_area_2": { "total": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 288.49999999996965, -253.0082417583355, 284.012362637335 ] ] }, "scenario": { "timestamps": [ "2024-01-01T00:00:00Z", "2024-12-30T00:00:00Z", "2025-12-29T00:00:00Z" ], "scenarios": [ [ 88.99999999998887, -994.0164835166214, 80.0247252747196 ], [ 487.99999999995043, 487.99999999995043, 487.99999999995043 ] ] } } } When running the model through this script, validation will fail. .. literalinclude:: ../../../../tests/residual_loads.py :language: python :linenos: Output: .. code-block:: (negative_residual_session) Model discrepancies found: 4 (negative_residual_session) [market_calibration_area_check] Negative residual load for area 'market_area_1' at 2024-01-01T00:00:00Z for scenario 0. Residual load -672.90 (negative_residual_session) [market_calibration_area_check] Negative residual load for area 'market_area_1' at 2024-12-30T00:00:00Z for scenario 0. Residual load -672.90 (negative_residual_session) [market_calibration_area_check] Negative residual load for area 'market_area_1' at 2025-12-29T00:00:00Z for scenario 0. Residual load -672.90 (negative_residual_session) [market_calibration_area_check] Negative residual load for area 'market_area_2' at 2024-12-30T00:00:00Z for scenario 0. Residual load -253.01 (negative_residual_session) Model validation failed