{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Dispatch with Energy Storage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case, we will show the usage of energy storage included dispatch.\n", "\n", "In AMS, ``ESD1`` is an dispatch model for energy storage, which has a corresponding\n", "dynamic model ``ESD1`` in ANDES." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "import ams\n", "\n", "import datetime" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Last run time: 2025-01-27 06:04:56\n", "ams:1.0.1.post0.dev0+g26601dec\n" ] } ], "source": [ "print(\"Last run time:\", datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", "\n", "print(f'ams:{ams.__version__}')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "ams.config_logger(stream_level=20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A small-size PJM 5-bus case with ESD1 is used in this example." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/work/ams/ams/cases/5bus/pjm5bus_uced_esd1.xlsx\"...\n", "Input file parsed in 0.0641 seconds.\n", "Zero line rates detacted in rate_b, rate_c, adjusted to 999.\n", "System set up in 0.0017 seconds.\n" ] } ], "source": [ "sp = ams.load(ams.get_case('5bus/pjm5bus_uced_esd1.xlsx'),\n", " setup=True,\n", " no_output=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The model information can be inspected as follow." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idxunamebusgenSngammapgammaqSOCminSOCmaxSOCinitEnEtaCEtaD
uid
0ESD1_11.0ESD1_11PV_2100.01.01.00.01.00.2100.01.01.0
\n", "
" ], "text/plain": [ " idx u name bus gen Sn gammap gammaq SOCmin SOCmax \\\n", "uid \n", "0 ESD1_1 1.0 ESD1_1 1 PV_2 100.0 1.0 1.0 0.0 1.0 \n", "\n", " SOCinit En EtaC EtaD \n", "uid \n", "0 0.2 100.0 1.0 1.0 " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sp.ESD1.as_df()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`RTEDES` extends RTED to include energy storage.\n", "\n", "Note that mixed integer linear programming (MILP) requires\n", "capable solvers such as Gurobi or CPLEX.\n", "They might require extra installation and have their own license.\n", "\n", "The example here only aims to show the usage of RTEDES.\n", "More details can be found at [CVXPY - Choosing a solver](https://www.cvxpy.org/tutorial/advanced/index.html#choosing-a-solver)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Building system matrices\n", "Parsing OModel for \n", "Evaluating OModel for \n", "Finalizing OModel for \n", " initialized in 0.0170 seconds.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Restricted license - for non-production use only - expires 2026-11-23\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " solved as optimal in 0.0198 seconds, converged in 5 iterations with GUROBI.\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sp.RTEDES.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that, in RTED, the time interval is 5/60 [H] by default, and the\n", "dispatch model has been adjusted accordingly." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Var Value info\n", "0 uce [0.0] ESD1 charging decision\n", "1 ude [1.0] ESD1 discharging decision\n", "2 pce [0.0] ESD1 charging power\n", "3 pde [0.0] ESD1 discharging power\n", "4 SOC [0.2] ESD1 State of Charge\n", "5 SOCinit [0.2] Initial SOC\n" ] } ], "source": [ "RTEDESres = pd.DataFrame()\n", "\n", "items = [sp.RTEDES.uce, sp.RTEDES.ude,\n", " sp.RTEDES.pce, sp.RTEDES.pde,\n", " sp.RTEDES.SOC, sp.RTEDES.SOCinit]\n", "\n", "RTEDESres['Var'] = [item.name for item in items]\n", "RTEDESres['Value'] = [item.v.round(4) for item in items]\n", "RTEDESres['info'] = [item.info for item in items]\n", "\n", "print(RTEDESres)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, multi-period dispatch ``EDES`` and ``UCES`` are also available.\n", "They have 1 [H] time interval by default." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sp.EDES.config.t" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Parsing OModel for \n", "Evaluating OModel for \n", "Finalizing OModel for \n", " initialized in 0.0421 seconds.\n", " solved as optimal in 0.0252 seconds, converged in 4 iterations with GUROBI.\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sp.EDES.run()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Var Value info\n", "0 uce [[0.0, 0.0, 0.0, 0.0]] ESD1 charging decision\n", "1 ude [[1.0, 1.0, 1.0, 1.0]] ESD1 discharging decision\n", "2 pce [[0.0, 0.0, 0.0, 0.0]] ESD1 charging power\n", "3 pde [[0.0, 0.0, 0.0, 0.0]] ESD1 discharging power\n", "4 SOC [[0.2, 0.2, 0.2, 0.2]] ESD1 State of Charge\n", "5 SOCinit [0.2] Initial SOC\n" ] } ], "source": [ "EDESres = pd.DataFrame()\n", "\n", "items = [sp.EDES.uce, sp.EDES.ude,\n", " sp.EDES.pce, sp.EDES.pde,\n", " sp.EDES.SOC, sp.EDES.SOCinit]\n", "\n", "EDESres['Var'] = [item.name for item in items]\n", "EDESres['Value'] = [item.v.round(4) for item in items]\n", "EDESres['info'] = [item.info for item in items]\n", "\n", "print(EDESres)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "All generators are online at initial, make initial guess for commitment.\n", "As initial commitment guess, turn off StaticGen: PV_1\n", "Parsing OModel for \n", "Evaluating OModel for \n", "Finalizing OModel for \n", " initialized in 0.0249 seconds.\n", " solved as optimal in 0.0298 seconds, converged in 4 iterations with GUROBI.\n" ] }, { "data": { "text/plain": [ "True" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sp.UCES.run()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Var Value info\n", "0 uce [[0.0, 0.0, 0.0, 0.0]] ESD1 charging decision\n", "1 ude [[1.0, 1.0, 1.0, 1.0]] ESD1 discharging decision\n", "2 pce [[0.0, 0.0, 0.0, 0.0]] ESD1 charging power\n", "3 pde [[0.0, 0.0, 0.0, 0.0]] ESD1 discharging power\n", "4 SOC [[0.2, 0.2, 0.2, 0.2]] ESD1 State of Charge\n", "5 SOCinit [0.2] Initial SOC\n" ] } ], "source": [ "UCESres = pd.DataFrame()\n", "\n", "items = [sp.UCES.uce, sp.UCES.ude,\n", " sp.UCES.pce, sp.UCES.pde,\n", " sp.UCES.SOC, sp.UCES.SOCinit]\n", "\n", "UCESres['Var'] = [item.name for item in items]\n", "UCESres['Value'] = [item.v.round(4) for item in items]\n", "UCESres['info'] = [item.info for item in items]\n", "\n", "print(UCESres)" ] } ], "metadata": { "kernelspec": { "display_name": "ams-test", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.0" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }