{
"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 a 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": [],
"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": 3,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Parsing input file \"/Users/jinningwang/work/ams/ams/cases/5bus/pjm5bus_demo.xlsx\"...\n",
"Input file parsed in 0.1181 seconds.\n",
"Zero line rates detacted in rate_b, rate_c, adjusted to 999.\n",
"System set up in 0.0028 seconds.\n"
]
}
],
"source": [
"sp = ams.load(ams.get_case('5bus/pjm5bus_demo.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": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" idx | \n",
" u | \n",
" name | \n",
" bus | \n",
" gen | \n",
" Sn | \n",
" gammap | \n",
" gammaq | \n",
" SOCmin | \n",
" SOCmax | \n",
" SOCinit | \n",
" En | \n",
" EtaC | \n",
" EtaD | \n",
"
\n",
" \n",
" | uid | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" ESD1_1 | \n",
" 1.0 | \n",
" ESD1_1 | \n",
" 1 | \n",
" PV_2 | \n",
" 100.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
" 0.0 | \n",
" 1.0 | \n",
" 0.8 | \n",
" 100.0 | \n",
" 1.0 | \n",
" 1.0 | \n",
"
\n",
" \n",
"
\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.8 100.0 1.0 1.0 "
]
},
"execution_count": 4,
"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": 5,
"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.0280 seconds.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Set parameter Username\n",
"Set parameter LicenseID to value 2617183\n",
"Academic license - for non-commercial use only - expires 2026-02-02\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" solved as optimal in 0.0398 seconds, converged in 6 iterations with GUROBI.\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 5,
"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": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Var | \n",
" info | \n",
" Value | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" uce | \n",
" ESD1 charging decision | \n",
" [0.0] | \n",
"
\n",
" \n",
" | 1 | \n",
" ude | \n",
" ESD1 discharging decision | \n",
" [1.0] | \n",
"
\n",
" \n",
" | 2 | \n",
" pce | \n",
" ESD1 charging power | \n",
" [0.0] | \n",
"
\n",
" \n",
" | 3 | \n",
" pde | \n",
" ESD1 discharging power | \n",
" [0.0] | \n",
"
\n",
" \n",
" | 4 | \n",
" SOC | \n",
" ESD1 State of Charge | \n",
" [0.8] | \n",
"
\n",
" \n",
" | 5 | \n",
" SOCinit | \n",
" Initial SOC | \n",
" [0.8] | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Var info Value\n",
"0 uce ESD1 charging decision [0.0]\n",
"1 ude ESD1 discharging decision [1.0]\n",
"2 pce ESD1 charging power [0.0]\n",
"3 pde ESD1 discharging power [0.0]\n",
"4 SOC ESD1 State of Charge [0.8]\n",
"5 SOCinit Initial SOC [0.8]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"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['info'] = [item.info for item in items]\n",
"RTEDESres['Value'] = [item.v.round(4) for item in items]\n",
"\n",
"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": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sp.EDES.config.t"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Parsing OModel for \n",
"Evaluating OModel for \n",
"Finalizing OModel for \n",
" initialized in 0.0314 seconds.\n",
" solved as optimal in 0.0443 seconds, converged in 8 iterations with GUROBI.\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sp.EDES.run()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Var | \n",
" info | \n",
" Value | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" uce | \n",
" ESD1 charging decision | \n",
" [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... | \n",
"
\n",
" \n",
" | 1 | \n",
" ude | \n",
" ESD1 discharging decision | \n",
" [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... | \n",
"
\n",
" \n",
" | 2 | \n",
" pce | \n",
" ESD1 charging power | \n",
" [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... | \n",
"
\n",
" \n",
" | 3 | \n",
" pde | \n",
" ESD1 discharging power | \n",
" [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... | \n",
"
\n",
" \n",
" | 4 | \n",
" SOC | \n",
" ESD1 State of Charge | \n",
" [[0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8,... | \n",
"
\n",
" \n",
" | 5 | \n",
" SOCinit | \n",
" Initial SOC | \n",
" [0.8] | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Var info \\\n",
"0 uce ESD1 charging decision \n",
"1 ude ESD1 discharging decision \n",
"2 pce ESD1 charging power \n",
"3 pde ESD1 discharging power \n",
"4 SOC ESD1 State of Charge \n",
"5 SOCinit Initial SOC \n",
"\n",
" Value \n",
"0 [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... \n",
"1 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n",
"2 [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... \n",
"3 [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... \n",
"4 [[0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8,... \n",
"5 [0.8] "
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"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['info'] = [item.info for item in items]\n",
"EDESres['Value'] = [item.v.round(4) for item in items]\n",
"\n",
"EDESres"
]
},
{
"cell_type": "code",
"execution_count": 10,
"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.0354 seconds.\n",
" solved as optimal in 0.0592 seconds, converged in 5 iterations with GUROBI.\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sp.UCES.run()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Var | \n",
" info | \n",
" Value | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" uce | \n",
" ESD1 charging decision | \n",
" [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... | \n",
"
\n",
" \n",
" | 1 | \n",
" ude | \n",
" ESD1 discharging decision | \n",
" [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... | \n",
"
\n",
" \n",
" | 2 | \n",
" pce | \n",
" ESD1 charging power | \n",
" [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... | \n",
"
\n",
" \n",
" | 3 | \n",
" pde | \n",
" ESD1 discharging power | \n",
" [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... | \n",
"
\n",
" \n",
" | 4 | \n",
" SOC | \n",
" ESD1 State of Charge | \n",
" [[0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8,... | \n",
"
\n",
" \n",
" | 5 | \n",
" SOCinit | \n",
" Initial SOC | \n",
" [0.8] | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Var info \\\n",
"0 uce ESD1 charging decision \n",
"1 ude ESD1 discharging decision \n",
"2 pce ESD1 charging power \n",
"3 pde ESD1 discharging power \n",
"4 SOC ESD1 State of Charge \n",
"5 SOCinit Initial SOC \n",
"\n",
" Value \n",
"0 [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... \n",
"1 [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,... \n",
"2 [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... \n",
"3 [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,... \n",
"4 [[0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8,... \n",
"5 [0.8] "
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"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['info'] = [item.info for item in items]\n",
"UCESres['Value'] = [item.v.round(4) for item in items]\n",
"\n",
"UCESres"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "andesre",
"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
}