BatteriesΒΆ

This notebook

[1]:
import os
import numpy as np
from pyltmapi import LtmSession, LtmPlot

import logging
logging.basicConfig(level=logging.INFO)

from pathlib import Path

ltm_core_path =  os.environ.get("LTM_CORE_PATH", str(Path("~").expanduser().joinpath("ltm/release/bin/")))
license_file = os.environ.get("LTM_CORE_LICENSE_FILE", str(Path("~").expanduser().joinpath("ltm/ltm-license.dat")))
[2]:
from IPython.display import display, display_markdown

ltmapi_version = LtmSession.version()
display(ltmapi_version)
'PyLTM version: 0.25.2'
[3]:
def usercallback(program_info: dict, userdata: any):
    print(userdata)
    print(program_info)

    return True


def print_have_results(area):
    print(
        f"{area}.have_detailed_hydro_results()      = {area.have_detailed_hydro_results()}"
    )
    print(
        f"{area}.have_aggregated_hydro_results()    = {area.have_aggregated_hydro_results()}"
    )
    print(
        f"{area}.have_battery_results()             = {area.have_battery_results()}"
    )
    print(
        f"{area}.have_water_value_results()         = {area.have_water_value_results()}"
    )
    print(
        f"{area}.have_market_results()              = {area.have_market_results()}"
    )


def generate_plots(ltm):
    # Water values and price series
    for dc_line in ltm.model.dclines():
        dc_line_exchange = dc_line.transmission_results(time_axis=False)
        if dc_line_exchange != None:
            dc_line_exchange = np.array(dc_line_exchange, copy=False)
            dim = np.size(dc_line_exchange)

    for battery in reversed(ltm.model.battery_modules()):
        LtmPlot.make_generic_plot(
            battery.sum_power_production(), f"Sum Battery Power Prod: {battery.name}"
        )

        LtmPlot.make_generic_plot(
            battery.sum_energy(), f"Sum Battery Energy: {battery.name}"
        )
        pass

    for agg in reversed(ltm.model.aggregated_hydro_modules()):
        LtmPlot.make_generic_plot(
            agg.sum_hydro_power_production(), f"Sum Hydro Power Prod: {agg.name}"
        )

        LtmPlot.make_generic_plot(
            agg.sum_hydro_energy(), f"Sum Hydro Energy: {agg.name}"
        )
        pass

    for area in reversed(ltm.model.areas()):
        print_have_results(area)

        # Market results
        LtmPlot.make_market_results_plot(area.market_result_price(), area.name)

        #
        LtmPlot.make_generic_plot(
            area.sum_hydro_production(), f"Sum Hydro Prod: {area.name}"
        )

        #
        LtmPlot.make_generic_plot(
            area.sum_reservoir(), f"Sum reservoir: {area.name}"
        )

        # Sum load
        LtmPlot.make_generic_plot(area.sum_load(), f"Sum load: {area.name}")
        LtmPlot.make_generic_plot(
            area.net_trade_on_market_steps(),
            f"Sum production from market steps: {area.name}",
        )

        # Water values
        LtmPlot.make_water_value_plot(area.water_value_results(), area.name)

    # Detailed hydro results from
    for area in ltm.model.areas():
        print(area)

        # area reservoirs
        for rsv in area.reservoirs():
            display("Reservoir")
            LtmPlot.make_generic_plot(rsv.reservoir(), f"Reservoir '{rsv.name}'")
            LtmPlot.make_generic_plot(rsv.discharge(), f"Discharge '{rsv.name}'")
            LtmPlot.make_generic_plot(rsv.inflow(), f"Inflow '{rsv.name}'")
            LtmPlot.make_generic_plot(rsv.production(), f"Production '{rsv.name}'")
[4]:
from pyltmapi import LtmDot


def open_and_write_model(filename: str):
    session = LtmSession("ikernel", ltm_core_path=ltm_core_path, overwrite_session=True)

    # Explicitly set license file
    session.model.global_settings.ltm_license_file_path = license_file

    with session:
        try:
            # Load model from file.
            session.load(filename=filename)

            # Write model to disk, and automatically generate an output directory.
            session.write_model()

            # Display model graph
            LtmDot.display_dot_image(session.build_connection_tree())
            LtmDot.display_dot_image(session.build_area_graph())

            # Execute/run LTM/EMPS on the model
            last_rc, results = session.execute_model()

            # If last return code is not 0, then there was an error.
            if last_rc != 0:
                err = results[0]["log_file_contents"]
                display_markdown(err)
            else:
                # Make plots from the results
                generate_plots(session)

        except Exception as e:
            print(e)
            raise (e)
[5]:
open_and_write_model("area_battery.json")
INFO:LtmApiModel:(ikernel) Loading model from file: area_battery.json
INFO:LtmApiModel:(ikernel) LtmApiModel::maybe_generate_output_dir: output_path: /builds/energy/ltm/pyltmapi/docs/ltm-api/guides/batteries/testout_batteries/2026-07-12-103619.794-EMPS-parallell
INFO:LtmApiModel:(ikernel) Using license file '/builds/energy/ltm/pyltmapi.tmp/CI_LTM_LICENSE_FILE'
INFO:LtmApiModel:(ikernel) Using license file '/builds/energy/ltm/pyltmapi.tmp/CI_LTM_LICENSE_FILE'
INFO:Validator:(ikernel) Model validation succeeded
INFO:LtmApiModel:(ikernel) Writing model to path /builds/energy/ltm/pyltmapi/docs/ltm-api/guides/batteries/testout_batteries/2026-07-12-103619.794-EMPS-parallell
INFO:InflowHandler:(ikernel) Writing inflow series
INFO:Validator:(ikernel) Model validation succeeded
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_1.svg
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_2.svg
INFO:LtmApiModel:(ikernel) Model executed successfully
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_4.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_5.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_6.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_7.png
area/battery_area.have_detailed_hydro_results()      = False
area/battery_area.have_aggregated_hydro_results()    = False
area/battery_area.have_battery_results()             = True
area/battery_area.have_water_value_results()         = True
area/battery_area.have_market_results()              = True
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_9.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_10.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_11.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_12.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_13.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_14.png
area/tev.have_detailed_hydro_results()      = False
area/tev.have_aggregated_hydro_results()    = True
area/tev.have_battery_results()             = False
area/tev.have_water_value_results()         = True
area/tev.have_market_results()              = True
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_16.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_17.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_18.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_19.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_20.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_21.png
area/numedal.have_detailed_hydro_results()      = True
area/numedal.have_aggregated_hydro_results()    = True
area/numedal.have_battery_results()             = False
area/numedal.have_water_value_results()         = True
area/numedal.have_market_results()              = True
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_23.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_24.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_25.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_26.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_27.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_28.png
area/numedal
'Reservoir'
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_31.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_32.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_33.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_34.png
'Reservoir'
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_36.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_37.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_38.png
../../../_images/ltm-api_guides_batteries_batteries-notebook_5_39.png
INFO:LtmApiModel:(ikernel) Not deleting output dir (/builds/energy/ltm/pyltmapi/docs/ltm-api/guides/batteries/testout_batteries/2026-07-12-103619.794-EMPS-parallell), as delete_output_dir: false, and has_generated_output_dir: true
INFO:LtmApiModel:(ikernel) Not deleting output dir (/builds/energy/ltm/pyltmapi/docs/ltm-api/guides/batteries/testout_batteries/2026-07-12-103619.794-EMPS-parallell), as delete_output_dir: false, and has_generated_output_dir: true
area/tev
area/battery_area