Pumps¶
This notebook is an example on how to use pumps with and without power plants. It contains an example on how to use revisions (unavailable capacity) on pumps and plants.
Unavailable capacity is set by attribute unavailable_capacity on Plant and Pump.
"unavailable_capacity": {
"timestamps": [
"2023-01-02T00:00:00Z",
"2024-06-01T00:00:00Z",
"2024-12-01T00:00:00Z"
],
"scenarios": [
[
170,
150,
0
]
]
}
Example plot for a plant with a pump:
No revisions:¶
No revisions set
Plant revision:¶
A substantial revision set on the power plant to reduce production. Max power production is down to ~45WM from ~150MW.
Pump and plant revisions:¶
Same revision on the plant.
Pump capacity is down to ~25MW, from ~100MW.
[1]:
import os
import numpy as np
from pyltmapi import LtmSession, LtmPlot, LtmDot
import pyltm
import json
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 HTML, Image, display, display_markdown
ltmapi_version = LtmSession.version()
display(f"pyltm version {ltmapi_version}")
'pyltm version PyLTM version: 0.25.2'
[3]:
def usercallback(program_info, userdata):
# print(userdata)
# print(program_info)
return True
def generate_plots(ltm):
for dc_line in ltm.model.dclines():
if(dc_line.have_transmission_results()):
LtmPlot.make_generic_plot(dc_line.transmission_results(),name="Exchange " + '"'+dc_line.name+'"')
# Water values and price series
for area in ltm.model.areas():
display_markdown(f"# area: {area}", raw=True)
# Pumped energy
if (area.have_pump_results()):
pumped_energy = area.sum_pumped_power()
LtmPlot.make_generic_plot(pumped_energy, f"sum_pumped_power '{area.name}'")
energy_pumping = area.sum_power_used_for_pumping()
LtmPlot.make_generic_plot(energy_pumping, f"sum_power_used_for_pumping '{area.name}'")
# Water values
if (area.have_water_value_results()):
LtmPlot.make_water_value_plot(area.water_value_results(), area.name)
# Market results
if (area.have_market_results()):
LtmPlot.make_market_results_plot(area.market_result_price(), area.name)
# extract market step results
for market_step in ltm.model.market_steps():
if(market_step.have_results()):
if(area.name == market_step.area_name):
time, ms = market_step.results()
LtmPlot.generic_plot(time, ms, name="Market step"+'"'+market_step.name+'"' +' "'+area.name+'"')
# Detailed hydro results from
for area in ltm.model.areas():
if(area.have_detailed_hydro_results()):
display_markdown(f"## {area}", raw=True)
LtmDot.display_dot_image(area.build_connection_tree())
# 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}'")
LtmPlot.make_generic_plot(rsv.bypass(), f"Bypass '{rsv.name}'")
LtmPlot.make_generic_plot(rsv.spill(), f"Spill '{rsv.name}'")
[4]:
def open_and_write_model(filename: str):
session = LtmSession("ikernel", ltm_core_path=ltm_core_path, overwrite_session=True)
session.set_execute_callback(usercallback, None)
# Explicitly set license file
session.model.global_settings.ltm_license_file_path = license_file
session.model.global_settings.simulation_type = pyltm.SimulationType.Parallel
with session:
try:
print(f"python pid: {os.getpid()}") # for debugging
# Load model from file.
session.load(filename=filename)
# print(vars(session.model.global_settings))
session.model.global_settings.model_type = pyltm.ModelType.EMPS
# Write model to disk, and automatically generate an output directory.
session.write_model()
# session.dump_model("pump_dump")
# Display model graph
LtmDot.display_dot_image(session.build_connection_tree())
LtmDot.display_dot_image(session.build_area_graph())
# return
# 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"]
LtmDot.print(err)
else:
# Make plots from the results
generate_plots(session)
except Exception as e:
print(e)
raise (e)
[5]:
open_and_write_model("pumps.json")
INFO:LtmApiModel:(ikernel) Loading model from file: pumps.json
INFO:LtmApiModel:(ikernel) LtmApiModel::maybe_generate_output_dir: output_path: /builds/energy/ltm/pyltmapi/docs/ltm-api/guides/pumps/testout_pumps/2026-07-12-103637.592-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/pumps/testout_pumps/2026-07-12-103637.592-EMPS-parallell
INFO:InflowHandler:(ikernel) Writing inflow series
INFO:InflowHandler:(ikernel) Writing Forecast for 'after_one_year'
INFO:InflowHandler:(ikernel) Writing Forecast for 'after_one_year'
INFO:InflowHandler:(ikernel) Writing Forecast for 'after_one_year'
INFO:Validator:(ikernel) Model validation succeeded
python pid: 266
INFO:LtmApiModel:(ikernel) Model executed successfully
area: area/pumpekraft¶
area: area/tev¶
area/pumpekraft¶
'Reservoir'
'Reservoir'
'Reservoir'
'Reservoir'
area/tev¶
'Reservoir'
INFO:LtmApiModel:(ikernel) Not deleting output dir (/builds/energy/ltm/pyltmapi/docs/ltm-api/guides/pumps/testout_pumps/2026-07-12-103637.592-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/pumps/testout_pumps/2026-07-12-103637.592-EMPS-parallell), as delete_output_dir: false, and has_generated_output_dir: true