|
|
<!DOCTYPE html>
|
|
|
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Locational Marginal Prices · UnitCommitment.jl</title><meta name="title" content="Locational Marginal Prices · UnitCommitment.jl"/><meta property="og:title" content="Locational Marginal Prices · UnitCommitment.jl"/><meta property="twitter:title" content="Locational Marginal Prices · UnitCommitment.jl"/><meta name="description" content="Documentation for UnitCommitment.jl."/><meta property="og:description" content="Documentation for UnitCommitment.jl."/><meta property="twitter:description" content="Documentation for UnitCommitment.jl."/><script data-outdated-warner src="../../assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.050/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL="../.."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="../../assets/documenter.js"></script><script src="../../search_index.js"></script><script src="../../siteinfo.js"></script><script src="../../../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../../assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../../assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="../../assets/themeswap.js"></script><link href="../../assets/custom.css" rel="stylesheet" type="text/css"/></head><body><div id="documenter"><nav class="docs-sidebar"><div class="docs-package-name"><span class="docs-autofit"><a href="../../">UnitCommitment.jl</a></span></div><button class="docs-search-query input is-rounded is-small is-clickable my-2 mx-auto py-1 px-2" id="documenter-search-query">Search docs (Ctrl + /)</button><ul class="docs-menu"><li><a class="tocitem" href="../../">Home</a></li><li><span class="tocitem">Tutorials</span><ul><li><a class="tocitem" href="../usage/">Getting started</a></li><li><a class="tocitem" href="../customizing/">Model customization</a></li><li class="is-active"><a class="tocitem" href>Locational Marginal Prices</a></li><li><a class="tocitem" href="../market/">Market Clearing</a></li><li><a class="tocitem" href="../decomposition/">Decomposition methods</a></li></ul></li><li><span class="tocitem">User guide</span><ul><li><a class="tocitem" href="../../guides/problem/">Problem definition</a></li><li><a class="tocitem" href="../../guides/format/">JSON data format</a></li><li><a class="tocitem" href="../../guides/instances/">Benchmark instances</a></li></ul></li><li><a class="tocitem" href="../../api/">API Reference</a></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><a class="docs-sidebar-button docs-navbar-link fa-solid fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a><nav class="breadcrumb"><ul class="is-hidden-mobile"><li><a class="is-disabled">Tutorials</a></li><li class="is-active"><a href>Locational Marginal Prices</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Locational Marginal Prices</a></li></ul></nav><div class="docs-right"><a class="docs-navbar-link" href="https://github.com/ANL-CEEESA/UnitCommitment.jl" title="View the repository on GitHub"><span class="docs-icon fa-brands"></span><span class="docs-label is-hidden-touch">GitHub</span></a><a class="docs-navbar-link" href="https://github.com/ANL-CEEESA/UnitCommitment.jl/blob/dev/docs/src/tutorials/lmp.jl" title="Edit source on GitHub"><span class="docs-icon fa-solid"></span></a><a class="docs-settings-button docs-navbar-link fa-solid fa-gear" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-article-toggle-button fa-solid fa-chevron-up" id="documenter-article-toggle-button" href="javascript:;" title="Collapse all docstrings"></a></div></header><article class="content" id="documenter-page"><h1 id="Locational-Marginal-Prices"><a class="docs-heading-anchor" href="#Locational-Marginal-Prices">Locational Marginal Prices</a><a id="Locational-Marginal-Prices-1"></a><a class="docs-heading-anchor-permalink" href="#Locational-Marginal-Prices" title="Permalink"></a></h1><p>Locational Marginal Prices (LMPs) refer to the cost of supplying electricity at specific locations of the network. LMPs are crucial for the operation of electricity markets and have many other applications, such as indicating what areas of the network may require additional generation or transmission capacity. UnitCommitment.jl implements two methods for calculating LMPS: Conventional LMPs and Approximated Extended LMPs (AELMPs). In this tutorial, we introduce each method and illustrate their usage.</p><h3 id="Conventional-LMPs"><a class="docs-heading-anchor" href="#Conventional-LMPs">Conventional LMPs</a><a id="Conventional-LMPs-1"></a><a class="docs-heading-anchor-permalink" href="#Conventional-LMPs" title="Permalink"></a></h3><p>Conventional LMPs work by (1) solving the original SCUC problem, (2) fixing all binary variables to their optimal values, and (3) re-solving the resulting linear programming model. In this approach, the LMPs are defined as the values of the dual variables associated with the net injection constraints.</p><p>The first step to use this method is to load and optimize an instance, as explained in previous tutorials:</p><pre><code class="language-julia hljs">using UnitCommitment
|
|
|
using HiGHS
|
|
|
|
|
|
instance = UnitCommitment.read_benchmark("matpower/case14/2017-01-01")
|
|
|
model =
|
|
|
UnitCommitment.build_model(instance = instance, optimizer = HiGHS.Optimizer)
|
|
|
UnitCommitment.optimize!(model)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi"><span class="sgr36"><span class="sgr1">[ Info: </span></span>Building model...
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Building scenario s1 with probability 1.0
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Computing injection shift factors...
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Computed ISF in 0.00 seconds
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Computing line outage factors...
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Computed LODF in 0.00 seconds
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Applying PTDF and LODF cutoffs (0.00500, 0.00100)
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Built model in 0.01 seconds
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Setting MILP time limit to 86400.00 seconds
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Solving MILP...
|
|
|
Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms
|
|
|
Presolving model
|
|
|
4382 rows, 2704 cols, 14776 nonzeros
|
|
|
3279 rows, 2195 cols, 11913 nonzeros
|
|
|
3160 rows, 2085 cols, 12983 nonzeros
|
|
|
|
|
|
Solving MIP model with:
|
|
|
3160 rows
|
|
|
2085 cols (865 binary, 0 integer, 0 implied int., 1220 continuous)
|
|
|
12983 nonzeros
|
|
|
|
|
|
Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work
|
|
|
Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time
|
|
|
|
|
|
0 0 0 0.00% 1.86264515e-09 inf inf 0 0 0 0 0.0s
|
|
|
R 0 0 0 0.00% 360642.328869 360642.544974 0.00% 0 0 0 861 0.0s
|
|
|
|
|
|
Solving report
|
|
|
Status Optimal
|
|
|
Primal bound 360642.544974
|
|
|
Dual bound 360642.328869
|
|
|
Gap 6e-05% (tolerance: 0.01%)
|
|
|
Solution status feasible
|
|
|
360642.544974 (objective)
|
|
|
0 (bound viol.)
|
|
|
0 (int. viol.)
|
|
|
0 (row viol.)
|
|
|
Timing 0.05 (total)
|
|
|
0.03 (presolve)
|
|
|
0.00 (postsolve)
|
|
|
Nodes 1
|
|
|
LP iterations 861 (total)
|
|
|
0 (strong br.)
|
|
|
0 (separation)
|
|
|
0 (heuristics)
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Verifying transmission limits...
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>Verified transmission limits in 0.00 seconds
|
|
|
<span class="sgr36"><span class="sgr1">[ Info: </span></span>No violations found</code></pre><p>Next, we call <code>UnitCommitment.compute_lmp</code>, as shown below. The function accepts three arguments – a solved SCUC model, the LMP method, and a linear optimizer – and it returns a dictionary mapping <code>(scenario_name, bus_name, time)</code> to the marginal price.</p><pre><code class="language-julia hljs">lmp = UnitCommitment.compute_lmp(
|
|
|
model,
|
|
|
UnitCommitment.ConventionalLMP(),
|
|
|
optimizer = HiGHS.Optimizer,
|
|
|
)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">OrderedCollections.OrderedDict{Tuple{String, String, Int64}, Float64} with 504 entries:
|
|
|
("s1", "b1", 1) => 44.4253
|
|
|
("s1", "b2", 1) => 44.4253
|
|
|
("s1", "b3", 1) => 44.4253
|
|
|
("s1", "b4", 1) => 44.4253
|
|
|
("s1", "b5", 1) => 44.4253
|
|
|
("s1", "b6", 1) => 44.4253
|
|
|
("s1", "b7", 1) => 44.4253
|
|
|
("s1", "b8", 1) => 44.4253
|
|
|
("s1", "b9", 1) => 44.4253
|
|
|
("s1", "b10", 1) => 44.4253
|
|
|
("s1", "b11", 1) => 44.4253
|
|
|
("s1", "b12", 1) => 44.4253
|
|
|
("s1", "b13", 1) => 44.4253
|
|
|
("s1", "b14", 1) => 44.4253
|
|
|
("s1", "b1", 2) => 44.4253
|
|
|
("s1", "b2", 2) => 44.4253
|
|
|
("s1", "b3", 2) => 44.4253
|
|
|
("s1", "b4", 2) => 44.4253
|
|
|
("s1", "b5", 2) => 44.4253
|
|
|
⋮ => ⋮</code></pre><p>For example, the following code queries the LMP of bus <code>b1</code> in scenario <code>s1</code> at time 1:</p><pre><code class="language-julia hljs">@show lmp["s1", "b1", 1]</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">44.425275404366815</code></pre><h3 id="Approximate-Extended-LMPs"><a class="docs-heading-anchor" href="#Approximate-Extended-LMPs">Approximate Extended LMPs</a><a id="Approximate-Extended-LMPs-1"></a><a class="docs-heading-anchor-permalink" href="#Approximate-Extended-LMPs" title="Permalink"></a></h3><p>Approximate Extended LMPs (AELMPs) are an alternative method to calculate locational marginal prices which attemps to minimize uplift payments. The method internally works by modifying the instance data in three ways: (1) it sets the minimum power output of each generator to zero, (2) it averages the start-up cost over the offer blocks for each generator, and (3) it relaxes all integrality constraints. To compute AELMPs, as shown in the example below, we call <code>compute_lmp</code> and provide <code>UnitCommitment.AELMP()</code> as the second argument.</p><p>This method has two configurable parameters: <code>allow_offline_participation</code> and <code>consider_startup_costs</code>. If <code>allow_offline_participation = true</code>, then offline generators are allowed to participate in the pricing. If instead <code>allow_offline_participation = false</code>, offline generators are not allowed and therefore are excluded from the system. A solved UC model is optional if offline participation is allowed, but is required if not allowed. The method forces offline participation to be allowed if the UC model supplied by the user is not solved. For the second field, If <code>consider_startup_costs = true</code>, then start-up costs are integrated and averaged over each unit production; otherwise the production costs stay the same. By default, both fields are set to <code>true</code>.</p><div class="admonition is-warning"><header class="admonition-header">Warning</header><div class="admonition-body"><p>This method is still under active research, and has several limitations. The implementation provided in the package is based on MISO Phase I only. It only supports fast start resources. More specifically, the minimum up/down time of all generators must be 1, the initial power of all generators must be 0, and the initial status of all generators must be negative. The method does not support time-varying start-up costs, and only currently works for deterministic instances. If offline participation is not allowed, AELMPs treats an asset to be offline if it is never on throughout all time periods.</p></div></div><pre><code class="language-julia hljs">instance = UnitCommitment.read_benchmark("test/aelmp_simple")
|
|
|
|
|
|
model =
|
|
|
UnitCommitment.build_model(instance = instance, optimizer = HiGHS.Optimizer)
|
|
|
|
|
|
UnitCommitment.optimize!(model)
|
|
|
|
|
|
lmp = UnitCommitment.compute_lmp(
|
|
|
model,
|
|
|
UnitCommitment.AELMP(
|
|
|
allow_offline_participation = false,
|
|
|
consider_startup_costs = true,
|
|
|
),
|
|
|
optimizer = HiGHS.Optimizer,
|
|
|
)
|
|
|
|
|
|
@show lmp["s1", "B1", 1]</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">274.3333333333333</code></pre></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../customizing/">« Model customization</a><a class="docs-footer-nextpage" href="../market/">Market Clearing »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="auto">Automatic (OS)</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.2.1 on <span class="colophon-date" title="Tuesday 21 May 2024 10:28">Tuesday 21 May 2024</span>. Using Julia version 1.10.3.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|