You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
UnitCommitment.jl/0.4/tutorials/market/index.html

77 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Market clearing and LMPs · UnitCommitment.jl</title><meta name="title" content="Market clearing and LMPs · UnitCommitment.jl"/><meta property="og:title" content="Market clearing and LMPs · UnitCommitment.jl"/><meta property="twitter:title" content="Market clearing and LMPs · 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>Market clearing and LMPs</a><ul class="internal"><li><a class="tocitem" href="#Computing-Locational-Marginal-Prices"><span>Computing Locational Marginal Prices</span></a></li></ul></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>Market clearing and LMPs</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Market clearing and LMPs</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/market.md" 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="Market-clearing-and-LMPs"><a class="docs-heading-anchor" href="#Market-clearing-and-LMPs">Market clearing and LMPs</a><a id="Market-clearing-and-LMPs-1"></a><a class="docs-heading-anchor-permalink" href="#Market-clearing-and-LMPs" title="Permalink"></a></h1><p>The UC.jl package offers a comprehensive set of functions for solving marketing problems. The primary function, <code>solve_market</code>, facilitates the solution of day-ahead (DA) markets, which can be either deterministic or stochastic in nature. Subsequently, it sequentially maps the commitment status obtained from the DA market to all the real-time (RT) markets, which are deterministic instances. It is essential to ensure that the time span of the DA market encompasses all the RT markets, and the file paths for the RT markets must be specified in chronological order. Each RT market should represent a single time slot, and it is recommended to include a few additional time slots to mitigate the closing window effect.</p><p>The <code>solve_market</code> function accepts several parameters, including the file path (or a list of file paths in the case of stochastic markets) for the DA market, a list of file paths for the RT markets, the market settings specified by the <code>MarketSettings</code> structure, and an optimizer. The <code>MarketSettings</code> structure itself requires three optional arguments: <code>inner_method</code>, <code>lmp_method</code>, and <code>formulation</code>. If the computation of Locational Marginal Prices (LMPs) is not desired, the <code>lmp_method</code> can be set to <code>nothing</code>. Additional optional parameters include a linear programming optimizer for solving LMPs (if a different optimizer than the required one is desired), callback functions <code>after_build_da</code> and <code>after_optimize_da</code>, which are invoked after the construction and optimization of the DA market, and callback functions <code>after_build_rt</code> and <code>after_optimize_rt</code>, which are invoked after the construction and optimization of each RT market. It is crucial to note that the <code>after_build</code> function requires its two arguments to consistently correspond to <code>model</code> and <code>instance</code>, while the <code>after_optimize</code> function requires its three arguments to consistently correspond to <code>solution</code>, <code>model</code>, and <code>instance</code>.</p><p>As an illustrative example, suppose the DA market predicts hourly data for a 24-hour period, while the RT markets represent 5-minute intervals. In this scenario, each RT market file corresponds to a specific 5-minute interval, with the first RT market representing the initial 5 minutes, the second RT market representing the subsequent 5 minutes, and so on. Consequently, there should be 12 RT market files for each hour. To mitigate the closing window effect, except for the last few RT markets, each RT market should contain three time slots, resulting in a total time span of 15 minutes. However, only the first time slot is considered in the final solution. The last two RT markets should only contain 2 and 1 time slot(s), respectively, to ensure that the total time covered by all RT markets does not exceed the time span of the DA market. The code snippet below demonstrates a simplified example of how to utilize the <code>solve_market</code> function. Please note that it only serves as a simplified example and may require further customization based on the specific requirements of your use case.</p><pre><code class="language-julia hljs">using UnitCommitment, Cbc, HiGHS
import UnitCommitment:
MarketSettings,
XavQiuWanThi2019,
ConventionalLMP,
Formulation
solution = UnitCommitment.solve_market(
&quot;da_instance.json&quot;,
[&quot;rt_instance_1.json&quot;, &quot;rt_instance_2.json&quot;, &quot;rt_instance_3.json&quot;],
MarketSettings(
inner_method = XavQiuWanThi2019.Method(),
lmp_method = ConventionalLMP(),
formulation = Formulation(),
),
optimizer = Cbc.Optimizer,
lp_optimizer = HiGHS.Optimizer,
)</code></pre><h2 id="Computing-Locational-Marginal-Prices"><a class="docs-heading-anchor" href="#Computing-Locational-Marginal-Prices">Computing Locational Marginal Prices</a><a id="Computing-Locational-Marginal-Prices-1"></a><a class="docs-heading-anchor-permalink" href="#Computing-Locational-Marginal-Prices" title="Permalink"></a></h2><p>Locational marginal prices (LMPs) refer to the cost of supplying electricity at a particular location of the network. Multiple methods for computing LMPs have been proposed in the literature. UnitCommitment.jl implements two commonly-used methods: conventional LMPs and Approximated Extended LMPs (AELMPs). To compute LMPs for a given unit commitment instance, the <code>compute_lmp</code> function can be used, as shown in the examples below. The function accepts three arguments a solved SCUC model, an LMP method, and a linear optimizer and it returns a dictionary mapping <code>(bus_name, time)</code> to the marginal price.</p><div class="admonition is-warning"><header class="admonition-header">Warning</header><div class="admonition-body"><p>Most mixed-integer linear optimizers, such as <code>HiGHS</code>, <code>Gurobi</code> and <code>CPLEX</code> can be used with <code>compute_lmp</code>, with the notable exception of <code>Cbc</code>, which does not support dual value evaluations. If using <code>Cbc</code>, please provide <code>Clp</code> as the linear optimizer.</p></div></div><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>LMPs are conventionally computed by: (1) solving the SCUC model, (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 dual variables&#39; values associated with the net injection constraints. The example below shows how to compute conventional LMPs for a given unit commitment instance. First, we build and optimize the SCUC model. Then, we call the <code>compute_lmp</code> function, providing as the second argument <code>ConventionalLMP()</code>.</p><pre><code class="language-julia hljs">using UnitCommitment
using HiGHS
import UnitCommitment: ConventionalLMP
# Read benchmark instance
instance = UnitCommitment.read_benchmark(&quot;matpower/case118/2018-01-01&quot;)
# Build the model
model = UnitCommitment.build_model(
instance = instance,
optimizer = HiGHS.Optimizer,
)
# Optimize the model
UnitCommitment.optimize!(model)
# Compute the LMPs using the conventional method
lmp = UnitCommitment.compute_lmp(
model,
ConventionalLMP(),
optimizer = HiGHS.Optimizer,
)
# Access the LMPs
# Example: &quot;s1&quot; is the scenario name, &quot;b1&quot; is the bus name, 1 is the first time slot
@show lmp[&quot;s1&quot;,&quot;b1&quot;, 1]</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>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 approximation 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. The method does not support multiple scenarios. 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">using UnitCommitment
using HiGHS
import UnitCommitment: AELMP
# Read benchmark instance
instance = UnitCommitment.read_benchmark(&quot;matpower/case118/2017-02-01&quot;)
# Build the model
model = UnitCommitment.build_model(
instance = instance,
optimizer = HiGHS.Optimizer,
)
# Optimize the model
UnitCommitment.optimize!(model)
# Compute the AELMPs
aelmp = UnitCommitment.compute_lmp(
model,
AELMP(
allow_offline_participation = false,
consider_startup_costs = true
),
optimizer = HiGHS.Optimizer
)
# Access the AELMPs
# Example: &quot;s1&quot; is the scenario name, &quot;b1&quot; is the bus name, 1 is the first time slot
# Note: although scenario is supported, the query still keeps the scenario keys for consistency.
@show aelmp[&quot;s1&quot;, &quot;b1&quot;, 1]</code></pre></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../customizing/">« Model customization</a><a class="docs-footer-nextpage" href="../decomposition/">Decomposition methods »</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="Thursday 9 May 2024 13:50">Thursday 9 May 2024</span>. Using Julia version 1.10.3.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>