diff --git a/tutorial-1/sheet01.tex b/tutorial-1/sheet01.tex index 60450927f3345fbe65c9c47fa4f5ab3a5d1880ef..b54accc6416ba2e24392ab1c285855844bdae163 100755 --- a/tutorial-1/sheet01.tex +++ b/tutorial-1/sheet01.tex @@ -69,11 +69,11 @@ \begin{document} \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Tutorial I: Time Series Analysis}}\\ - \small Will be worked on in the exercise session on Wednesday, 11 July 2018.\1.5em] + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Tutorial I: Time Series Analysis}}\\ + \small Will be worked on in the exercise session on Wednesday, 11 July 2018.\\[1.5em] \end{center} \vspace{1em} @@ -90,30 +90,30 @@ page\footnote{\url{https://nworbmot.org/courses/complex_renewable_energy_network They describe (quasi-real) time series for wind power generation $$W(t)$$, solar power generation $$S(t)$$ and load $$L(t)$$ in Great Britain (GB), Germany (DE) and Europe (EU). The time step is $$1\e{h}$$ and the time series are several years long. \begin{enumerate}[(a)] -\item Check that the wind and solar time series are normalized to 'per-unit of installed \mbox{capacity}', and that the load time series is normalized to MW. -\item For all three regions, calculate the maximum, mean, and variance of the time series. -\item For all three regions, plot the time series $$W(t)$$, - $$S(t)$$, - $$L(t)$$ for a winter month (January) and a summer month (July). -\item For all three regions, plot the duration curve for $$W(t)$$, $$S(t)$$, $$L(t)$$. -\item For all three regions, plot the probability density function of $$W(t)$$, $$S(t)$$, $$L(t)$$. -\item Apply a (Fast) Fourier Transform to the the three time series X \in W(t), S(t), L(t): -\begin{equation*} - \tilde{X}(\omega) = \int_0^T X(t) e^{\i \omega t} \,\ud t \, . -\end{equation*} -For all three regions, plot the energy spectrum -\left| \tilde{\Delta}(\omega) \right|^2 as a function of -\omega. Discuss the relationship of these results with the -findings obtained in (b)-(e). -\item Normalize the time series to one, so that $$\expect{W} = \expect{S} = \expect{L} = 1$$. -Now, for all three regions, plot the mismatch time series - \begin{equation*} - \Delta(t) = \gamma \alpha W(t) + \gamma (1 - \alpha) S(t) - L(t) - \end{equation*} - for the same winter and summer months as in (c). Choose - $$\alpha \in \{0.0, 0.5, 0.75, 1.0\}$$ with $$\gamma = 1$$, - and \gamma \in \{0.5, 0.75, 1.0, 1.25, 1.5\}  with \alpha = 0.75. -\item For all three regions, repeat (b)-(f) for the mismatch time series. + \item Check that the wind and solar time series are normalized to 'per-unit of installed \mbox{capacity}', and that the load time series is normalized to MW. + \item For all three regions, calculate the maximum, mean, and variance of the time series. + \item For all three regions, plot the time series $$W(t)$$, + $$S(t)$$, + $$L(t)$$ for a winter month (January) and a summer month (July). + \item For all three regions, plot the duration curve for $$W(t)$$, $$S(t)$$, $$L(t)$$. + \item For all three regions, plot the probability density function of $$W(t)$$, $$S(t)$$, $$L(t)$$. + \item Apply a (Fast) Fourier Transform to the the three time series X \in W(t), S(t), L(t): + \begin{equation*} + \tilde{X}(\omega) = \int_0^T X(t) e^{\i \omega t} \,\ud t \, . + \end{equation*} + For all three regions, plot the energy spectrum + \left| \tilde{\Delta}(\omega) \right|^2 as a function of + \omega. Discuss the relationship of these results with the + findings obtained in (b)-(e). + \item Normalize the time series to one, so that $$\expect{W} = \expect{S} = \expect{L} = 1$$. + Now, for all three regions, plot the mismatch time series + \begin{equation*} + \Delta(t) = \gamma \alpha W(t) + \gamma (1 - \alpha) S(t) - L(t) + \end{equation*} + for the same winter and summer months as in (c). Choose + $$\alpha \in \{0.0, 0.5, 0.75, 1.0\}$$ with $$\gamma = 1$$, + and \gamma \in \{0.5, 0.75, 1.0, 1.25, 1.5\}  with \alpha = 0.75. + \item For all three regions, repeat (b)-(f) for the mismatch time series. \end{enumerate} \pagebreak @@ -122,62 +122,62 @@ Now, for all three regions, plot the mismatch time series %===================================================================== \begin{wrapfigure}[11]{r}{0pt} - \begin{tikzpicture} - \begin{axis}[ - domain=0:1, no markers, samples=200 - % xlabel = x, ylabel = f(x) - ] - \addplot+[dashed] {1 + 0.4 * cos(deg(2*pi*x))}; \label{figref:w} - \addplot+[densely dotted] {1 - 0.75 * cos(deg(2*pi*x))}; \label{figref:s} - \addplot+[solid] {1 + 0.1 * cos(deg(2*pi*x))}; \label{figref:l} - \addplot+[dotted] {1}; \label{figref:1} - \end{axis} - \end{tikzpicture} - \caption{Seasonal variations of wind and solar power generation - $$W(t)$$ - \autoref{figref:w} and $$S(t)$$ - \autoref{figref:s}, and load $$L(t)$$ - \autoref{figref:l} around the mean $$1$$ \ref{figref:1}.} - \label{fig:seasonalvariations} + \begin{tikzpicture} + \begin{axis}[ + domain=0:1, no markers, samples=200 + % xlabel = x, ylabel = f(x) + ] + \addplot+[dashed] {1 + 0.4 * cos(deg(2*pi*x))}; \label{figref:w} + \addplot+[densely dotted] {1 - 0.75 * cos(deg(2*pi*x))}; \label{figref:s} + \addplot+[solid] {1 + 0.1 * cos(deg(2*pi*x))}; \label{figref:l} + \addplot+[dotted] {1}; \label{figref:1} + \end{axis} + \end{tikzpicture} + \caption{Seasonal variations of wind and solar power generation + $$W(t)$$ + \autoref{figref:w} and $$S(t)$$ + \autoref{figref:s}, and load $$L(t)$$ + \autoref{figref:l} around the mean $$1$$ \ref{figref:1}.} + \label{fig:seasonalvariations} \end{wrapfigure} Figure \ref{fig:seasonalvariations} shows approximations to the seasonal variations of wind and solar power generation $$W(t)$$ and $$S(t)$$ and load $$L(t)$$: \begin{align*} -W(t) & = 1 + A_W \cos \omega t \\ -S(t) & = 1 - A_S \cos \omega t \\ -L(t) & = 1 + A_L \cos \omega t + W(t) & = 1 + A_W \cos \omega t \\ + S(t) & = 1 - A_S \cos \omega t \\ + L(t) & = 1 + A_L \cos \omega t \end{align*} The time series are normalized to $$\expect{W} = \expect{S} = \expect{L} := \frac{1}{T} \int_0^T L(t) \ud t = 1$$, and the constants have the values \begin{align*} -\omega & = \frac{2\pi}{T} & T & = 1 \e{year} \\ -A_W & = 0.4 & A_S & = 0.75 & A_L & = 0.1 + \omega & = \frac{2\pi}{T} & T & = 1 \e{year} \\ + A_W & = 0.4 & A_S & = 0.75 & A_L & = 0.1 \end{align*} ~\\ \begin{enumerate}[(a)] - \item What is the seasonal optimal mix $$\alpha$$, which minimizes - \begin{equation*} - \expect{\left[ \alpha W(\cdot) + (1-\alpha) S(\cdot) - L(\cdot) \right]^2} = \frac1T \int_0^T \left[ \alpha W(t) + (1-\alpha) S(t) - L(t) \right]^2 \,\mathrm d t - , - \end{equation*} - \item How does the optimal mix change if we replace $$A_L \to -A_L$$? - \item Now assume that there is a seasonal shift in the wind signal - \begin{equation*} - W(t) = 1 + A_W \cos \left( \omega t - \phi \right) - . - \end{equation*} - Express the optimal mix $$\alpha$$ as a function of $$\phi$$. - \item A constant conventional power source $$C(t) = 1 - \gamma$$ is now introduced. The mismatch then becomes - $$- \Delta(t) = \gamma \left[ \alpha W(t) + (1-\alpha) S(t) \right] + C(t) - L(t) - . -$$ - Analogously to (a), find the optimal mix $$\alpha$$ as a function of $$0 \leq \gamma \leq 1$$, which minimizes $$\expect{\Delta^2}$$. + \item What is the seasonal optimal mix $$\alpha$$, which minimizes + \begin{equation*} + \expect{\left[ \alpha W(\cdot) + (1-\alpha) S(\cdot) - L(\cdot) \right]^2} = \frac1T \int_0^T \left[ \alpha W(t) + (1-\alpha) S(t) - L(t) \right]^2 \,\mathrm d t + , + \end{equation*} + \item How does the optimal mix change if we replace $$A_L \to -A_L$$? + \item Now assume that there is a seasonal shift in the wind signal + \begin{equation*} + W(t) = 1 + A_W \cos \left( \omega t - \phi \right) + . + \end{equation*} + Express the optimal mix $$\alpha$$ as a function of $$\phi$$. + \item A constant conventional power source $$C(t) = 1 - \gamma$$ is now introduced. The mismatch then becomes + $$+ \Delta(t) = \gamma \left[ \alpha W(t) + (1-\alpha) S(t) \right] + C(t) - L(t) + . +$$ + Analogously to (a), find the optimal mix $$\alpha$$ as a function of $$0 \leq \gamma \leq 1$$, which minimizes $$\expect{\Delta^2}$$. \end{enumerate} \pagebreak @@ -188,21 +188,21 @@ A_W & = 0.4 & A_S & = 0.75 & A_L & = 0.1 I found the python notebook based notes of Robert Johansson to be a comprehensive kick starter\footnote{\url{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/tree/master/}}. \begin{itemize} -\item - \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-0-Scientific-Computing-with-Python.ipynb}{Lecture~0} covers installation and getting ready. -\item - \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-1-Introduction-to-Python-Programming.ipynb}{Lecture~1} - zooms through most basic general python control structures (only - brush over it and stop reading early, i.e. if you read the word - \verb+classes+ you already know too much). -\item \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-2-Numpy.ipynb}{Lecture~2} is the most important and closely connected to the exercises. -\item You might as well stop now, but if you \emph{are} hooked, I recommend \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-3-Scipy.ipynb}{Lecture~3} for more physics and \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-4-Matplotlib.ipynb}{Lecture~4} for prettier graphs. + \item + \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-0-Scientific-Computing-with-Python.ipynb}{Lecture~0} covers installation and getting ready. + \item + \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-1-Introduction-to-Python-Programming.ipynb}{Lecture~1} + zooms through most basic general python control structures (only + brush over it and stop reading early, i.e. if you read the word + \verb+classes+ you already know too much). + \item \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-2-Numpy.ipynb}{Lecture~2} is the most important and closely connected to the exercises. + \item You might as well stop now, but if you \emph{are} hooked, I recommend \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-3-Scipy.ipynb}{Lecture~3} for more physics and \href{http://nbviewer.jupyter.org/github/jrjohansson/scientific-python-lectures/blob/master/Lecture-4-Matplotlib.ipynb}{Lecture~4} for prettier graphs. \end{itemize} Further reference material of help is: \begin{itemize} -\item The website-books \url{http://python-course.eu/} (english), \url{http://python-kurs.eu/} (german); especially if you only \emph{very} quickly skim over the \href{http://www.python-course.eu/course.php}{python2 tutorial} and switch over to the \href{http://www.python-course.eu/numerical_programming.php}{numerical python} stuff early; especially of interest might be the \href{http://www.python-course.eu/pandas.php}{pandas} bit in the end, which will make the exercises a breeze at the expense of yet another package to learn. -\item the exhaustive (overly so) official python tutorial\footnote{\url{https://docs.python.org/2/tutorial/}} available in \href{https://docs.python.org/2/tutorial/}{english} and \href{https://py-tutorial-de.readthedocs.org/de/python-3.3/index.html}{german}; which will NOT introduce you to numpy or scipy. + \item The website-books \url{http://python-course.eu/} (english), \url{http://python-kurs.eu/} (german); especially if you only \emph{very} quickly skim over the \href{http://www.python-course.eu/course.php}{python2 tutorial} and switch over to the \href{http://www.python-course.eu/numerical_programming.php}{numerical python} stuff early; especially of interest might be the \href{http://www.python-course.eu/pandas.php}{pandas} bit in the end, which will make the exercises a breeze at the expense of yet another package to learn. + \item the exhaustive (overly so) official python tutorial\footnote{\url{https://docs.python.org/2/tutorial/}} available in \href{https://docs.python.org/2/tutorial/}{english} and \href{https://py-tutorial-de.readthedocs.org/de/python-3.3/index.html}{german}; which will NOT introduce you to numpy or scipy. \end{itemize} diff --git a/tutorial-2/sheet02.tex b/tutorial-2/sheet02.tex index 3c91cae3cc1de5dcbcab582da8e5d54cda0ec03f..1c37041041999742d3fc9747294c176e2561013c 100755 --- a/tutorial-2/sheet02.tex +++ b/tutorial-2/sheet02.tex @@ -71,11 +71,11 @@ \begin{document} \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Tutorial II: Network Theory and Power Flow}}\\ - \small Will be worked on in the exercise session on Friday, 13 July 2018.\\[1.5em] + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Tutorial II: Network Theory and Power Flow}}\\ + \small Will be worked on in the exercise session on Friday, 13 July 2018.\\[1.5em] \end{center} @@ -86,34 +86,34 @@ %===================================================================== \begin{wrapfigure}[10]{r}{0pt} - \centering - \begin{tikzpicture} - [scale=.81,auto=left,every node/.style={circle,fill=gray!20}] - \node (n0) at (2,14) {0}; - \node (n1) at (2,8) {1}; - \node (n2) at (0,4) {2}; - \node (n3) at (3,0) {3}; - \node (n4) at (4,4) {4}; - \node (n5) at (5,7) {5}; - \foreach \from/\to in {n0/n1,n1/n2,n1/n4,n1/n5,n2/n4,n2/n3,n3/n4,n4/n5} - \draw (\from) -- (\to); - \end{tikzpicture} - \caption{Simple Network} - \label{fig:network} + \centering + \begin{tikzpicture} + [scale=.81,auto=left,every node/.style={circle,fill=gray!20}] + \node (n0) at (2,14) {0}; + \node (n1) at (2,8) {1}; + \node (n2) at (0,4) {2}; + \node (n3) at (3,0) {3}; + \node (n4) at (4,4) {4}; + \node (n5) at (5,7) {5}; + \foreach \from/\to in {n0/n1,n1/n2,n1/n4,n1/n5,n2/n4,n2/n3,n3/n4,n4/n5} + \draw (\from) -- (\to); + \end{tikzpicture} + \caption{Simple Network} + \label{fig:network} \end{wrapfigure} Consider the simple network shown ins Figure \ref{fig:network}. Calculate in Python or by hand: \begin{enumerate}[(a)] - \item Compile the \textit{nodes list} and the \textit{edge list}.\\~\\ - \textbf{Remark:} While graph-theoretically both lists are unordered sets, let's agree on an ordering now which can serve as basis for the matrices in the following exercises: we sort everything in ascending numerical order, i.e.\ node 1 before node 2 and edge (1,2) before (1,4) before (2,3). - \item Determine the \textit{order} and the \textit{size} of the network. - \item Compute the\textit{ adjacency matrix} A and check that it is symmetric. - \item Find the \textit{degree} k_n of each node n and compute the \textit{average degree} of the network. - \item Determine the \textit{incidence matrix} K by assuming the links are always directed from smaller-numbered node to larger-numbered node, i.e.\ from node 2 to node 3, instead of from 3 to 2. - \item Compute the \textit{Laplacian} L of the network using k_n and A. Remember that the Laplacian can also be computed as L=KK^T and check that the two definitions agree. - \item Find the \textit{diameter} of the network by looking at Figure \ref{fig:network}. + \item Compile the \textit{nodes list} and the \textit{edge list}.\\~\\ + \textbf{Remark:} While graph-theoretically both lists are unordered sets, let's agree on an ordering now which can serve as basis for the matrices in the following exercises: we sort everything in ascending numerical order, i.e.\ node 1 before node 2 and edge (1,2) before (1,4) before (2,3). + \item Determine the \textit{order} and the \textit{size} of the network. + \item Compute the\textit{ adjacency matrix} A and check that it is symmetric. + \item Find the \textit{degree} k_n of each node n and compute the \textit{average degree} of the network. + \item Determine the \textit{incidence matrix} K by assuming the links are always directed from smaller-numbered node to larger-numbered node, i.e.\ from node 2 to node 3, instead of from 3 to 2. + \item Compute the \textit{Laplacian} L of the network using k_n and A. Remember that the Laplacian can also be computed as L=KK^T and check that the two definitions agree. + \item Find the \textit{diameter} of the network by looking at Figure \ref{fig:network}. \end{enumerate} @@ -128,32 +128,32 @@ If you map the nodes to countries like \texttt{0=DK, 1=DE, 2=CH, 3=IT, 4=AT,5=CZ The linear power flow is given by $$- p_i = \sum_j \tilde{L}_{i,j}\theta_j \qquad \text{and} \qquad f_l = \frac{1}{x_l} \sum_i K_{i,l}\theta_i, \qquad \text{where} \qquad \tilde{L}_{i,j}= \sum_l = K_{i,l}\frac{1}{x_l} K_{j,l} + p_i = \sum_j \tilde{L}_{i,j}\theta_j \qquad \text{and} \qquad f_l = \frac{1}{x_l} \sum_i K_{i,l}\theta_i, \qquad \text{where} \qquad \tilde{L}_{i,j}= \sum_l = K_{i,l}\frac{1}{x_l} K_{j,l}$$ is the weighted Laplacian. For simplicity, we assume identity reactance on all links x_l = 1. \begin{enumerate}[(a)] - \item Compute the \textit{voltage angles }\theta_j and \textit{flows} f_l for the first hour in the dataset with the convention of \theta_0 = 0; i.e.\ the slack bus is at node 0.\\~\\ - \textbf{Remark:} Linear equation systems are solved efficiently using \texttt{numpy.linalg.solve}. - \item Determine the average flow on each link for 01-2017 and draw it as a directed network. - + \item Compute the \textit{voltage angles }\theta_j and \textit{flows} f_l for the first hour in the dataset with the convention of \theta_0 = 0; i.e.\ the slack bus is at node 0.\\~\\ + \textbf{Remark:} Linear equation systems are solved efficiently using \texttt{numpy.linalg.solve}. + \item Determine the average flow on each link for 01-2017 and draw it as a directed network. + \end{enumerate} \begin{figure}[h] - \centering - \begin{tikzpicture} - [scale=.7,auto=left,every node/.style={circle,fill=gray!20}] - \node (n0) at (2,14) {DK}; - \node (n1) at (2,8) {DE}; - \node (n2) at (0,4) {CH}; - \node (n3) at (3,0) {IT}; - \node (n4) at (4,4) {AT}; - \node (n5) at (5,7) {CZ}; - \foreach \from/\to in {n0/n1,n1/n2,n1/n4,n1/n5,n2/n4,n2/n3,n3/n4,n4/n5} - \draw (\from) -- (\to); - \end{tikzpicture} - \caption{Simple Network} - \label{fig:network} + \centering + \begin{tikzpicture} + [scale=.7,auto=left,every node/.style={circle,fill=gray!20}] + \node (n0) at (2,14) {DK}; + \node (n1) at (2,8) {DE}; + \node (n2) at (0,4) {CH}; + \node (n3) at (3,0) {IT}; + \node (n4) at (4,4) {AT}; + \node (n5) at (5,7) {CZ}; + \foreach \from/\to in {n0/n1,n1/n2,n1/n4,n1/n5,n2/n4,n2/n3,n3/n4,n4/n5} + \draw (\from) -- (\to); + \end{tikzpicture} + \caption{Simple Network} + \label{fig:network} \end{figure} %\bibliographystyle{unsrt} diff --git a/tutorial-3/sheet03.pdf b/tutorial-3/sheet03.pdf index 4eb6b0d0069ab801748fef7909e5c880940fd53f..7b9b4d5bd1b0d1c9aaddb118160348835fd6bc3f 100755 Binary files a/tutorial-3/sheet03.pdf and b/tutorial-3/sheet03.pdf differ diff --git a/tutorial-3/sheet03.tex b/tutorial-3/sheet03.tex index c9c629f77650114cda57792baa76fcc3cd12084b..4ad077f28527f77582091ce8124a0da3080f7bbc 100755 --- a/tutorial-3/sheet03.tex +++ b/tutorial-3/sheet03.tex @@ -87,11 +87,11 @@ \begin{document} \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Tutorial III: Storage Optimisation}}\\ - \small Will be worked on in the exercise session on Monday, 16 July 2018.\\[1.5em] + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Tutorial III: Storage Optimisation}}\\ + \small Will be worked on in the exercise session on Monday, 16 July 2018.\\[1.5em] \end{center} \vspace{.5em} @@ -101,22 +101,22 @@ %===================================================================== \begin{wrapfigure}[11]{r}{0pt} - \begin{tikzpicture} - \begin{axis}[ - domain=0:14, no markers, samples=200 - % xlabel = x, ylabel = f(x) - ] - \addplot+[dashed] {0.3 * (1 + 0.9 * sin(deg(2*pi*x/7)))}; \label{figref:w} - \addplot+[densely dotted] {0.12*(1 + sin(deg(2*pi*x))}; \label{figref:s} - \addplot+[solid] {1}; \label{figref:l} - \end{axis} - \end{tikzpicture} - \caption{Diurnal and synoptic variations of wind and solar power generation - $$G_{N,w}(t)$$ - \autoref{figref:w} and $$G_{S,s}(t)$$ - \autoref{figref:s}, and a constant load (all in per-unit) $$L(t)$$ - \autoref{figref:l}.} - \label{fig:variations} + \begin{tikzpicture} + \begin{axis}[ + domain=0:14, no markers, samples=200 + % xlabel = x, ylabel = f(x) + ] + \addplot+[dashed] {0.3 * (1 + 0.9 * sin(deg(2*pi*x/7)))}; \label{figref:w} + \addplot+[densely dotted] {0.12*(1 + sin(deg(2*pi*x))}; \label{figref:s} + \addplot+[solid] {1}; \label{figref:l} + \end{axis} + \end{tikzpicture} + \caption{Diurnal and synoptic variations of wind and solar power generation + $$G_{N,w}(t)$$ + \autoref{figref:w} and $$G_{S,s}(t)$$ + \autoref{figref:s}, and a constant load (all in per-unit) $$L(t)$$ + \autoref{figref:l}.} + \label{fig:variations} \end{wrapfigure} Imagine a two-node Germany. The South can install solar panels with a capacity factor Cf_s to cover its load L_S, while the North uses wind turbines that have a capacity factor Cf_w @@ -125,61 +125,61 @@ to feed their load L_N. Figure \ref{fig:variations} shows approximations to th \vspace{-0.5em} \begin{align*} - G_{N,w}(t) &= Cf_w(1+A_w \sin \omega_w t), \\ - G_{S,s}(t) &= Cf_s(1+A_s \sin \omega_s t), \\ - L_{N/S}(t) &= A_{l,N/S}. + G_{N,w}(t) & = Cf_w(1+A_w \sin \omega_w t), \\ + G_{S,s}(t) & = Cf_s(1+A_s \sin \omega_s t), \\ + L_{N/S}(t) & = A_{l,N/S}. \end{align*} The capacity factors and constants are \vspace{-0.25em} \begin{align*} - A_{l,N} &= 20 \si{\giga\watt}, &A_{l,S}&= 30 \si{\giga\watt},\\ - Cf_w &= 0.3, &A_w &= 0.9, &\omega_w &= \frac{2\pi}{7 \text{d}}, \\ - Cf_s &= 0.12, &A_s &= 1.0, &\omega_s &= \frac{2\pi}{1 \text{d}}. \\ + A_{l,N} & = 20 \si{\giga\watt}, & A_{l,S} & = 30 \si{\giga\watt}, \\ + Cf_w & = 0.3, & A_w & = 0.9, & \omega_w & = \frac{2\pi}{7 \text{d}}, \\ + Cf_s & = 0.12, & A_s & = 1.0, & \omega_s & = \frac{2\pi}{1 \text{d}}. \\ \end{align*} \vspace{-0.3em} For now, assume the stores are lossless. Losses will be considered in III.2. \begin{enumerate}[(a)] - % (a) - \item How much wind capacity G_{N,w} must be installed in the North and solar capacity G_{S,s} in the South? - - % (b) - \item What is the amount of store and dispatch power capacity G_{s,store}=\max(-g_s(t)) and G_{s,dispatch}= \max g_s(t) the storages must have in the North and in the South? - - % (c) - \item What is the amount of energy capacity one needs in the North and in the South? - - \begin{equation*}$$- E_s = \max_t e_s(t) = \max_t \int_{0}^{t} (-g_s(t')) \;\mathrm{d}t' -$$\end{equation*} - - % (d) - \item Should they choose hydrogen or battery storages? And how much would it cost them with the prices in Table 1? Is the South or the North paying more for their energy? - - \item What do you imagine would change if you considered the storage losses given in Table 1 in your results (a)-(d)? Support your statement with a graphical illustration. - + % (a) + \item How much wind capacity G_{N,w} must be installed in the North and solar capacity G_{S,s} in the South? + + % (b) + \item What is the amount of store and dispatch power capacity G_{s,store}=\max(-g_s(t)) and G_{s,dispatch}= \max g_s(t) the storages must have in the North and in the South? + + % (c) + \item What is the amount of energy capacity one needs in the North and in the South? + + \begin{equation*} + E_s = \max_t e_s(t) = \max_t \int_{0}^{t} (-g_s(t')) \;\mathrm{d}t' + \end{equation*} + + % (d) + \item Should they choose hydrogen or battery storages? And how much would it cost them with the prices in Table 1? Is the South or the North paying more for their energy? + + \item What do you imagine would change if you considered the storage losses given in Table 1 in your results (a)-(d)? Support your statement with a graphical illustration. + \end{enumerate} - Now we lift the restriction against transmission and allow them to bridge their 500 km separation with a transmission line. - +Now we lift the restriction against transmission and allow them to bridge their 500 km separation with a transmission line. + \begin{enumerate}[(e)] - % (e) - \item Estimate the cost-optimal technology mix by assuming wind energy in the North is only stored in the North and solar energy in the South is likewise only stored in the South! What would happen if you dropped that assumption? + % (e) + \item Estimate the cost-optimal technology mix by assuming wind energy in the North is only stored in the North and solar energy in the South is likewise only stored in the South! What would happen if you dropped that assumption? \end{enumerate} \begin{table}[] - \centering - \label{tab:prices} - \begin{tabular}{@{}lrrrr@{}} - \toprule - & \eur per kW & \eur per kWh & \eta_{store} & \eta_{dispatch} \\ \midrule - Battery & 300 & 200 & 0.9 & 0.9 \\ - Hydrogen & 750 & 10 & 0.75 & 0.58 \\ - Solar & 600 & & & \\ - Wind & 1200 & & & \\ - Transmission line (500 km) & 200 & & & \\ \bottomrule - \end{tabular} - \caption{Investment costs of renewable energy infrastructure.} + \centering + \label{tab:prices} + \begin{tabular}{@{}lrrrr@{}} + \toprule + & \eur per kW & \eur per kWh & \eta_{store} & \eta_{dispatch} \\ \midrule + Battery & 300 & 200 & 0.9 & 0.9 \\ + Hydrogen & 750 & 10 & 0.75 & 0.58 \\ + Solar & 600 & & & \\ + Wind & 1200 & & & \\ + Transmission line (500 km) & 200 & & & \\ \bottomrule + \end{tabular} + \caption{Investment costs of renewable energy infrastructure.} \end{table} %=============== ====================================================== @@ -189,11 +189,11 @@ For now, assume the stores are lossless. Losses will be considered in III.2. Python for Power System Analysis (PyPSA) is a free software toolbox for optimising modern power systems that include features such as variable wind and solar generation, storage units, etc\.. Use the toolbox to extend on your findings in Problem III.1. \begin{enumerate}[(a)] - \item Build a network in PyPSA with the two buses North and South and attach the load at each bus and attach the wind and solar generators with availability according to G_{N,w}(t) = Cf_w(1+A_w\sin \omega_w t) and G_{S,s}(t) = Cf_s(1+A_s\sin \omega_s t) for a year (you have to call \texttt{set\_snapshots} for the year) and with \texttt{p\_nom\_extendable} set to True. As help you should have a look at the minimal LOPF example\footnote{\url{https://www.pypsa.org/examples/minimal_example_lopf.html}}, understand what the components documentation\footnote{\url{https://pypsa.org/doc/components.html}} of PyPSA gives you and that you can find the underlying objective function and constraints in the LOPF documentation\footnote{\url{https://pypsa.org/doc/optimal_power_flow.html\#linear-optimal-power-flow}}. - \item Attach extendable storages at the North and the South! The storages have to be modelled as an \texttt{H2-bus} (a bus with \texttt{carrier='H2'}) linked to the \texttt{AC-bus} North with a \texttt{Link} where \texttt{p\_nom\_extendable=True} with the \texttt{capital\_cost} of the power capacity and an also extendable \texttt{Store} with the \texttt{capital\_cost} of the energy capacity, for instance. The losses can be set on the links as \texttt{efficiency}. - \item Run an investment optimization by calling the \texttt{lopf} function. - \item How do your results \texttt{objective} and \texttt{{generators,stores,links}.p\_nom\_opt} compare with the results of III.1(d)? - \item Now lift the restriction against transmission and allow North and South to bridge their 500 km separation with a transmission line. How does the cost optimal technology mix change compared to III.1(f)? - \item Replace the approximated availability time-series of the wind and the solar generators with the ones from \texttt{availability.csv} computed from reanalysis weather data available on the course homepage\footnote{\url{https://nworbmot.org/courses/complex_renewable_energy_networks/}} and re-run the LOPF. Compare the results! Explain the differences by looking at the cumulative variations relative to the mean of the availability time-series! + \item Build a network in PyPSA with the two buses North and South and attach the load at each bus and attach the wind and solar generators with availability according to G_{N,w}(t) = Cf_w(1+A_w\sin \omega_w t) and G_{S,s}(t) = Cf_s(1+A_s\sin \omega_s t) for a year (you have to call \texttt{set\_snapshots} for the year) and with \texttt{p\_nom\_extendable} set to True. As help you should have a look at the minimal LOPF example\footnote{\url{https://www.pypsa.org/examples/minimal_example_lopf.html}}, understand what the components documentation\footnote{\url{https://pypsa.org/doc/components.html}} of PyPSA gives you and that you can find the underlying objective function and constraints in the LOPF documentation\footnote{\url{https://pypsa.org/doc/optimal_power_flow.html\#linear-optimal-power-flow}}. + \item Attach extendable storages at the North and the South! The storages have to be modelled as an \texttt{H2-bus} (a bus with \texttt{carrier='H2'}) linked to the \texttt{AC-bus} North with a \texttt{Link} where \texttt{p\_nom\_extendable=True} with the \texttt{capital\_cost} of the power capacity and an also extendable \texttt{Store} with the \texttt{capital\_cost} of the energy capacity, for instance. The losses can be set on the links as \texttt{efficiency}. + \item Run an investment optimization by calling the \texttt{lopf} function. + \item How do your results \texttt{objective} and \texttt{{generators,stores,links}.p\_nom\_opt} compare with the results of III.1(d)? + \item Now lift the restriction against transmission and allow North and South to bridge their 500 km separation with a transmission line. How does the cost optimal technology mix change compared to III.1(f)? + \item Replace the approximated availability time-series of the wind and the solar generators with the ones from \texttt{availability.csv} computed from reanalysis weather data available on the course homepage\footnote{\url{https://nworbmot.org/courses/complex_renewable_energy_networks/}} and re-run the LOPF. Compare the results! Explain the differences by looking at the cumulative variations relative to the mean of the availability time-series! \end{enumerate} \end{document} diff --git a/tutorial-3/solution03.tex b/tutorial-3/solution03.tex index 219065381b066dde007b0ea0468caa8a14adcd4c..20339e2111a7a016a636fe9407de098961f0e12f 100755 --- a/tutorial-3/solution03.tex +++ b/tutorial-3/solution03.tex @@ -86,11 +86,11 @@ \begin{document} \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Solutions to Tutorial III}}\\ - \small Will be worked on in the exercise session on Monday, 16 July 2018.\\[1.5em] + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Solutions to Tutorial III}}\\ + \small Will be worked on in the exercise session on Monday, 16 July 2018.\\[1.5em] \end{center} \vspace{1em} @@ -100,242 +100,242 @@ %===================================================================== \begin{wrapfigure}[11]{r}{0pt} - \begin{tikzpicture} - \begin{axis}[ - domain=0:14, no markers, samples=200 - % xlabel = x, ylabel = f(x) - ] - \addplot+[dashed] {0.3 * (1 + 0.9 * sin(deg(2*pi*x/7)))}; \label{figref:w} - \addplot+[densely dotted] {0.12*(1 + sin(deg(2*pi*x))}; \label{figref:s} - \addplot+[solid] {1}; \label{figref:l} - \end{axis} - \end{tikzpicture} - \caption{Diurnal and synoptic variations of wind and solar power generation - $$G_{N,w}(t)$$ - \autoref{figref:w} and $$G_{S,s}(t)$$ - \autoref{figref:s}, and a constant load (all in per-unit) $$L(t)$$ - \autoref{figref:l}.} - \label{fig:variations} + \begin{tikzpicture} + \begin{axis}[ + domain=0:14, no markers, samples=200 + % xlabel = x, ylabel = f(x) + ] + \addplot+[dashed] {0.3 * (1 + 0.9 * sin(deg(2*pi*x/7)))}; \label{figref:w} + \addplot+[densely dotted] {0.12*(1 + sin(deg(2*pi*x))}; \label{figref:s} + \addplot+[solid] {1}; \label{figref:l} + \end{axis} + \end{tikzpicture} + \caption{Diurnal and synoptic variations of wind and solar power generation + $$G_{N,w}(t)$$ + \autoref{figref:w} and $$G_{S,s}(t)$$ + \autoref{figref:s}, and a constant load (all in per-unit) $$L(t)$$ + \autoref{figref:l}.} + \label{fig:variations} \end{wrapfigure} Imagine a two-node Germany. The South can install solar panels with a capacity factor Cf_s to cover its load L_S, while the North uses wind turbines that have a capacity factor Cf_w to feed their load L_N. Figure \ref{fig:variations} shows approximations to the daily and synoptic variations of per-unit wind and solar power generation $$G_{N,w}(t)$$ and $$G_{S,s}(t)$$ and a constant load $$L_{N/S}(t)$$: \begin{align*} -G_{N,w}(t) &= Cf_w(1+A_w \sin \omega_w t), \\ -G_{S,s}(t) &= Cf_s(1+A_s \sin \omega_s t), \\ -L_{N/S}(t) &= A_{l,N/S}. + G_{N,w}(t) & = Cf_w(1+A_w \sin \omega_w t), \\ + G_{S,s}(t) & = Cf_s(1+A_s \sin \omega_s t), \\ + L_{N/S}(t) & = A_{l,N/S}. \end{align*} The capacity factors and constants are \begin{align*} -A_{l,N} &= 20 \si{\giga\watt}, &A_{l,S}&= 30 \si{\giga\watt},\\ -Cf_w &= 0.3, &A_w &= 0.9, &\omega_w &= \frac{2\pi}{7 \text{d}}, \\ -Cf_s &= 0.12, &A_s &= 1.0, &\omega_s &= \frac{2\pi}{1 \text{d}}. \\ + A_{l,N} & = 20 \si{\giga\watt}, & A_{l,S} & = 30 \si{\giga\watt}, \\ + Cf_w & = 0.3, & A_w & = 0.9, & \omega_w & = \frac{2\pi}{7 \text{d}}, \\ + Cf_s & = 0.12, & A_s & = 1.0, & \omega_s & = \frac{2\pi}{1 \text{d}}. \\ \end{align*} For now, assume the stores are lossless. Losses will be considered in III.2. \begin{enumerate}[(a)] - % (a) - \begin{shaded}\item How much wind capacity G_{N,w} must be installed in the North and solar capacity G_{S,s} in the South?\end{shaded} - - In the North: - - \expect{L_N} = \expect{G_{N,w} \cdot G_{N,w}(t)} - - \Rightarrow \quad A_{l,N} = G_{N,w}\cdot Cf_w  - - \DIVIDE{20}{0.3}\res - - \Rightarrow \quad G_{N,w} = \frac{A_{l,N}}{Cf_w} = \frac{20\si{\giga\watt}}{0.3} = \rd{\res}\si{\giga\watt} - - In the South: - - \expect{L_S} = \expect{G_{S,s} \cdot G_{S,s}(t)} - - \Rightarrow \quad A_{l,S} = G_{S,w}\cdot Cf_w  - - \DIVIDE{30}{0.12}\res - - \Rightarrow \quad G_{S,s} = \frac{A_{l,S}}{Cf_s} = \frac{30\si{\giga\watt}}{0.12} = \rd{\res}\si{\giga\watt} - - % (b) - \begin{shaded}\item What is the amount of store and dispatch power capacity G_{s,store}=\max(-g_s(t)) and G_{s,dispatch}= \max g_s(t) the storages must have in the North and in the South?\end{shaded} - - In the North: - - \begin{align*} - G_{s,storage,dispatch}^N &= \max ( \pm g_s^N(t)) \\ - &= \max (\pm [L_N(t) - G_{N,w} \cdot G_{N,w}(t)]) \\ - &= \max (\pm [L_N(t) - \frac{A_{l,N}}{Cf_w}\cdot Cf_w\cdot (1+A_w \sin \omega_w t)]) \\ - &= \max (\pm [L_N(t) - A_{l,N} + A_{l,N} A_w \sin \omega_w t)]) \\ - &= \max (\pm [A_{l,N} A_w \sin \omega_w t)]) \\ - &= A_{l,N} A_w = 0.9 \cdot 20 \si{\giga\watt} = 18 \si{\giga\watt} - \end{align*} - - In the South: - - \begin{align*} - G_{s,storage,dispatch}^S &= \max ( \pm g_s^S(t)) \\ - &= \max (\pm [L_S(t) - G_{S,s} \cdot G_{S,s}(t)^{m(t)}]) \\ - &= \max (\pm [L_S(t) - \frac{A_{l,S}}{Cf_s}\cdot Cf_s\cdot (1+A_s \sin \omega_s t)]) \\ - &= \max (\pm [L_S(t) - A_{l,S} + A_{l,S} A_s \sin \omega_s t)]) \\ - &= \max (\pm [A_{l,S} A_s \sin \omega_s t)]) \\ - &= A_{l,S} A_s = 1.0 \cdot 30 \si{\giga\watt} = 30 \si{\giga\watt} - \end{align*} - - % (c) - \begin{shaded}\item What is the amount of energy capacity one needs in the North and in the South? - - $$- E_s = \max_t e_s(t) = \max_t \int_{0}^{t} (-g_s(t')) \;\mathrm{d}t' -$$ - -\end{shaded} - - In the North: - - \begin{align*} - e_s^N(t) &= \int_{0}^{t} -g_s^N(t') \;\mathrm{d}t' = \int_{0}^{t} A_{l,N} A_w \sin \omega_w t' \;\mathrm{d}t' \\ - &= A_{l,N} A_w \frac{-\cos(\omega_w t')}{\omega_w}\Big|_0^t = A_{l,N} A_w \frac{1-\cos(\omega_w t')}{\omega_w} - \end{align*} - - \begin{equation*} - E_s^N = \max_t e_s(t) = \frac{2A_{l,N}A_w}{\omega_w} = \frac{2\cdot 20 \si{\giga\watt}\cdot 0.9}{2\pi} \cdot 7\cdot 24 \si{\hour} = 1 \si{\tera\watt\hour} - \end{equation*} - - In the South: - - \begin{align*} - e_s^S(t) &= \int_{0}^{t} -g_s^S(t') \;\mathrm{d}t' = \int_{0}^{t} A_{l,S} A_s \sin \omega_s t' \;\mathrm{d}t' \\ - &= A_{l,S} A_s \frac{-\cos(\omega_s t')}{\omega_s}\Big|_0^t = A_{l,S} A_s \frac{1-\cos(\omega_s t')}{\omega_s} - \end{align*} - - \begin{equation*} - E_s^S = \max_t e_s(t) = \frac{2A_{l,S}A_s}{\omega_s} = \frac{2\cdot 30 \si{\giga\watt}\cdot 1}{2\pi} \cdot 24 \si{\hour} = 230 \si{\giga\watt\hour} - \end{equation*} - - % (d) - \begin{shaded}\item Should they choose hydrogen or battery storages? And how much would it cost them? Is the South or the North paying more for their energy?\end{shaded} - - \textbf{In the North:} - - The cost of renewable generation in the North is - - P_w^N=G_{N,w} \cdot 1200 \text{\EUR{}}\si{\per\kilo\watt}=80\cdot10^9\text{\EUR{}}  - - The minimal (lossless) corresponding cost to supply constant demand by using hydrogen as storage technology are - - \begin{align*} - P_h^N &= 750 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^N + 10 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^N \\ - &= 13.5 \cdot 10^9 \eur + 10 \cdot 10^9 \eur \\ - &= 23.5 \cdot 10^9 \eur - \end{align*} - - The minimal (lossless) corresponding cost to supply constant demand by using batteries as storage technology are: - - \begin{align*} - P_b^N &= 300 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^N + 200 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^N \\ - &= 5.4 \cdot 10^9 \eur + 200 \cdot 10^9 \eur \\ - &= 205.4 \cdot 10^9 \eur - \end{align*} - - The minimal (lossless) total system cost using hydrogen storages accumulates to - - P_w^N + P_h^N = 104 \cdot 10^9\eur \leq P_{w+h}^N - - whereas the system cost using batteries are - - P_w^N + P_b^N = 285 \cdot 10^9\eur \leq P_{w+b}^N. - - Thus, the North should choose hydrogen storages.\\~\\ - - \textbf{In the South:} - - The cost of renewable generation in the South is - - P_s^S=G_{S,s} \cdot 600 \text{\EUR{}}\si{\per\kilo\watt}=150\cdot10^9\text{\EUR{}}  - - The minimal (lossless) corresponding cost to supply constant demand by using hydrogen as storage technology are - - \begin{align*} - P_h^S &= 1200 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^S + 10 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^S \\ - &= 22.5 \cdot 10^9 \eur + 2.3 \cdot 10^9 \eur \\ - &= 24.8 \cdot 10^9 \eur - \end{align*} - - The minimal (lossless) corresponding cost to supply constant demand by using batteries as storage technology are: - - \begin{align*} - P_b^S &= 300 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^S + 200 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^S \\ - &= 9 \cdot 10^9 \eur + 46 \cdot 10^9 \eur \\ - &= 54 \cdot 10^9 \eur - \end{align*} - - The minimal (lossless) total system cost using hydrogen storages accumulates to - - P_s^S + P_h^S = 175 \cdot 10^9\eur \leq P_{s+h}^S - - whereas the system cost using batteries are - - P_s^S + P_b^S = 204 \cdot 10^9\eur \leq P_{s+b}^S - - Thus, the South should also choose hydrogen storages.\\~\\ - - \textbf{Cost comparison between North and South:} - - Without taking losses into account, both regions should choose hydrogen storages. Overall, the North can provide electricity at a lower rate than the South: - - \tilde{P}_{w+h}^N = \frac{104 \cdot 10^9 \eur}{20 \si{\giga\watt}} = 5 \cdot 10^9 \eur \si{\per\giga\watt} - - \tilde{P}_{s+h}^S = \frac{175 \cdot 10^9 \eur}{30 \si{\giga\watt}} = 6 \cdot 10^9 \eur \si{\per\giga\watt} - - % (e) - \begin{shaded} - \item What do you imagine would change if you considered the storage losses given in Table 1 in your results (a)-(d)? Support your statement with a graphical illustration. - \end{shaded} - - To compensate for the energy losses wind and solar capacity G_{N/S,w/s}, store and dispatch power capacities G_s and storage energy capacities E_s have to increase. - - % (f) - \begin{shaded}\item Now we lift the restriction against transmission and allow them to bridge their 500 km separation with a transmission line. Estimate the cost-optimal technology mix by assuming wind energy in the North is only stored in the North and solar energy in the South is likewise only stored in the South! What would happen if you dropped that assumption?\end{shaded} - - Because \tilde{P}_{w+h}^N < \tilde{P}_{w+h}^S there will be energy exports from North to South: - - E^N > E^S \quad \text{and} \quad E^N + E^S = 50 \si{\giga\watt} - - The total price of electricity is given by - - \begin{align*} - P_{tot} &=\frac{ E^N \cdot \tilde{P}_{w+h}^N + E^S \cdot \tilde{P}_{s+h}^S + (E^N - E^S)\cdot 200 \eur\si{\per\kilo\watt}}{E^N + E^S} \\ - &= \frac{E^N \cdot \tilde{P}_{w+h}^N + (50\si{\giga\watt} - E^N) \cdot \tilde{P}_{s+h}^S + (2E^N - 50\si{\giga\watt})\cdot 200 \eur\si{\per\kilo\watt}}{E^N + E^S} \\ - &= \frac{E^N (\tilde{P}_{w+h}^N - \tilde{P}_{s+h}^S + 400 \eur \si{\per\kilo\watt}) + 50 \si{\giga\watt} (\tilde{P}_{s+h}^S - 200 \eur \si{\per\kilo\watt})}{E^N + E^S} \\ - \end{align*} - - Now, minimising the term for a choice of E^N will yield - - \begin{align*} - E^N &= 50 \si{\giga\watt} - \end{align*} - - such that all power would be produced from wind in the North and the total system cost is - - \begin{align*} - \min P_{tot} &= \frac{-0.6 \cdot 50 \cdot 10^9 \eur + 5.8 \cdot 50 \cdot 10^9 \eur}{50 \si{\giga\watt}} \\ - &= \frac{260 \cdot 10^9 \eur}{50 \si{\giga\watt}} = 5.2 \cdot 10^9 \eur \si{\per\giga\watt} - \end{align*} - - Compared to the weighted electricity cost of North and South without transmission - - \begin{align*} - \min \tilde{P}_{tot} &= \frac{20\si{\giga\watt}\cdot 5 \cdot 10^9 \eur \si{\per\giga\watt} + 30\si{\giga\watt}\cdot 6 \cdot 10^9 \eur \si{\per\giga\watt}}{50 \si{\giga\watt}} \\ - &= \frac{280 \cdot 10^9 \eur}{50 \si{\giga\watt}} = 5.6 \cdot 10^9 \eur \si{\per\giga\watt} - \end{align*} - - the system cost could be reduced by approx.\ 7 \%. - + % (a) + \begin{shaded}\item How much wind capacity G_{N,w} must be installed in the North and solar capacity G_{S,s} in the South?\end{shaded} + + In the North: + + \expect{L_N} = \expect{G_{N,w} \cdot G_{N,w}(t)} + + \Rightarrow \quad A_{l,N} = G_{N,w}\cdot Cf_w  + + \DIVIDE{20}{0.3}\res + + \Rightarrow \quad G_{N,w} = \frac{A_{l,N}}{Cf_w} = \frac{20\si{\giga\watt}}{0.3} = \rd{\res}\si{\giga\watt} + + In the South: + + \expect{L_S} = \expect{G_{S,s} \cdot G_{S,s}(t)} + + \Rightarrow \quad A_{l,S} = G_{S,w}\cdot Cf_w  + + \DIVIDE{30}{0.12}\res + + \Rightarrow \quad G_{S,s} = \frac{A_{l,S}}{Cf_s} = \frac{30\si{\giga\watt}}{0.12} = \rd{\res}\si{\giga\watt} + + % (b) + \begin{shaded}\item What is the amount of store and dispatch power capacity G_{s,store}=\max(-g_s(t)) and G_{s,dispatch}= \max g_s(t) the storages must have in the North and in the South?\end{shaded} + + In the North: + + \begin{align*} + G_{s,storage,dispatch}^N & = \max ( \pm g_s^N(t)) \\ + & = \max (\pm [L_N(t) - G_{N,w} \cdot G_{N,w}(t)]) \\ + & = \max (\pm [L_N(t) - \frac{A_{l,N}}{Cf_w}\cdot Cf_w\cdot (1+A_w \sin \omega_w t)]) \\ + & = \max (\pm [L_N(t) - A_{l,N} + A_{l,N} A_w \sin \omega_w t)]) \\ + & = \max (\pm [A_{l,N} A_w \sin \omega_w t)]) \\ + & = A_{l,N} A_w = 0.9 \cdot 20 \si{\giga\watt} = 18 \si{\giga\watt} + \end{align*} + + In the South: + + \begin{align*} + G_{s,storage,dispatch}^S & = \max ( \pm g_s^S(t)) \\ + & = \max (\pm [L_S(t) - G_{S,s} \cdot G_{S,s}(t)^{m(t)}]) \\ + & = \max (\pm [L_S(t) - \frac{A_{l,S}}{Cf_s}\cdot Cf_s\cdot (1+A_s \sin \omega_s t)]) \\ + & = \max (\pm [L_S(t) - A_{l,S} + A_{l,S} A_s \sin \omega_s t)]) \\ + & = \max (\pm [A_{l,S} A_s \sin \omega_s t)]) \\ + & = A_{l,S} A_s = 1.0 \cdot 30 \si{\giga\watt} = 30 \si{\giga\watt} + \end{align*} + + % (c) + \begin{shaded}\item What is the amount of energy capacity one needs in the North and in the South? + + $$+ E_s = \max_t e_s(t) = \max_t \int_{0}^{t} (-g_s(t')) \;\mathrm{d}t' +$$ + + \end{shaded} + + In the North: + + \begin{align*} + e_s^N(t) & = \int_{0}^{t} -g_s^N(t') \;\mathrm{d}t' = \int_{0}^{t} A_{l,N} A_w \sin \omega_w t' \;\mathrm{d}t' \\ + & = A_{l,N} A_w \frac{-\cos(\omega_w t')}{\omega_w}\Big|_0^t = A_{l,N} A_w \frac{1-\cos(\omega_w t')}{\omega_w} + \end{align*} + + \begin{equation*} + E_s^N = \max_t e_s(t) = \frac{2A_{l,N}A_w}{\omega_w} = \frac{2\cdot 20 \si{\giga\watt}\cdot 0.9}{2\pi} \cdot 7\cdot 24 \si{\hour} = 1 \si{\tera\watt\hour} + \end{equation*} + + In the South: + + \begin{align*} + e_s^S(t) & = \int_{0}^{t} -g_s^S(t') \;\mathrm{d}t' = \int_{0}^{t} A_{l,S} A_s \sin \omega_s t' \;\mathrm{d}t' \\ + & = A_{l,S} A_s \frac{-\cos(\omega_s t')}{\omega_s}\Big|_0^t = A_{l,S} A_s \frac{1-\cos(\omega_s t')}{\omega_s} + \end{align*} + + \begin{equation*} + E_s^S = \max_t e_s(t) = \frac{2A_{l,S}A_s}{\omega_s} = \frac{2\cdot 30 \si{\giga\watt}\cdot 1}{2\pi} \cdot 24 \si{\hour} = 230 \si{\giga\watt\hour} + \end{equation*} + + % (d) + \begin{shaded}\item Should they choose hydrogen or battery storages? And how much would it cost them? Is the South or the North paying more for their energy?\end{shaded} + + \textbf{In the North:} + + The cost of renewable generation in the North is + + P_w^N=G_{N,w} \cdot 1200 \text{\EUR{}}\si{\per\kilo\watt}=80\cdot10^9\text{\EUR{}}  + + The minimal (lossless) corresponding cost to supply constant demand by using hydrogen as storage technology are + + \begin{align*} + P_h^N & = 750 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^N + 10 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^N \\ + & = 13.5 \cdot 10^9 \eur + 10 \cdot 10^9 \eur \\ + & = 23.5 \cdot 10^9 \eur + \end{align*} + + The minimal (lossless) corresponding cost to supply constant demand by using batteries as storage technology are: + + \begin{align*} + P_b^N & = 300 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^N + 200 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^N \\ + & = 5.4 \cdot 10^9 \eur + 200 \cdot 10^9 \eur \\ + & = 205.4 \cdot 10^9 \eur + \end{align*} + + The minimal (lossless) total system cost using hydrogen storages accumulates to + + P_w^N + P_h^N = 104 \cdot 10^9\eur \leq P_{w+h}^N + + whereas the system cost using batteries are + + P_w^N + P_b^N = 285 \cdot 10^9\eur \leq P_{w+b}^N. + + Thus, the North should choose hydrogen storages.\\~\\ + + \textbf{In the South:} + + The cost of renewable generation in the South is + + P_s^S=G_{S,s} \cdot 600 \text{\EUR{}}\si{\per\kilo\watt}=150\cdot10^9\text{\EUR{}}  + + The minimal (lossless) corresponding cost to supply constant demand by using hydrogen as storage technology are + + \begin{align*} + P_h^S & = 1200 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^S + 10 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^S \\ + & = 22.5 \cdot 10^9 \eur + 2.3 \cdot 10^9 \eur \\ + & = 24.8 \cdot 10^9 \eur + \end{align*} + + The minimal (lossless) corresponding cost to supply constant demand by using batteries as storage technology are: + + \begin{align*} + P_b^S & = 300 \text{\EUR{}}\si{\per\kilo\watt} \cdot G_{s,storage,dispatch}^S + 200 \text{\EUR{}}\si{\per\kilo\watt\hour} \cdot E_s^S \\ + & = 9 \cdot 10^9 \eur + 46 \cdot 10^9 \eur \\ + & = 54 \cdot 10^9 \eur + \end{align*} + + The minimal (lossless) total system cost using hydrogen storages accumulates to + + P_s^S + P_h^S = 175 \cdot 10^9\eur \leq P_{s+h}^S + + whereas the system cost using batteries are + + P_s^S + P_b^S = 204 \cdot 10^9\eur \leq P_{s+b}^S + + Thus, the South should also choose hydrogen storages.\\~\\ + + \textbf{Cost comparison between North and South:} + + Without taking losses into account, both regions should choose hydrogen storages. Overall, the North can provide electricity at a lower rate than the South: + + \tilde{P}_{w+h}^N = \frac{104 \cdot 10^9 \eur}{20 \si{\giga\watt}} = 5 \cdot 10^9 \eur \si{\per\giga\watt} + + \tilde{P}_{s+h}^S = \frac{175 \cdot 10^9 \eur}{30 \si{\giga\watt}} = 6 \cdot 10^9 \eur \si{\per\giga\watt} + + % (e) + \begin{shaded} + \item What do you imagine would change if you considered the storage losses given in Table 1 in your results (a)-(d)? Support your statement with a graphical illustration. + \end{shaded} + + To compensate for the energy losses wind and solar capacity G_{N/S,w/s}, store and dispatch power capacities G_s and storage energy capacities E_s have to increase. + + % (f) + \begin{shaded}\item Now we lift the restriction against transmission and allow them to bridge their 500 km separation with a transmission line. Estimate the cost-optimal technology mix by assuming wind energy in the North is only stored in the North and solar energy in the South is likewise only stored in the South! What would happen if you dropped that assumption?\end{shaded} + + Because \tilde{P}_{w+h}^N < \tilde{P}_{w+h}^S there will be energy exports from North to South: + + E^N > E^S \quad \text{and} \quad E^N + E^S = 50 \si{\giga\watt} + + The total price of electricity is given by + + \begin{align*} + P_{tot} & =\frac{ E^N \cdot \tilde{P}_{w+h}^N + E^S \cdot \tilde{P}_{s+h}^S + (E^N - E^S)\cdot 200 \eur\si{\per\kilo\watt}}{E^N + E^S} \\ + & = \frac{E^N \cdot \tilde{P}_{w+h}^N + (50\si{\giga\watt} - E^N) \cdot \tilde{P}_{s+h}^S + (2E^N - 50\si{\giga\watt})\cdot 200 \eur\si{\per\kilo\watt}}{E^N + E^S} \\ + & = \frac{E^N (\tilde{P}_{w+h}^N - \tilde{P}_{s+h}^S + 400 \eur \si{\per\kilo\watt}) + 50 \si{\giga\watt} (\tilde{P}_{s+h}^S - 200 \eur \si{\per\kilo\watt})}{E^N + E^S} \\ + \end{align*} + + Now, minimising the term for a choice of E^N will yield + + \begin{align*} + E^N & = 50 \si{\giga\watt} + \end{align*} + + such that all power would be produced from wind in the North and the total system cost is + + \begin{align*} + \min P_{tot} & = \frac{-0.6 \cdot 50 \cdot 10^9 \eur + 5.8 \cdot 50 \cdot 10^9 \eur}{50 \si{\giga\watt}} \\ + & = \frac{260 \cdot 10^9 \eur}{50 \si{\giga\watt}} = 5.2 \cdot 10^9 \eur \si{\per\giga\watt} + \end{align*} + + Compared to the weighted electricity cost of North and South without transmission + + \begin{align*} + \min \tilde{P}_{tot} & = \frac{20\si{\giga\watt}\cdot 5 \cdot 10^9 \eur \si{\per\giga\watt} + 30\si{\giga\watt}\cdot 6 \cdot 10^9 \eur \si{\per\giga\watt}}{50 \si{\giga\watt}} \\ + & = \frac{280 \cdot 10^9 \eur}{50 \si{\giga\watt}} = 5.6 \cdot 10^9 \eur \si{\per\giga\watt} + \end{align*} + + the system cost could be reduced by approx.\ 7 \%. + \end{enumerate} \end{document} diff --git a/tutorial-4/sheet04.pdf b/tutorial-4/sheet04.pdf index 013a818d0f67a298a660428ceaf4ec2cd0937fb6..1fa3270a325f1eea39f1c568e4b4df7b709550dc 100755 Binary files a/tutorial-4/sheet04.pdf and b/tutorial-4/sheet04.pdf differ diff --git a/tutorial-4/sheet04.tex b/tutorial-4/sheet04.tex index 694926fe8edbb2a9b8820599c223129acb301cbe..04e56efd750af147a56097d3ee0cd50a189b1558 100755 --- a/tutorial-4/sheet04.tex +++ b/tutorial-4/sheet04.tex @@ -100,101 +100,88 @@ %===================================================================== %===================================================================== \begin{document} - - \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Tutorial IV: Electricity Markets}}\\ - \small Will be worked on in the exercise session on Tuesday, 17 July 2018.\\[1.5em] - \end{center} - - \vspace{1em} - - %=============== ====================================================== - \paragraph{Problem IV.1 \normalsize (Shadow prices of limits on consumption).}~\\ - %===================================================================== - - Suppose that the utility for the electricity consumption of an industrial company is given by - \[ - U(q) = 70q - 3q^2 [\textrm{\euro}/h] \quad , \quad q_{min}=2\leq q \leq q_{max}=10, - - where $q$ is the demand in MW and $q_{min}, q_{max}$ are the minimum and maximum demand. \\ - [1em] - Assume that the company is maximising its net surplus for a given electricity price $\pi$, i.e. it maximises $\max_{q} \left[U(q) - - \pi q\right]$. - \begin{enumerate}[(a)] - \item If the price is $\pi = 5$~\euro/MWh, what is the optimal - demand $q^*$? What is the value of the KKT multiplier $\mu_{max}$ - for the constraint $q \leq q_{max}=10$ at this optimal solution? - What is the value of $\mu_{min}$ for $q \geq q_{min} = 2$? - \item Suppose now the electricity price is $\pi = 60$~\euro/MWh. What are - the optimal demand $q^*$, $\mu_{max}$ and $\mu_{min}$ now? - \end{enumerate} - - %=============== ====================================================== - \paragraph{Problem VI.2 \normalsize (Economic dispatch in a single bidding zone).}~\\ - %===================================================================== - - Consider an electricity market with two generator types, one with variable cost $c = 20\emwh$, capacity $K = 300\mw$ and a dispatch rate of $Q_1$~[MW] and another with variable cost $c=50\emwh$, capacity $K=400\mw$ and a dispatch rate of $Q_2$~[MW]. The demand has utility function $U(Q) = 8000Q - 5Q^2$~[\euro/h] for a consumption rate of $Q$~[MW]. - \begin{enumerate}[(a)] - \item What are the objective function and constraints required for an optimisation problem to maximise short-run social welfare in this market? - \item Write down the Karush-Kuhn-Tucker (KKT) conditions for this problem. - \item Determine the optimal rate of production of the generators and the value of all KKT multipliers. What is the interpretation of the respective KKT multipliers? - \end{enumerate} - - %%=============== ====================================================== - %\paragraph{Problem II.3 \normalsize (Revenue, profit and consumer surplus).}~\\ - %%===================================================================== - % - %Consider the example of bids and offers in an electricity market from - %slides 28 to 31 from Lecture 2 on 18.04.2016 (taken from the book - %Kirschen and Strbac pages 56-58). - % - %\begin{enumerate}[(a)] - % \item Compute the revenue and profit of each generating company and the net - % surplus of each consuming company. - % \item If consumer company Orange'' withdraws its offers from the market, how do the market price and the profits/surpluses of generators and consumers change? - %\end{enumerate} - - %=============== ====================================================== - \paragraph{Problem IV.3 \normalsize (efficient dispatch in a two-bus power system).}~\\ - %===================================================================== - - \begin{figure}[h] - \centering - \includegraphics[width=14cm]{two-bus} - \label{fig:two-bus} - \caption{A simple two-bus power system.} - \end{figure} - - Consider the two-bus power system shown in Figure \ref{fig:two-bus}, where the two nodes represent two markets, each with different total demand, and one generator at each node. At node A the demand is $D_A = 2000 \si{\mega\watt}$, whereas at node B the demand is $D_B = 1000 \si{\mega\watt}$. Furthermore, there is a transmission line with a capacity denoted by $F_{AB}$. The marginal cost of production of the generators connected to buses A and B are given respectively by the following expressions: - \begin{align*} - MC_A & = 20 + 0.03 P_A \hspace{1cm}\eur/\si{\mega\watt\hour} \\ - MC_B & = 15 + 0.02 P_B \hspace{1cm} \eur/\si{\mega\watt\hour} - \end{align*} - - Assume that the demand $D_*$ is constant and insensitive to price, that energy is sold at its marginal cost of production and that there are no limits on the output of the generators. - - \begin{enumerate}[(a)] - \item Calculate the price of electricity at each bus, the production - of each generator, the flow on the line, and the value of any KKT - multipliers for the following cases: - \begin{enumerate}[(i)] - \item The line between buses A and B is disconnected. - \item The line between buses A and B is in service and has an unlimited capacity. - \item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator B is 1500~MW. - \item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator A is 900~MW. The output of Generator B is unlimited. - \item The line between buses A and B is in service but its capacity is limited to 600~MW. The output of the generators is unlimited. - \end{enumerate} - \item Calculate the generator revenues, generator profits, consumer payments and consumer net surplus for all the cases considered in the above problem. Who benefits from the line connecting these two buses? - \item Calculate the congestion surplus for case (v). For what values of the flow on the line between buses A and B is the congestion surplus equal to zero? - \end{enumerate} - - %=============== ====================================================== - \paragraph{Problem IV.4 \normalsize (bidding in africa with pypsa).}~\\ - %===================================================================== - - - + +\begin{center} + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Tutorial IV: Electricity Markets}}\\ + \small Will be worked on in the exercise session on Tuesday, 17 July 2018.\$1.5em] +\end{center} + +\vspace{1em} + +%=============== ====================================================== +\paragraph{Problem IV.1 \normalsize (Shadow prices of limits on consumption).}~\\ +%===================================================================== + +Suppose that the utility for the electricity consumption of an industrial company is given by +\[ + U(q) = 70q - 3q^2 [\textrm{\euro}/h] \quad , \quad q_{min}=2\leq q \leq q_{max}=10, +$ +where $q$ is the demand in MW and $q_{min}, q_{max}$ are the minimum and maximum demand. \\ +[1em] +Assume that the company is maximising its net surplus for a given electricity price $\pi$, i.e. it maximises $\max_{q} \left[U(q) - + \pi q\right]$. +\begin{enumerate}[(a)] + \item If the price is $\pi = 5$~\euro/MWh, what is the optimal + demand $q^*$? What is the value of the KKT multiplier $\mu_{max}$ + for the constraint $q \leq q_{max}=10$ at this optimal solution? + What is the value of $\mu_{min}$ for $q \geq q_{min} = 2$? + \item Suppose now the electricity price is $\pi = 60$~\euro/MWh. What are + the optimal demand $q^*$, $\mu_{max}$ and $\mu_{min}$ now? +\end{enumerate} + +%=============== ====================================================== +\paragraph{Problem VI.2 \normalsize (Economic dispatch in a single bidding zone).}~\\ +%===================================================================== + +Consider an electricity market with two generator types, one with variable cost $c = 20\emwh$, capacity $K = 300\mw$ and a dispatch rate of $Q_1$~[MW] and another with variable cost $c=50\emwh$, capacity $K=400\mw$ and a dispatch rate of $Q_2$~[MW]. The demand has utility function $U(Q) = 8000Q - 5Q^2$~[\euro/h] for a consumption rate of $Q$~[MW]. +\begin{enumerate}[(a)] + \item What are the objective function and constraints required for an optimisation problem to maximise short-run social welfare in this market? + \item Write down the Karush-Kuhn-Tucker (KKT) conditions for this problem. + \item Determine the optimal rate of production of the generators and the value of all KKT multipliers. What is the interpretation of the respective KKT multipliers? +\end{enumerate} + +%=============== ====================================================== +\paragraph{Problem IV.3 \normalsize (efficient dispatch in a two-bus power system).}~\\ +%===================================================================== + +\begin{figure}[h] + \centering + \includegraphics[width=14cm]{two-bus} + + \caption{A simple two-bus power system.} + \label{test} +\end{figure} + +Consider the two-bus power system shown in Figure \ref{test}, where the two nodes represent two markets, each with different total demand, and one generator at each node. At node A the demand is $D_A = 2000 \si{\mega\watt}$, whereas at node B the demand is $D_B = 1000 \si{\mega\watt}$. Furthermore, there is a transmission line with a capacity denoted by $F_{AB}$. The marginal cost of production of the generators connected to buses A and B are given respectively by the following expressions: +\begin{align*} + MC_A & = 20 + 0.03 P_A \hspace{1cm}\eur/\si{\mega\watt\hour} \\ + MC_B & = 15 + 0.02 P_B \hspace{1cm} \eur/\si{\mega\watt\hour} +\end{align*} + +Assume that the demand $D_*$ is constant and insensitive to price, that energy is sold at its marginal cost of production and that there are no limits on the output of the generators. + +\begin{enumerate}[(a)] + \item Calculate the price of electricity at each bus, the production + of each generator, the flow on the line, and the value of any KKT + multipliers for the following cases: + \begin{enumerate}[(i)] + \item The line between buses A and B is disconnected. + \item The line between buses A and B is in service and has an unlimited capacity. + \item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator B is 1500~MW. + \item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator A is 900~MW. The output of Generator B is unlimited. + \item The line between buses A and B is in service but its capacity is limited to 600~MW. The output of the generators is unlimited. + \end{enumerate} + \item Calculate the generator revenues, generator profits, consumer payments and consumer net surplus for all the cases considered in the above problem. Who benefits from the line connecting these two buses? + \item Calculate the congestion surplus for case (v). For what values of the flow on the line between buses A and B is the congestion surplus equal to zero? +\end{enumerate} + +%=============== ====================================================== +\paragraph{Problem IV.4 \normalsize (bidding in africa with pypsa).}~\\ +%===================================================================== + + + \end{document} diff --git a/tutorial-4/solution04-4.ipynb b/tutorial-4/solution04-4.ipynb index 8b70ebaaadbb0f235d909290e94df736036a70b3..0b762c30d2eb17c7f8307b0b20fcd1c7ad07ab96 100755 --- a/tutorial-4/solution04-4.ipynb +++ b/tutorial-4/solution04-4.ipynb @@ -6,12 +6,6 @@ "source": [ "# Simple electricity market examples\n", "\n", - "This Jupyter notebook is meant for teaching purposes. To use it, you need to install a Python environment with Jupyter notebooks, and the Python for Power System Analysis (PyPSA) library. See\n", - "\n", - "https://pypsa.org/doc/installation.html\n", - "\n", - "for tips on installation.\n", - "\n", "It gradually builds up more and more complicated energy-only electricity markets in PyPSA, starting from a single bidding zone, going up to multiple bidding zones connected with transmission (NTCs) along with variable renewables and storage.\n", "\n", "Available as a Jupyter notebook at http://www.pypsa.org/examples/simple-electricity-market-examples.ipynb." @@ -29,9 +23,7 @@ { "cell_type": "code", "execution_count": 1, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "import pypsa, numpy as np" @@ -40,18 +32,25 @@ { "cell_type": "code", "execution_count": 2, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "#marginal costs in EUR/MWh\n", "marginal_costs = {\"Wind\" : 0,\n", " \"Hydro\" : 0,\n", + " \"Solar\" : 0,\n", " \"Coal\" : 30,\n", " \"Gas\" : 60,\n", " \"Oil\" : 80}\n", "\n", + "#capital costs in EUR/kW\n", + "capital_costs = {\"Wind\" : 10000,\n", + " \"Hydro\" : 3000,\n", + " \"Solar\" : 6000,\n", + " \"Coal\" : 35000,\n", + " \"Gas\" : 8000,\n", + " \"Oil\" : 20000}\n", + "\n", "#power plant capacities (nominal powers in MW) in each country (not necessarily realistic)\n", "power_plant_p_nom = {\"South Africa\" : {\"Coal\" : 35000,\n", " \"Wind\" : 3000,\n", @@ -79,103 +78,174 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Single bidding zone with fixed load, one period\n", - "\n", - "In this example we consider a single market bidding zone, South Africa.\n", + "## Three bidding zones connected by transmission, one period\n", "\n", - "The inelastic load has essentially infinite marginal utility (or higher than the marginal cost of any generator)." + "In this example we have bidirectional transmission capacity between three bidding zones. The power transfer is treated as controllable (like an A/NTC (Available/Net Transfer Capacity) or HVDC line). Note that in the physical grid, power flows passively according to the network impedances." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ - "country = \"South Africa\"\n", - "\n", "network = pypsa.Network()\n", "\n", - "network.add(\"Bus\",country)\n", + "countries = [\"Swaziland\", \"Mozambique\", \"South Africa\"]\n", "\n", - "for tech in power_plant_p_nom[country]:\n", - " network.add(\"Generator\",\n", - " \"{} {}\".format(country,tech),\n", - " bus=country,\n", - " p_nom=power_plant_p_nom[country][tech],\n", - " marginal_cost=marginal_costs[tech])\n", + "for country in countries:\n", + " \n", + " network.add(\"Bus\",country)\n", + "\n", + " for tech in power_plant_p_nom[country]:\n", + " network.add(\"Generator\",\n", + " \"{} {}\".format(country,tech),\n", + " bus=country,\n", + " p_nom=power_plant_p_nom[country][tech],\n", + " marginal_cost=marginal_costs[tech])\n", "\n", "\n", - "network.add(\"Load\",\n", - " \"{} load\".format(country),\n", - " bus=country,\n", - " p_set=loads[country])" + " network.add(\"Load\",\n", + " \"{} load\".format(country),\n", + " bus=country,\n", + " p_set=loads[country])\n", + " \n", + " #add transmission as controllable Link\n", + " if country not in transmission:\n", + " continue\n", + " \n", + " for other_country in countries:\n", + " if other_country not in transmission[country]:\n", + " continue\n", + " \n", + " #NB: Link is by default unidirectional, so have to set p_min_pu = -1\n", + " #to allow bidirectional (i.e. also negative) flow\n", + " network.add(\"Link\",\n", + " \"{} - {} link\".format(country, other_country),\n", + " bus0=country,\n", + " bus1=other_country,\n", + " p_nom=transmission[country][other_country],\n", + " p_min_pu=-1)" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "INFO:pypsa.pf:Slack bus for sub-network 0 is South Africa\n", + "INFO:pypsa.pf:Slack bus for sub-network 0 is Swaziland\n", + "INFO:pypsa.pf:Slack bus for sub-network 1 is Mozambique\n", + "INFO:pypsa.pf:Slack bus for sub-network 2 is South Africa\n", "INFO:pypsa.opf:Performed preliminary steps\n", "INFO:pypsa.opf:Building pyomo model using angles formulation\n", + "/home/ws/sp2668/software/anaconda3/lib/python3.6/site-packages/pypsa/components.py:758: FutureWarning:\n", + "\n", + "Sorting because non-concatenation axis is not aligned. A future version\n", + "of pandas will change to not sort by default.\n", + "\n", + "To accept the future behavior, pass 'sort=True'.\n", + "\n", + "To retain the current behavior and silence the warning, pass sort=False\n", + "\n", + "\n", "INFO:pypsa.opf:Solving model using glpk\n", "INFO:pypsa.opf:Optimization successful\n" ] }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# ==========================================================\n", + "# = Solver Results =\n", + "# ==========================================================\n", + "# ----------------------------------------------------------\n", + "# Problem Information\n", + "# ----------------------------------------------------------\n", + "Problem: \n", + "- Name: unknown\n", + " Lower bound: 1245000.0\n", + " Upper bound: 1245000.0\n", + " Number of objectives: 1\n", + " Number of constraints: 13\n", + " Number of variables: 13\n", + " Number of nonzeros: 22\n", + " Sense: minimize\n", + "# ----------------------------------------------------------\n", + "# Solver Information\n", + "# ----------------------------------------------------------\n", + "Solver: \n", + "- Status: ok\n", + " Termination condition: optimal\n", + " Statistics: \n", + " Branch and bound: \n", + " Number of bounded subproblems: 0\n", + " Number of created subproblems: 0\n", + " Error rc: 0\n", + " Time: 0.01071619987487793\n", + "# ----------------------------------------------------------\n", + "# Solution Information\n", + "# ----------------------------------------------------------\n", + "Solution: \n", + "- number of solutions: 0\n", + " number of solutions displayed: 0\n" + ] + }, { "data": { "text/plain": [ "('ok', 'optimal')" ] }, - "execution_count": 4, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "#Run optimisation to determine market dispatch\n", "network.lopf()" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", - "\n", "\n", " \n", " \n", " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -183,486 +253,251 @@ "" ], "text/plain": [ - " South Africa load\n", - "now 42000.0" + " Swaziland load Mozambique load South Africa load\n", + "now 250.0 650.0 42000.0" ] }, - "execution_count": 5, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "#print the load active power (P) consumption\n", "network.loads_t.p" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", - "\n", "
now250.0650.042000.0
\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", "
South Africa OilSwaziland HydroMozambique HydroSouth Africa CoalSouth Africa WindSouth Africa GasSouth Africa CoalSouth Africa Oil
now0.03000.04000.0600.01050.035000.03000.03250.00.0
\n", "
" ], "text/plain": [ - " South Africa Oil South Africa Wind South Africa Gas South Africa Coal\n", - "now 0.0 3000.0 4000.0 35000.0" + " Swaziland Hydro Mozambique Hydro South Africa Coal South Africa Wind \\\n", + "now 600.0 1050.0 35000.0 3000.0 \n", + "\n", + " South Africa Gas South Africa Oil \n", + "now 3250.0 0.0 " ] }, - "execution_count": 6, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "#print the generator active power (P) dispatch\n", "network.generators_t.p" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 16, "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", "
now60.0-100.0-250.0-500.0
\n", "
" ], "text/plain": [ - " South Africa\n", - "now 60.0" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#print the clearing price (corresponding to gas)\n", - "network.buses_t.marginal_price" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Two bidding zones connected by transmission, one period\n", - "\n", - "In this example we have bidirectional transmission capacity between two bidding zones. The power transfer is treated as controllable (like an A/NTC (Available/Net Transfer Capacity) or HVDC line). Note that in the physical grid, power flows passively according to the network impedances." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "network = pypsa.Network()\n", - "\n", - "countries = [\"Mozambique\", \"South Africa\"]\n", - "\n", - "for country in countries:\n", - " \n", - " network.add(\"Bus\",country)\n", - "\n", - " for tech in power_plant_p_nom[country]:\n", - " network.add(\"Generator\",\n", - " \"{} {}\".format(country,tech),\n", - " bus=country,\n", - " p_nom=power_plant_p_nom[country][tech],\n", - " marginal_cost=marginal_costs[tech])\n", - "\n", - "\n", - " network.add(\"Load\",\n", - " \"{} load\".format(country),\n", - " bus=country,\n", - " p_set=loads[country])\n", - " \n", - " #add transmission as controllable Link\n", - " if country not in transmission:\n", - " continue\n", - " \n", - " for other_country in countries:\n", - " if other_country not in transmission[country]:\n", - " continue\n", - " \n", - " #NB: Link is by default unidirectional, so have to set p_min_pu = -1\n", - " #to allow bidirectional (i.e. also negative) flow\n", - " network.add(\"Link\",\n", - " \"{} - {} link\".format(country, other_country),\n", - " bus0=country,\n", - " bus1=other_country,\n", - " p_nom=transmission[country][other_country],\n", - " p_min_pu=-1)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:pypsa.pf:Slack bus for sub-network 0 is Mozambique\n", - "INFO:pypsa.pf:Slack bus for sub-network 1 is South Africa\n", - "INFO:pypsa.opf:Performed preliminary steps\n", - "INFO:pypsa.opf:Building pyomo model using angles formulation\n", - "INFO:pypsa.opf:Solving model using glpk\n", - "INFO:pypsa.opf:Optimization successful\n" - ] - }, - { - "data": { - "text/plain": [ - "('ok', 'optimal')" + " Mozambique - Swaziland link South Africa - Swaziland link \\\n", + "now -100.0 -250.0 \n", + "\n", + " South Africa - Mozambique link \n", + "now -500.0 " ] }, - "execution_count": 9, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "network.lopf()" + "network.links_t.p0" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 17, "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", "
now650.042000.00.00.060.0
\n", "
" ], "text/plain": [ - " Mozambique load South Africa load\n", - "now 650.0 42000.0" + " Swaziland Mozambique South Africa\n", + "now 0.0 0.0 60.0" ] }, - "execution_count": 10, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "network.loads_t.p" + "#print the clearing price (corresponding to hydro in S and M, and gas in SA)\n", + "network.buses_t.marginal_price" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 18, "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", "
Mozambique HydroSouth Africa OilSouth Africa WindSouth Africa GasSouth Africa CoalMozambique - Swaziland linkSouth Africa - Swaziland linkSouth Africa - Mozambique link
now1150.00.03000.03500.035000.060.060.0
\n", "
" ], "text/plain": [ - " Mozambique Hydro South Africa Oil South Africa Wind South Africa Gas \\\n", - "now 1150.0 0.0 3000.0 3500.0 \n", + " Mozambique - Swaziland link South Africa - Swaziland link \\\n", + "now 0.0 60.0 \n", "\n", - " South Africa Coal \n", - "now 35000.0 " + " South Africa - Mozambique link \n", + "now 60.0 " ] }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.generators_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
now-500.0
\n", - "
" - ], - "text/plain": [ - " South Africa - Mozambique link\n", - "now -500.0" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.links_t.p0" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
MozambiqueSouth Africa
now0.060.0
\n", - "
" - ], - "text/plain": [ - " Mozambique South Africa\n", - "now 0.0 60.0" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#print the clearing price (corresponding to water in Mozambique and gas in SA)\n", - "network.buses_t.marginal_price" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
now60.0
\n", - "
" - ], - "text/plain": [ - " South Africa - Mozambique link\n", - "now 60.0" - ] - }, - "execution_count": 15, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -671,1224 +506,6 @@ "#link shadow prices\n", "network.links_t.mu_lower" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Three bidding zones connected by transmission, one period\n", - "\n", - "In this example we have bidirectional transmission capacity between three bidding zones. The power transfer is treated as controllable (like an A/NTC (Available/Net Transfer Capacity) or HVDC line). Note that in the physical grid, power flows passively according to the network impedances." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "network = pypsa.Network()\n", - "\n", - "countries = [\"Swaziland\", \"Mozambique\", \"South Africa\"]\n", - "\n", - "for country in countries:\n", - " \n", - " network.add(\"Bus\",country)\n", - "\n", - " for tech in power_plant_p_nom[country]:\n", - " network.add(\"Generator\",\n", - " \"{} {}\".format(country,tech),\n", - " bus=country,\n", - " p_nom=power_plant_p_nom[country][tech],\n", - " marginal_cost=marginal_costs[tech])\n", - "\n", - "\n", - " network.add(\"Load\",\n", - " \"{} load\".format(country),\n", - " bus=country,\n", - " p_set=loads[country])\n", - " \n", - " #add transmission as controllable Link\n", - " if country not in transmission:\n", - " continue\n", - " \n", - " for other_country in countries:\n", - " if other_country not in transmission[country]:\n", - " continue\n", - " \n", - " #NB: Link is by default unidirectional, so have to set p_min_pu = -1\n", - " #to allow bidirectional (i.e. also negative) flow\n", - " network.add(\"Link\",\n", - " \"{} - {} link\".format(country, other_country),\n", - " bus0=country,\n", - " bus1=other_country,\n", - " p_nom=transmission[country][other_country],\n", - " p_min_pu=-1)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:pypsa.pf:Slack bus for sub-network 0 is Swaziland\n", - "INFO:pypsa.pf:Slack bus for sub-network 1 is Mozambique\n", - "INFO:pypsa.pf:Slack bus for sub-network 2 is South Africa\n", - "INFO:pypsa.opf:Performed preliminary steps\n", - "INFO:pypsa.opf:Building pyomo model using angles formulation\n", - "INFO:pypsa.opf:Solving model using glpk\n", - "INFO:pypsa.opf:Optimization successful\n" - ] - }, - { - "data": { - "text/plain": [ - "('ok', 'optimal')" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.lopf()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
now250.0650.042000.0
\n", - "
" - ], - "text/plain": [ - " Swaziland load Mozambique load South Africa load\n", - "now 250.0 650.0 42000.0" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.loads_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "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", - "
Swaziland HydroMozambique HydroSouth Africa OilSouth Africa WindSouth Africa GasSouth Africa Coal
now600.01050.00.03000.03250.035000.0
\n", - "
" - ], - "text/plain": [ - " Swaziland Hydro Mozambique Hydro South Africa Oil South Africa Wind \\\n", - "now 600.0 1050.0 0.0 3000.0 \n", - "\n", - " South Africa Gas South Africa Coal \n", - "now 3250.0 35000.0 " - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.generators_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
now-100.0-250.0-500.0
\n", - "
" - ], - "text/plain": [ - " Mozambique - Swaziland link South Africa - Swaziland link \\\n", - "now -100.0 -250.0 \n", - "\n", - " South Africa - Mozambique link \n", - "now -500.0 " - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.links_t.p0" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SwazilandMozambiqueSouth Africa
now0.00.060.0
\n", - "
" - ], - "text/plain": [ - " Swaziland Mozambique South Africa\n", - "now 0.0 0.0 60.0" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#print the clearing price (corresponding to hydro in S and M, and gas in SA)\n", - "network.buses_t.marginal_price" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
now0.060.060.0
\n", - "
" - ], - "text/plain": [ - " Mozambique - Swaziland link South Africa - Swaziland link \\\n", - "now 0.0 60.0 \n", - "\n", - " South Africa - Mozambique link \n", - "now 60.0 " - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#link shadow prices\n", - "network.links_t.mu_lower" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Single bidding zone with price-sensitive industrial load, one period\n", - "\n", - "In this example we consider a single market bidding zone, South Africa.\n", - "\n", - "Now there is a large industrial load with a marginal utility which is low enough to interact with the generation marginal cost." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "country = \"South Africa\"\n", - "\n", - "network = pypsa.Network()\n", - "\n", - "network.add(\"Bus\",country)\n", - "\n", - "for tech in power_plant_p_nom[country]:\n", - " network.add(\"Generator\",\n", - " \"{} {}\".format(country,tech),\n", - " bus=country,\n", - " p_nom=power_plant_p_nom[country][tech],\n", - " marginal_cost=marginal_costs[tech])\n", - "\n", - "#standard high marginal utility consumers\n", - "network.add(\"Load\",\n", - " \"{} load\".format(country),\n", - " bus=country,\n", - " p_set=loads[country])\n", - "\n", - "#add an industrial load as a dummy negative-dispatch generator with marginal utility of 70 EUR/MWh for 8000 MW\n", - "network.add(\"Generator\",\n", - " \"{} industrial load\".format(country),\n", - " bus=country,\n", - " p_max_pu=0,\n", - " p_min_pu=-1,\n", - " p_nom=8000,\n", - " marginal_cost=70)" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:pypsa.pf:Slack bus for sub-network 0 is South Africa\n", - "INFO:pypsa.opf:Performed preliminary steps\n", - "INFO:pypsa.opf:Building pyomo model using angles formulation\n", - "INFO:pypsa.opf:Solving model using glpk\n", - "INFO:pypsa.opf:Optimization successful\n" - ] - }, - { - "data": { - "text/plain": [ - "('ok', 'optimal')" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.lopf()" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
now42000.0
\n", - "
" - ], - "text/plain": [ - " South Africa load\n", - "now 42000.0" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.loads_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "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", - "
South Africa WindSouth Africa OilSouth Africa GasSouth Africa CoalSouth Africa industrial load
now3000.00.08000.035000.0-4000.0
\n", - "
" - ], - "text/plain": [ - " South Africa Wind South Africa Oil South Africa Gas South Africa Coal \\\n", - "now 3000.0 0.0 8000.0 35000.0 \n", - "\n", - " South Africa industrial load \n", - "now -4000.0 " - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#NB only half of industrial load is served, because this maxes out \n", - "#Gas. Oil is too expensive with a marginal cost of 80 EUR/MWh\n", - "network.generators_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SwazilandMozambiqueSouth Africa
now0.00.060.0
\n", - "
" - ], - "text/plain": [ - " Swaziland Mozambique South Africa\n", - "now 0.0 0.0 60.0" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.buses_t.marginal_price" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Single bidding zone with fixed load, several periods\n", - "\n", - "In this example we consider a single market bidding zone, South Africa.\n", - "\n", - "We consider multiple time periods (labelled [0,1,2,3]) to represent variable wind generation." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "country = \"South Africa\"\n", - "\n", - "network = pypsa.Network()\n", - "\n", - "#snapshots labelled by [0,1,2,3]\n", - "network.set_snapshots(range(4))\n", - "\n", - "network.add(\"Bus\",country)\n", - "\n", - "#p_max_pu is variable for wind\n", - "for tech in power_plant_p_nom[country]:\n", - " network.add(\"Generator\",\n", - " \"{} {}\".format(country,tech),\n", - " bus=country,\n", - " p_nom=power_plant_p_nom[country][tech],\n", - " marginal_cost=marginal_costs[tech],\n", - " p_max_pu=([0.3,0.6,0.4,0.5] if tech == \"Wind\" else 1),\n", - " )\n", - "\n", - "#load which varies over the snapshots\n", - "network.add(\"Load\",\n", - " \"{} load\".format(country),\n", - " bus=country,\n", - " p_set=loads[country] + np.array([0,1000,3000,4000]))" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:pypsa.pf:Slack bus for sub-network 0 is South Africa\n", - "INFO:pypsa.opf:Performed preliminary steps\n", - "INFO:pypsa.opf:Building pyomo model using angles formulation\n", - "INFO:pypsa.opf:Solving model using glpk\n", - "INFO:pypsa.opf:Optimization successful\n" - ] - }, - { - "data": { - "text/plain": [ - "('ok', 'optimal')" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#specify that we consider all snapshots\n", - "network.lopf(network.snapshots)" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "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", - "
042000.0
143000.0
245000.0
346000.0
\n", - "
" - ], - "text/plain": [ - " South Africa load\n", - "0 42000.0\n", - "1 43000.0\n", - "2 45000.0\n", - "3 46000.0" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.loads_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "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", - "
South Africa OilSouth Africa WindSouth Africa GasSouth Africa Coal
00.0900.06100.035000.0
10.01800.06200.035000.0
2800.01200.08000.035000.0
31500.01500.08000.035000.0
\n", - "
" - ], - "text/plain": [ - " South Africa Oil South Africa Wind South Africa Gas South Africa Coal\n", - "0 0.0 900.0 6100.0 35000.0\n", - "1 0.0 1800.0 6200.0 35000.0\n", - "2 800.0 1200.0 8000.0 35000.0\n", - "3 1500.0 1500.0 8000.0 35000.0" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.generators_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "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", - "
South Africa
060.0
160.0
280.0
380.0
\n", - "
" - ], - "text/plain": [ - " South Africa\n", - "0 60.0\n", - "1 60.0\n", - "2 80.0\n", - "3 80.0" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.buses_t.marginal_price" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Single bidding zone with fixed load and storage, several periods\n", - "\n", - "In this example we consider a single market bidding zone, South Africa.\n", - "\n", - "We consider multiple time periods (labelled [0,1,2,3]) to represent variable wind generation. Storage is allowed to do price arbitrage to reduce oil consumption." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "country = \"South Africa\"\n", - "\n", - "network = pypsa.Network()\n", - "\n", - "#snapshots labelled by [0,1,2,3]\n", - "network.set_snapshots(range(4))\n", - "\n", - "network.add(\"Bus\",country)\n", - "\n", - "#p_max_pu is variable for wind\n", - "for tech in power_plant_p_nom[country]:\n", - " network.add(\"Generator\",\n", - " \"{} {}\".format(country,tech),\n", - " bus=country,\n", - " p_nom=power_plant_p_nom[country][tech],\n", - " marginal_cost=marginal_costs[tech],\n", - " p_max_pu=([0.3,0.6,0.4,0.5] if tech == \"Wind\" else 1),\n", - " )\n", - "\n", - "#load which varies over the snapshots\n", - "network.add(\"Load\",\n", - " \"{} load\".format(country),\n", - " bus=country,\n", - " p_set=loads[country] + np.array([0,1000,3000,4000]))\n", - "\n", - "#storage unit to do price arbitrage\n", - "network.add(\"StorageUnit\",\n", - " \"{} pumped hydro\".format(country),\n", - " bus=country,\n", - " p_nom=1000,\n", - " max_hours=6, #energy storage in terms of hours at full power\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "INFO:pypsa.pf:Slack bus for sub-network 0 is South Africa\n", - "INFO:pypsa.opf:Performed preliminary steps\n", - "INFO:pypsa.opf:Building pyomo model using angles formulation\n", - "INFO:pypsa.opf:Solving model using glpk\n", - "INFO:pypsa.opf:Optimization successful\n" - ] - }, - { - "data": { - "text/plain": [ - "('ok', 'optimal')" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.lopf(network.snapshots)" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "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", - "
042000.0
143000.0
245000.0
346000.0
\n", - "
" - ], - "text/plain": [ - " South Africa load\n", - "0 42000.0\n", - "1 43000.0\n", - "2 45000.0\n", - "3 46000.0" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.loads_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "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", - "
South Africa OilSouth Africa WindSouth Africa GasSouth Africa Coal
00.0900.06900.035000.0
10.01800.07200.035000.0
20.01200.08000.035000.0
3500.01500.08000.035000.0
\n", - "
" - ], - "text/plain": [ - " South Africa Oil South Africa Wind South Africa Gas South Africa Coal\n", - "0 0.0 900.0 6900.0 35000.0\n", - "1 0.0 1800.0 7200.0 35000.0\n", - "2 0.0 1200.0 8000.0 35000.0\n", - "3 500.0 1500.0 8000.0 35000.0" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.generators_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "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", - "
South Africa pumped hydro
0-800.0
1-1000.0
2800.0
31000.0
\n", - "
" - ], - "text/plain": [ - " South Africa pumped hydro\n", - "0 -800.0\n", - "1 -1000.0\n", - "2 800.0\n", - "3 1000.0" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.storage_units_t.p" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "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", - "
South Africa pumped hydro
0800.0
11800.0
21000.0
30.0
\n", - "
" - ], - "text/plain": [ - " South Africa pumped hydro\n", - "0 800.0\n", - "1 1800.0\n", - "2 1000.0\n", - "3 0.0" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.storage_units_t.state_of_charge" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "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", - "
South Africa
060.0
160.0
260.0
380.0
\n", - "
" - ], - "text/plain": [ - " South Africa\n", - "0 60.0\n", - "1 60.0\n", - "2 60.0\n", - "3 80.0" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "network.buses_t.marginal_price" - ] } ], "metadata": { diff --git a/tutorial-4/solution04.pdf b/tutorial-4/solution04.pdf index 2c4e5c99fe3dbfdbae8a199656385e2f14cf5de6..7195a40d5cb2d0ad807186e7abd153c3cf79861a 100755 Binary files a/tutorial-4/solution04.pdf and b/tutorial-4/solution04.pdf differ diff --git a/tutorial-4/solution04.tex b/tutorial-4/solution04.tex index 3b4f5e8777eeec1b0f359feab5b758f95c98913e..24adca5f6adfd5f527dd4a641fa57e1f4d950731 100755 --- a/tutorial-4/solution04.tex +++ b/tutorial-4/solution04.tex @@ -103,11 +103,11 @@ \begin{document} \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Tutorial IV: Electricity Markets}}\\ - \small Will be worked on in the exercise session on Tuesday, 17 July 2018.\$1.5em] + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Solution IV: Electricity Markets}}\\ + \small Will be worked on in the exercise session on Tuesday, 17 July 2018.\\[1.5em] \end{center} \vspace{1em} @@ -118,206 +118,192 @@ Suppose that the utility for the electricity consumption of an industrial company is given by \[ -U(q) = 70q - 3q^2 [\textrm{\euro}/h] \quad , \quad q_{min}=2\leq q \leq q_{max}=10, + U(q) = 70q - 3q^2 [\textrm{\euro}/h] \quad , \quad q_{min}=2\leq q \leq q_{max}=10,$ where $q$ is the demand in MW and $q_{min}, q_{max}$ are the minimum and maximum demand. \\ [1em] Assume that the company is maximising its net surplus for a given electricity price $\pi$, i.e. it maximises $\max_{q} \left[U(q) - -\pi q\right]$. + \pi q\right]$. \begin{enumerate}[(a)] - \begin{shaded} \item If the price is$\pi = 5$~\euro/MWh, what is the optimal - demand$q^*$? What is the value of the KKT multiplier$\mu_{max}$- for the constraint$q \leq q_{max}=10$at this optimal solution? - What is the value of$\mu_{min}$for$q \geq q_{min} = 2?\end{shaded} - We convert the exercise to an optimisation problem with objective - $$- \max_q U(q) - \pi q -$$ - with constraints - \begin{align} - q & \leq q_{max} \hspace{1cm}\leftrightarrow\hspace{1cm} \m_{max} \\ - -q & \leq -q_{min} \hspace{1cm}\leftrightarrow\hspace{1cm} \m_{min} - \end{align} - - From stationarity we get: - \begin{align} - 0 & = \frac{\d}{\d q} \left(U(q) - \pi q\right) - \m_{max} \frac{\d}{\d q} (q-q_{max})- \m_{min} \frac{\d}{\d q} (-q+q_{min}) \\ - & = U'(q) - \pi - \m_{max} + \m_{min} \label{eq:2stat} - \end{align} - - The marginal utility curve isU'(q) = 70 - 6q$[\euro/MWh]. At -$\pi = 5$, the demand would be determined by$5=70-6q$, i.e.$q = - 65/6 = 10.8333$, which is above the consumption limit -$q_{max} = 10$. Therefore the optimal demand is$q^* = 10$, the upper limit is binding$\mu_{max} - \geq 0$and the lower limit is non-binding$\mu_{min} = 0$. - - To determine the value of$\mu_{max}$we use \eqref{eq:2stat} to get -$\m_{max} = U'(q^*) - \pi = U'(10) - 5 = 5$. - - \begin{shaded} - \item Suppose now the electricity price is$\pi = 60$~\euro/MWh. What are - the optimal demand$q^*$,$\mu_{max}$and$\mu_{min}$now? - \end{shaded} - -At$\pi = 60$, the demand would be determined by$60=70-6q$, i.e.$q = 10/6 = 1.667$, which is below the consumption limit$q_{min} = 2$. Therefore the optimal demand is$q^* = 2$, the upper limit is non-binding$\mu_{max} -= 0$and the lower limit is binding$\mu_{min} \geq 0$. - -To determine the value of$\mu_{min}$we use \eqref{eq:2stat} to get -$\m_{min} = \pi - U'(q^*) = 60 - U'(2) = 2$. + \begin{shaded} \item If the price is$\pi = 5$~\euro/MWh, what is the optimal + demand$q^*$? What is the value of the KKT multiplier$\mu_{max}$+ for the constraint$q \leq q_{max}=10$at this optimal solution? + What is the value of$\mu_{min}$for$q \geq q_{min} = 2?\end{shaded} + We convert the exercise to an optimisation problem with objective + $$+ \max_q U(q) - \pi q +$$ + with constraints + \begin{align} + q & \leq q_{max} \hspace{1cm}\leftrightarrow\hspace{1cm} \m_{max} \\ + -q & \leq -q_{min} \hspace{1cm}\leftrightarrow\hspace{1cm} \m_{min} + \end{align} + + From stationarity we get: + \begin{align} + 0 & = \frac{\d}{\d q} \left(U(q) - \pi q\right) - \m_{max} \frac{\d}{\d q} (q-q_{max})- \m_{min} \frac{\d}{\d q} (-q+q_{min}) \\ + & = U'(q) - \pi - \m_{max} + \m_{min} \label{eq:2stat} + \end{align} + + The marginal utility curve isU'(q) = 70 - 6q$[\euro/MWh]. At +$\pi = 5$, the demand would be determined by$5=70-6q$, i.e.$q = + 65/6 = 10.8333$, which is above the consumption limit +$q_{max} = 10$. Therefore the optimal demand is$q^* = 10$, the upper limit is binding$\mu_{max} + \geq 0$and the lower limit is non-binding$\mu_{min} = 0$. + + To determine the value of$\mu_{max}$we use \eqref{eq:2stat} to get +$\m_{max} = U'(q^*) - \pi = U'(10) - 5 = 5$. + + \begin{shaded} + \item Suppose now the electricity price is$\pi = 60$~\euro/MWh. What are + the optimal demand$q^*$,$\mu_{max}$and$\mu_{min}$now? + \end{shaded} + + At$\pi = 60$, the demand would be determined by$60=70-6q$, i.e.$q = 10/6 = 1.667$, which is below the consumption limit$q_{min} = 2$. Therefore the optimal demand is$q^* = 2$, the upper limit is non-binding$\mu_{max} + = 0$and the lower limit is binding$\mu_{min} \geq 0$. + + To determine the value of$\mu_{min}$we use \eqref{eq:2stat} to get +$\m_{min} = \pi - U'(q^*) = 60 - U'(2) = 2$. \end{enumerate} %=============== ====================================================== -\paragraph{Problem IV.2 \normalsize (Economic dispatch in a single bidding zone).}~\\ +\paragraph{Solution IV.2 \normalsize (Economic dispatch in a single bidding zone).}~\\ %===================================================================== Consider an electricity market with two generator types, one with variable cost$c = 20\emwh$, capacity$K = 300\mw$and a dispatch rate of$Q_1$~[MW] and another with variable cost$c=50\emwh$, capacity$K=400\mw$and a dispatch rate of$Q_2$~[MW]. The demand has utility function$U(Q) = 8000Q - 5Q^2$~[\euro/h] for a consumption rate of$Q~[MW]. \begin{enumerate}[(a)] - \begin{shaded}\item What are the objective function and constraints required for an optimisation problem to maximise short-run social welfare in this market?\end{shaded} - - The optimisation problem has objective function: - \begin{equation*} - \max_{Q,Q_1,Q_2}\left[ U(Q) - C_1(Q_1) - C_2(Q_2) \right] = \max_{Q,Q_1,Q_2} \left[8000Q-5Q^2 - c_2Q_1 - c_2Q_2 \right] - \end{equation*} - with constraints: - \begin{align*} - Q - Q_1 - Q_2 & = 0 \leftrightarrow \l \\ - Q_1 & \leq K_1 \leftrightarrow \bar{\m}_1 \\ - Q_2 & \leq K_2 \leftrightarrow \bar{\m}_2 \\ - -Q_1 & \leq 0 \leftrightarrow \ubar{\m}_1 \\ - -Q_2 & \leq 0 \leftrightarrow \ubar{\m}_2 - \end{align*} - - \begin{shaded}\item Write down the Karush-Kuhn-Tucker (KKT) conditions for this problem.\end{shaded} - - Stationarity gives forQ$: - \begin{equation*} - \frac{\d U}{\d Q} - \l = 8000 - 10Q - \l = 0 - \end{equation*} - Stationarity for$Q_1$gives: - \begin{equation*} - -\frac{\d C_1}{\d Q_1} + \l - \m_1 = -c_1+ \l - \bar{\m}_1 + \ubar{\m_1} = 0 - \end{equation*} - Stationarity for$Q_2$gives: - \begin{equation*} - -\frac{\d C_2}{\d Q_2} + \l - \m_2 = -c_2+ \l - \bar{\m}_2 + \ubar{\m_2} = 0 - \end{equation*} - Primal feasibility is just the constraints above. Dual feasibility is$\bar{\m}_i,\ubar{\m}_i \geq 0$and complementary slackness is$\bar{\m}_i(Q_i-K) = 0$and$\ubar{\m}_i Q_i = 0$for$i=1,2$. - - \begin{shaded}\item Determine the optimal rate of production of the generators and the value of all KKT multipliers. What is the interpretation of the respective KKT multipliers?\end{shaded} - The marginal utility at the full output of the generators,$K_1 - + K_2 = $700~MW is$U'(700) = 8000 - 10\cdot700 = 1000$\euro/MWh, - which is higher than the costs$c_i$, so we'll find optimal rates -$Q_1^* = K_1$and$Q_2^* = K_2$and$Q^* = K_1+K_2$. This means$\l - = U'(K_1+K_2) = 1000$\euro/MWh, which is the market price. Because - the lower constraints on the generator output are not binding, from - complementary slackness we have$\ubar{\m}_i = 0$. The upper - constraints are binding, so$\bar{\m}_i \geq 0$. - From stationarity$\bar{\m}_i = - \l - c_i$, which is the increase in social welfare if Generator$i- could increase its capacity by a marginal amount. + \begin{shaded}\item What are the objective function and constraints required for an optimisation problem to maximise short-run social welfare in this market?\end{shaded} + + The optimisation problem has objective function: + \begin{equation*} + \max_{Q,Q_1,Q_2}\left[ U(Q) - C_1(Q_1) - C_2(Q_2) \right] = \max_{Q,Q_1,Q_2} \left[8000Q-5Q^2 - c_2Q_1 - c_2Q_2 \right] + \end{equation*} + with constraints: + \begin{align*} + Q - Q_1 - Q_2 & = 0 \leftrightarrow \l \\ + Q_1 & \leq K_1 \leftrightarrow \bar{\m}_1 \\ + Q_2 & \leq K_2 \leftrightarrow \bar{\m}_2 \\ + -Q_1 & \leq 0 \leftrightarrow \ubar{\m}_1 \\ + -Q_2 & \leq 0 \leftrightarrow \ubar{\m}_2 + \end{align*} + + \begin{shaded}\item Write down the Karush-Kuhn-Tucker (KKT) conditions for this problem.\end{shaded} + + Stationarity gives forQ$: + \begin{equation*} + \frac{\d U}{\d Q} - \l = 8000 - 10Q - \l = 0 + \end{equation*} + Stationarity for$Q_1$gives: + \begin{equation*} + -\frac{\d C_1}{\d Q_1} + \l - \m_1 = -c_1+ \l - \bar{\m}_1 + \ubar{\m_1} = 0 + \end{equation*} + Stationarity for$Q_2$gives: + \begin{equation*} + -\frac{\d C_2}{\d Q_2} + \l - \m_2 = -c_2+ \l - \bar{\m}_2 + \ubar{\m_2} = 0 + \end{equation*} + Primal feasibility is just the constraints above. Dual feasibility is$\bar{\m}_i,\ubar{\m}_i \geq 0$and complementary slackness is$\bar{\m}_i(Q_i-K) = 0$and$\ubar{\m}_i Q_i = 0$for$i=1,2$. + + \begin{shaded}\item Determine the optimal rate of production of the generators and the value of all KKT multipliers. What is the interpretation of the respective KKT multipliers?\end{shaded} + The marginal utility at the full output of the generators,$K_1 + + K_2 = $700~MW is$U'(700) = 8000 - 10\cdot700 = 1000$\euro/MWh, + which is higher than the costs$c_i$, so we'll find optimal rates +$Q_1^* = K_1$and$Q_2^* = K_2$and$Q^* = K_1+K_2$. This means$\l + = U'(K_1+K_2) = 1000$\euro/MWh, which is the market price. Because + the lower constraints on the generator output are not binding, from + complementary slackness we have$\ubar{\m}_i = 0$. The upper + constraints are binding, so$\bar{\m}_i \geq 0$. + From stationarity$\bar{\m}_i = + \l - c_i$, which is the increase in social welfare if Generator$i$+ could increase its capacity by a marginal amount. \end{enumerate} -%%=============== ====================================================== -%\paragraph{Problem II.3 \normalsize (Revenue, profit and consumer surplus).}~\\ -%%===================================================================== -% -%Consider the example of bids and offers in an electricity market from -%slides 28 to 31 from Lecture 2 on 18.04.2016 (taken from the book -%Kirschen and Strbac pages 56-58). -% -%\begin{enumerate}[(a)] -% \item Compute the revenue and profit of each generating company and the net -% surplus of each consuming company. -% \item If consumer company Orange'' withdraws its offers from the market, how do the market price and the profits/surpluses of generators and consumers change? -%\end{enumerate} - %=============== ====================================================== -\paragraph{Problem IV.3 \normalsize (efficient dispatch in a two-bus power system).}~\\ +\paragraph{Solution IV.3 \normalsize (efficient dispatch in a two-bus power system).}~\\ %===================================================================== \begin{figure}[h] - \centering - \includegraphics[width=14cm]{two-bus} - \label{fig:two-bus} - \caption{A simple two-bus power system.} + \centering + \includegraphics[width=14cm]{two-bus} + \caption{A simple two-bus power system.} + \label{twobus} \end{figure} -Consider the two-bus power system shown in Figure \ref{fig:two-bus}, where the two nodes represent two markets, each with different total demand, and one generator at each node. At node A the demand is$D_A = 2000 \si{\mega\watt}$, whereas at node B the demand is$D_B = 1000 \si{\mega\watt}$. Furthermore, there is a transmission line with a capacity denoted by$F_{AB}$. The marginal cost of production of the generators connected to buses A and B are given respectively by the following expressions: +Consider the two-bus power system shown in Figure \ref{twobus}, where the two nodes represent two markets, each with different total demand, and one generator at each node. At node A the demand is$D_A = 2000 \si{\mega\watt}$, whereas at node B the demand is$D_B = 1000 \si{\mega\watt}$. Furthermore, there is a transmission line with a capacity denoted by$F_{AB}. The marginal cost of production of the generators connected to buses A and B are given respectively by the following expressions: \begin{align*} -MC_A & = 20 + 0.03 P_A \hspace{1cm}\eur/\si{\mega\watt\hour} \\ -MC_B & = 15 + 0.02 P_B \hspace{1cm} \eur/\si{\mega\watt\hour} + MC_A & = 20 + 0.03 P_A \hspace{1cm}\eur/\si{\mega\watt\hour} \\ + MC_B & = 15 + 0.02 P_B \hspace{1cm} \eur/\si{\mega\watt\hour} \end{align*} Assume that the demandD_*$is constant and insensitive to price, that energy is sold at its marginal cost of production and that there are no limits on the output of the generators. \begin{enumerate}[(a)] - \begin{shaded}\item Calculate the price of electricity at each bus, the production - of each generator, the flow on the line, and the value of any KKT - multipliers for the following cases:\end{shaded} - Use the following nomenclature: price$\lambda_i$, production$Q^{S}_i$, flow$F$. - \begin{enumerate}[(i)] - \begin{shaded}\item The line between buses A and B is disconnected.\end{shaded} -$\l_A= 80\emwh$,$\l_B=35\emwh$, - -$Q_{A}^S=2000$MW,$Q_B^S=1000$MW,$F=0$- - \begin{shaded}\item The line between buses A and B is in service and has an unlimited capacity.\end{shaded} -$\l_A= 53\emwh$,$\l_B=53\emwh$, - -$Q_{A}^S=1100\mw$,$Q_B^S=1900$MW,$F=-900\mw$- - \begin{shaded}\item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator B is 1500~MW.\end{shaded} -$\l_A= 65\emwh$,$\l_B=65\emwh$, - -$Q_{A}^S=1500\mw$,$Q_B^S=1500$MW,$F=-500\mw$- - \begin{shaded}\item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator A is 900~MW. The output of Generator B is unlimited.\end{shaded} -$\l_A= 57\emwh$,$\l_B=57\emwh$, - -$Q_{A}^S=900\mw$,$Q_B^S=2100$MW,$F=-1100\mw$- - \begin{shaded}\item The line between buses A and B is in service but its capacity is limited to 600~MW. The output of the generators is unlimited.\end{shaded} -$\l_A= 62\emwh$,$\l_B=47\emwh$, - -$Q_{A}^S=1400\mw$,$Q_B^S=1600$MW,$F=-600\mw$- \end{enumerate} - \begin{shaded}\item Calculate the generator revenues, generator profits, consumer payments and consumer net surplus for all the cases considered in the above problem. Who benefits from the line connecting these two buses?\end{shaded} - Generator revenues$R_{i}$, generator costs$C_{i}$, generator profits$P_{i}$, consumer payments$E_{i}$. Find the generator profits by substracting the costs from the revenue. Costs are given by integrating the marginal cost, i.e.$C_A = 20Q + 0.015Q^2$and$C_B = 15Q + 0.01Q^2$. The generator at$B$and the consumers at$A$benefit from the line (price increases at$B$, decreases at$B$). - \begin{table}[!h] - \centering - \begin{tabular}{lccccc} - \toprule - Case & i & ii & iii & iv & v\\ - \midrule -$E_A$(\euro) & 160000 & 106000 & 130000 & 114000 & 124000 \\ - \midrule -$E_B$(\euro) & 35000 & 53000 & 65000 & 57000 & 47000\\ - \midrule -$R_A$(\euro) & 160000 & 58300 & 97500 & 51300 & 86800 \\ - \midrule -$R_B$(\euro) & 35000 & 100700 & 97500 & 119700 & 75200\\ - \midrule -$C_A$(\euro) & 100000 & 40150 & 63750 & 30150 & 57400 \\ - \midrule -$C_B$(\euro) & 25000 & 64600 & 45000 & 75600 & 49600\\ - \midrule -$P_A$(\euro) & 60000 & 18150 & 33750 & 21150 & 29400 \\ - \midrule -$P_B$(\euro) & 10000 & 36100 & 52500 & 44100 & 25600\\ - \bottomrule - \end{tabular} - \end{table} - - \begin{shaded}\item Calculate the congestion surplus for case (v). For what values of the flow on the line between buses A and B is the congestion surplus equal to zero?\end{shaded} - Congestion surplus is 9000 \euro: - \begin{equation*} - \left(E_A + E_B\right) - (R_A + R_B) = |F|\times (\l_A - \l_B) - \end{equation*} - Congestion surplus is equal to zero when the flow$F=0$, or when it is equal to the unconstrained value$F=-900\mw$(then$\l_A = \l_B$). + \begin{shaded}\item Calculate the price of electricity at each bus, the production + of each generator, the flow on the line, and the value of any KKT + multipliers for the following cases:\end{shaded} + Use the following nomenclature: price$\lambda_i$, production$Q^{S}_i$, flow$F$. + \begin{enumerate}[(i)] + \begin{shaded}\item The line between buses A and B is disconnected.\end{shaded} +$\l_A= 80\emwh$,$\l_B=35\emwh$, + +$Q_{A}^S=2000$MW,$Q_B^S=1000$MW,$F=0$+ + \begin{shaded}\item The line between buses A and B is in service and has an unlimited capacity.\end{shaded} +$\l_A= 53\emwh$,$\l_B=53\emwh$, + +$Q_{A}^S=1100\mw$,$Q_B^S=1900$MW,$F=-900\mw$+ + \begin{shaded}\item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator B is 1500~MW.\end{shaded} +$\l_A= 65\emwh$,$\l_B=65\emwh$, + +$Q_{A}^S=1500\mw$,$Q_B^S=1500$MW,$F=-500\mw$+ + \begin{shaded}\item The line between buses A and B is in service and has an unlimited capacity, but the maximum output of Generator A is 900~MW. The output of Generator B is unlimited.\end{shaded} +$\l_A= 57\emwh$,$\l_B=57\emwh$, + +$Q_{A}^S=900\mw$,$Q_B^S=2100$MW,$F=-1100\mw$+ + \begin{shaded}\item The line between buses A and B is in service but its capacity is limited to 600~MW. The output of the generators is unlimited.\end{shaded} +$\l_A= 62\emwh$,$\l_B=47\emwh$, + +$Q_{A}^S=1400\mw$,$Q_B^S=1600$MW,$F=-600\mw$+ \end{enumerate} + \begin{shaded}\item Calculate the generator revenues, generator profits, consumer payments and consumer net surplus for all the cases considered in the above problem. Who benefits from the line connecting these two buses?\end{shaded} + Generator revenues$R_{i}$, generator costs$C_{i}$, generator profits$P_{i}$, consumer payments$E_{i}$. Find the generator profits by substracting the costs from the revenue. Costs are given by integrating the marginal cost, i.e.$C_A = 20Q + 0.015Q^2$and$C_B = 15Q + 0.01Q^2$. The generator at$B$and the consumers at$A$benefit from the line (price increases at$B$, decreases at$B$). + \begin{table}[!h] + \centering + \begin{tabular}{lccccc} + \toprule + Case & i & ii & iii & iv & v \\ + \midrule +$E_A$(\euro) & 160000 & 106000 & 130000 & 114000 & 124000 \\ + \midrule +$E_B$(\euro) & 35000 & 53000 & 65000 & 57000 & 47000 \\ + \midrule +$R_A$(\euro) & 160000 & 58300 & 97500 & 51300 & 86800 \\ + \midrule +$R_B$(\euro) & 35000 & 100700 & 97500 & 119700 & 75200 \\ + \midrule +$C_A$(\euro) & 100000 & 40150 & 63750 & 30150 & 57400 \\ + \midrule +$C_B$(\euro) & 25000 & 64600 & 45000 & 75600 & 49600 \\ + \midrule +$P_A$(\euro) & 60000 & 18150 & 33750 & 21150 & 29400 \\ + \midrule +$P_B$(\euro) & 10000 & 36100 & 52500 & 44100 & 25600 \\ + \bottomrule + \end{tabular} + \end{table} + + \begin{shaded}\item Calculate the congestion surplus for case (v). For what values of the flow on the line between buses A and B is the congestion surplus equal to zero?\end{shaded} + Congestion surplus is 9000 \euro: + \begin{equation*} + \left(E_A + E_B\right) - (R_A + R_B) = |F|\times (\l_A - \l_B) + \end{equation*} + Congestion surplus is equal to zero when the flow$F=0$, or when it is equal to the unconstrained value$F=-900\mw$(then$\l_A = \l_B$). \end{enumerate} %=============== ====================================================== -\paragraph{Problem IV.4 \normalsize (bidding in africa with pypsa).}~\\ +\paragraph{Solution IV.4 \normalsize (bidding in africa with pypsa).}~\\ %===================================================================== diff --git a/tutorial-5/sheet05.pdf b/tutorial-5/sheet05.pdf index 2611e3480c5b8dc0eb150e2a028e119613ac12f5..9c37bfdf366632b3f3443f97942c328fadc0f08c 100755 Binary files a/tutorial-5/sheet05.pdf and b/tutorial-5/sheet05.pdf differ diff --git a/tutorial-5/sheet05.tex b/tutorial-5/sheet05.tex index 813e3e8402d90082ae6db0e74c56b25e0ff5c337..525656be1a3a2f51a497e5caddd4034af7a657df 100755 --- a/tutorial-5/sheet05.tex +++ b/tutorial-5/sheet05.tex @@ -87,91 +87,83 @@ \begin{document} \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Tutorial V: Investment and Large Power Systems\\}} - \small Will be worked on in the exercise session on Wednesday, 18 July 2018.\\[1.5em] + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Tutorial V: Investment and Large Power Systems\\}} + \small Will be worked on in the exercise session on Wednesday, 18 July 2018.\\[1.5em] \end{center} \vspace{1em} %=============== ====================================================== -\paragraph{Problem V.1 \normalsize (duration curves and generation investment).}~\\ +\paragraph{Problem V.1 \normalsize (investment, generator and transmission constraints).}~\\ %===================================================================== -Let us suppose that demand is inelastic. The demand-duration curve is given by$Q=1000-1000z$. Suppose that there is a choice between coal and gas generation plants with a variable cost of 2 and 12~\euro/MWh, together with load-shedding at 1012\euro/MWh. The fixed costs of coal and gas generation are 15 and 10~\euro/MWh, respectively. +Two generators are connected to the grid by a single transmission +line (with no electrical demand on their side of the transmission line). A single company owns both the generators and the transmission line. Generator 1 has a linear cost curve$C(q) = 5 q$[\euro/h] and a capacity of 300~MW and Generator 2 has a linear cost curve$C(q) = 10 q$[\euro/h] and a capacity of 900~MW. The transmission line has a capacity of 1000~MW. Suppose the demand in the grid is always high enough to absorb the +generation from the two generators and that the market price of +electricity$\pi$is never below 15 \euro/MWh and averages 20 +\euro/MWh. \begin{enumerate}[(a)] - \item Describe the concept of a screening curve and how it helps to determine generation investment, given a demand-duration curve. - \item Plot the screening curve and find the intersections of the generation technologies. - \item Compute the long-term equilibrium power plant investment (optimal mix of generation) using PyPSA. - \item Plot the resulting price duration curve and the generation dispatch. Comment! - \item Demonstrate that the zero-profit condition is fulfilled. - \item While it can be shown that generators recover their cost in theory, name reasons why this might not be the case in reality. + \item Determine the full set of equations (objective function and + constraints) for the generators to optimise their dispatch to + maximise total economic welfare. + \item What is the optimal dispatch? + \item What are the values of the KKT multipliers for all the constraints in terms of$\pi$? + \item A new turbo-boosting technology can increase the capacity of Generator 1 from 300~MW to 350~MW. At what annualised capital cost would it be efficient to invest in this new technology? + \item A new high temperature conductor technology can increase the capacity of the transmission line by 200~MW. At what annualised capital cost would it be efficient to invest in this new technology? \end{enumerate} -%%=============== ====================================================== -%\paragraph{Problem II.4 \normalsize (investment, generator and transmission constraints).}~\\ -%%===================================================================== -% -%Two generators are connected to the grid by a single transmission -%line (with no electrical demand on their side of the transmission line). A single company owns both the generators and the transmission line. Generator 1 has a linear cost curve$C(q) = 5 q$[\euro/h] and a capacity of 300~MW and Generator 2 has a linear cost curve$C(q) = 10 q$[\euro/h] and a capacity of 900~MW. The transmission line has a capacity of 1000~MW. -% -%Suppose the demand in the grid is always high enough to absorb the -%generation from the two generators and that the market price of -%electricity$\pi$is never below 15 \euro/MWh and averages 20 -%\euro/MWh. -% -%\begin{enumerate}[(a)] -% \item Determine the full set of equations (objective function and -% constraints) for the generators to optimise their dispatch to -% maximise total economic welfare. -% \item What is the optimal dispatch? -% \item What are the values of the KKT multipliers for all the constraints in terms of$\pi$? -% \item A new turbo-boosting technology can increase the capacity of Generator 1 from 300~MW to 350~MW. At what annualised capital cost would it be efficient to invest in this new technology? -% \item A new high temperature conductor technology can increase the capacity of the transmission line by 200~MW. At what annualised capital cost would it be efficient to invest in this new technology? -%\end{enumerate} +%=============== ====================================================== +\paragraph{Problem V.2 \normalsize (duration curves and generation investment).}~\\ +%===================================================================== + +Let us suppose that demand is inelastic. The demand-duration curve is given by$Q=1000-1000z$. Suppose that there is a choice between coal and gas generation plants with a variable cost of 2 and 12~\euro/MWh, together with load-shedding at 1012\euro/MWh. The fixed costs of coal and gas generation are 15 and 10~\euro/MWh, respectively. + +\begin{enumerate}[(a)] + \item Describe the concept of a screening curve and how it helps to determine generation investment, given a demand-duration curve. + \item Plot the screening curve and find the intersections of the generation technologies. + \item Compute the long-term equilibrium power plant investment (optimal mix of generation) using PyPSA. + \item Plot the resulting price duration curve and the generation dispatch. Comment! + \item Demonstrate that the zero-profit condition is fulfilled. + \item While it can be shown that generators recover their cost in theory, name reasons why this might not be the case in reality. +\end{enumerate} %=============== ====================================================== -\paragraph{Problem V.2 \normalsize (generator dispatch with SciGRID).}~\\ +\paragraph{Problem V.3 \normalsize (generator dispatch with SciGRID).}~\\ %===================================================================== -SciGRID\footnote{\url{https://www.scigrid.de/pages/general-information.html}} is a project that provides an open source reference model of the European transmission networks. In this tutorial, other than previous simple examples, you will examine the economic dispatch of many generators all over Germany and its effect on the power system. The data files for this example and a populated Jupyter notebook are provided on the course homepage\footnote{\url{https://nworbmot.org/courses/complex_renewable_energy_networks/}}. The dataset comprises time series for loads and the availability of renewable generation at an hourly resolution for the year 2011. Feel free to choose a day to your liking; we will later discuss your different outcomes in groups. A few days might be of particular interest: -\begin{itemize} - \item \texttt{2011-01-31} was the least windy day of 2011 - \item \texttt{2011-02-05} was a stormy day with lots of wind energy production, - \item \texttt{2011-07-12} the weather 7 years ago was very sunny day, and - \item \texttt{2011-09-06} was a windy and sunny autumn day. -\end{itemize} +SciGRID\footnote{\url{https://www.scigrid.de/pages/general-information.html}} is a project that provides an open source reference model of the European transmission networks. In this tutorial, other than previous simple examples, you will examine the economic dispatch of many generators all over Germany and its effect on the power system. The data files for this example and a populated Jupyter notebook are provided on the course homepage\footnote{\url{https://nworbmot.org/courses/complex_renewable_energy_networks/}}. The dataset comprises time series for loads and the availability of renewable generation at an hourly resolution for the year 2011. Feel free to choose a day to your liking; we will later discuss your different outcomes in groups. A few days might be of particular interest: \texttt{2011-01-31} was the least windy day of 2011, \texttt{2011-02-05} was a stormy day with lots of wind energy production, \texttt{2011-07-12} the weather 7 years ago was very sunny day, and \texttt{2011-09-06} was a windy and sunny autumn day. \begin{enumerate}[(a)] - \item Describe the network as well as its regional and temporal characteristics. - \begin{enumerate}[(i)] - \item Plot the aggregated load curve. - \item Plot the total generation capacities grouped by generation technology. Why is the share of capacity for renewables higher than the share of electricity produced? - \item Plot the regional distribution of the loads for different snapshots. What are the major load centres? - \item Plot the regional distribution of generation technologies. Comment! - \end{enumerate} - \item Run a linear optimal power flow to obtain the economic dispatch and analyse the results. - \begin{enumerate}[(i)] - \item To approximate n-1 security and allow room for reactive power flows, set the maximum line loading of any line in the network to 70 \% of their thermal rating. - \item Plot the hourly dispatch grouped by carrier for the chosen day. Comment! - \item Plot the aggregate dispatch of the pumped hydro storage units and the state of charge throughout the day and describe how they are used throughout the day. - \item Show the line loadings for different snapshots on the network. Can you identify a regional concentration of highly loaded branches? - \item Plot the locational marginal prices for snapshots on the network. What is the interpretation of high and low marginal prices? What do the geographical differences of nodal prices tell you about the regional generation capacity, load centres and the state of the transmission network? - \item Plot the curtailment for on- and offshore wind as well as for solar energy on the chosen day. Why is variable renewable electricity curtailed? Would there still be curtailment if there were unlimited transmission capacity? What happens to the nodal prices in this case? - \end{enumerate} - \item Perform a non-linear power flow (Newton-Raphson) on the injections determined by the linear optimal power flow. - \begin{enumerate}[(i)] - \item Plot the regional and temporal distribution of reactive power feed-in. What is the consequence of reactive flows in terms of the network's transfer capacity? - \item Analyse whether the chosen security constraint for thermal line loading was sufficient. What happens if you omit the security constraint or require an even higher security constraint? - \end{enumerate} + \item Describe the network as well as its regional and temporal characteristics. + \begin{enumerate}[(i)] + \item Plot the aggregated load curve. + \item Plot the total generation capacities grouped by generation technology. Why is the share of capacity for renewables higher than the share of electricity produced? + \item Plot the regional distribution of the loads for different snapshots. What are the major load centres? + \item Plot the regional distribution of generation technologies. Comment! + \end{enumerate} + \item Run a linear optimal power flow to obtain the economic dispatch and analyse the results. + \begin{enumerate}[(i)] + \item To approximate n-1 security and allow room for reactive power flows, set the maximum line loading of any line in the network to 70 \% of their thermal rating. + \item Plot the hourly dispatch grouped by carrier for the chosen day. Comment! + \item Plot the aggregate dispatch of the pumped hydro storage units and the state of charge throughout the day and describe how they are used throughout the day. + \item Show the line loadings for different snapshots on the network. Can you identify a regional concentration of highly loaded branches? + \item Plot the locational marginal prices for snapshots on the network. What is the interpretation of high and low marginal prices? What do the geographical differences of nodal prices tell you about the regional generation capacity, load centres and the state of the transmission network? + \item Plot the curtailment for on- and offshore wind as well as for solar energy on the chosen day. Why is variable renewable electricity curtailed? Would there still be curtailment if there were unlimited transmission capacity? What happens to the nodal prices in this case? + \end{enumerate} + \item Perform a non-linear power flow (Newton-Raphson) on the injections determined by the linear optimal power flow. + \begin{enumerate}[(i)] + \item Plot the regional and temporal distribution of reactive power feed-in. What is the consequence of reactive flows in terms of the network's transfer capacity? + \item Analyse whether the chosen security constraint for thermal line loading was sufficient. What happens if you omit the security constraint or require an even higher security constraint? + \end{enumerate} \end{enumerate} %=============== ====================================================== -\paragraph{Problem V.3 \normalsize (network clustering).}~\\ +\paragraph{Problem V.4 \normalsize (network clustering).}~\\ %===================================================================== \end{document} diff --git a/tutorial-5/solution05.pdf b/tutorial-5/solution05.pdf index ada2ac5c48c46d50988aa95925a42662f04390cb..eea757789c5ace24a6dd7eff9e6bf22cdf0526a1 100755 Binary files a/tutorial-5/solution05.pdf and b/tutorial-5/solution05.pdf differ diff --git a/tutorial-5/solution05.tex b/tutorial-5/solution05.tex index 304365eaa3e152793c08b8f0e16694be2006622c..7882b765a57d0849bf445e2eb3a1a7782505a58a 100755 --- a/tutorial-5/solution05.tex +++ b/tutorial-5/solution05.tex @@ -75,6 +75,23 @@ \DeclareSIUnit{\dollar}{\$} \newcommand{\eur}{\text{\EUR{}}} +\newcommand{\lgans}{\textquotedblleft} +\newcommand{\rgans}{\textquotedblright} +\newcommand{\D}{\Delta} + +\def\l{\lambda} +\def\m{\mu} +\def\d{\partial} +\def\nn{\nonumber} + + +\newcommand{\ubar}[1]{\text{\b{$#1$}}} + + +\newcommand{\E}{\mathbb{E}} +\newcommand{\dx}[1]{\mbox{d}{#1}} +\renewcommand{\vec}[1]{{\bf #1}} + \usepackage{palatino} \usepackage{mathpazo} \setlength\parindent{0pt} @@ -87,154 +104,216 @@ \begin{document} \begin{center} - \textbf{\Large Energy System Modelling }\\ - {SS 2018, Karlsruhe Institute of Technology}\\ - {Institute of Automation and Applied Informatics}\\ [1em] - \textbf{\textsc{\Large Tutorial V: Investment Optimisation}}\\ - \small Will be worked on in the exercise session on Wednesday, 18 July 2018.\\[1.5em] + \textbf{\Large Energy System Modelling }\\ + {SS 2018, Karlsruhe Institute of Technology}\\ + {Institute of Automation and Applied Informatics}\\ [1em] + \textbf{\textsc{\Large Solution V: Investment and Large Power Systems}}\\ + \small Will be worked on in the exercise session on Wednesday, 18 July 2018.\\[1.5em] \end{center} \vspace{1em} %=============== ====================================================== -\paragraph{Problem V.1 \normalsize (duration curves and generation investment).}~\\ +\paragraph{Solution V.1 \normalsize (investment, generator and transmission constraints).}~\\ +%===================================================================== + +Two generators are connected to the grid by a single transmission +line (with no electrical demand on their side of the transmission line). A single company owns both the generators and the transmission line. Generator 1 has a linear cost curve $C(q) = 5 q$ [\euro/h] and a capacity of 300~MW and Generator 2 has a linear cost curve $C(q) = 10 q$ [\euro/h] and a capacity of 900~MW. The transmission line has a capacity of 1000~MW. Suppose the demand in the grid is always high enough to absorb the +generation from the two generators and that the market price of +electricity $\pi$ is never below 15 \euro/MWh and averages 20 +\euro/MWh. + +\begin{enumerate}[(a)] + \begin{shaded}\item Determine the full set of equations (objective function and + constraints) for the generators to optimise their dispatch to + maximise total economic welfare.\end{shaded} + + Note that it is important in this example that the same company owns + both the generators and the transmission line; if an independent TSO + owned the transmission line, he could take the congestion revenue for + himself. + + If we label the dispatch of Generator 1 by $q_1$ and of Generator 2 by $q_2$, then the objective function is to maximise total profit + \begin{equation*} + \max_{q_1,q_2} \left[ \pi (q_1+q_2) - C_1(q_1) - C_2(q_2) \right] = \max_{q_1,q_2} \left[ \pi (q_1+q_2) - 5q_1 - 10q_2 \right] + \end{equation*} + + The constraints are + \begin{align*} + q_1 & \leq \hat q_1 & \leftrightarrow & \bar{\m}_1 \\ + -q_1 & \leq 0 & \leftrightarrow & \ubar{\m}_1 \\ + q_2 & \leq \hat q_2 & \leftrightarrow & \bar{\m}_2 \\ + -q_2 & \leq 0 & \leftrightarrow & \ubar{\m}_2 \\ + q_1+q_2 & \leq K & \leftrightarrow & \m_T + \end{align*} + Where the first four constraints come from generation, where $\hat q_1 =$ 300 MW and $\hat q_1 =$ 900 MW and the final constraint comes from the transmission, where $K =$ 1000~MW is the capacity of the export transmission line. + + \begin{shaded}\item What is the optimal dispatch?\end{shaded} + + Since the market price is always higher than the marginal price + of the generators, they will both run as high as possible given the + constraints. Since Generator 1 is cheaper than Generator 2, it will + max-out its capacity first, so that $q_1^* = \hat q_1 =$ 300~MW. Generator 2 will output as much as it can given the transmission constraint, so that $q_2^* =$ 700~MW. + + \begin{shaded}\item What are the values of the KKT multipliers for all the constraints in terms of $\pi$?\end{shaded} + + From stationarity we have for $q_1$ the non-zero terms: + \begin{align*} + 0 & = \frac{\d}{\d q_1} \left( \pi (q_1+q_2) - 5q_1 - 10q_2\right) - \bar{\m}_1 \frac{\d}{\d q_1} (q_1-\hat q_1)- \ubar{m}_1 \frac{\d}{\d q_1} (-q_1) -\m_T \frac{\d}{\d q_1} (q_1+q_2-K) \nn \\ + & = \pi -5 - \bar{\m}_1 + \ubar{\m}_1 - \m_T + \end{align*} + For $q_2$ we have + \begin{align*} + 0 & = \frac{\d}{\d q_2} \left( \pi (q_1+q_2) - 5q_1 - 10q_2\right) - \bar{\m}_2 \frac{\d}{\d q_2} (q_2-\hat q_2)- \ubar{m}_2 \frac{\d}{\d q_2} (-q_2) -\m_T \frac{\d}{\d q_2} (q_1+q_2-K) \nn \\ + & = \pi - 10- \bar{\m}_2 + \ubar{\m}_2 - \m_T + \end{align*} + + At the optimal point we can see that $\ubar{\m}_1$, $\bar{\m}_2$ and $\ubar{\m}_2$ are non-binding, so these are zero. To solve for $\m_T$ and $\bar{\m}_1$ we have two equations: + \begin{align*} + 0 & = \pi - 5 - \bar{\m}_1 - \m_T \nn \\ + 0 & = \pi - 10 - \m_T + \end{align*} + Therefore + \begin{align*} + \m_T & = \pi - 10 \\ + \bar{\m}_1 & = 5 + \end{align*} + + \begin{shaded}\item A new turbo-boosting technology can increase the capacity of Generator 1 from 300~MW to 350~MW. At what annualised capital cost would it be efficient to invest in this new technology?\end{shaded} + + The value of $\bar{\m}_1$ gives us the increase in profit for a small increase in $\hat{q}_1$. We want to understand a large increase in $\hat{q}_1$ of 50 MW, therefore we have to integrate over $\bar{\m}_1$ as a function of $\hat{q}_1$, since the value of $\bar{\m}_1$ may change as $\hat{q}_1$ changes. The total increase in profitability for expanding $\hat{q}_1$ from 300~MW to 350~MW is then + \begin{equation*} + \int_{300}^{350} \bar{\m}_1(\hat{q}_1) d\hat{q}_1 + \end{equation*} + Because of the linearity of the problem, $\bar{\m}_1$ is actually constant as we expand $\hat{q}_1$ in the region from 300~MW to 350~MW. The extra profit would be per year: 5 \euro/MWh * 50 MW * 8760h/a = \euro 2.19 million/a. + At or below this annualised capital cost, it would be worth investing. + + \begin{shaded}\item A new high temperature conductor technology can increase the capacity of the transmission line by 200~MW. At what annualised capital cost would it be efficient to invest in this new technology?\end{shaded} + + Here $\m_T$ changes as $K$ is expanded, so we have to integrate: + \begin{equation*} + \int_{1000}^{1200} \m_T(K) dK + \end{equation*} + Since $\m_T$ is constant as we expand $K$ from 1000~MW to 1200~MW, the extra profit would be per year: (average$(\pi)$-10) \euro/MWh * 200 MW * 8760h/a = \euro 17.52 million/a. + At or below this annualised capital cost, it would be worth investing. An extension beyond 1200~MW would not bring anything, because the generator constraints would be then binding. +\end{enumerate} +%=============== ====================================================== +\paragraph{Solution V.2 \normalsize (duration curves and generation investment).}~\\ %===================================================================== Let us suppose that demand is inelastic. The demand-duration curve is given by $Q=1000-1000z$. Suppose that there is a choice between coal and gas generation plants with a variable cost of 2 and 12~\euro/MWh, together with load-shedding at 1012\euro/MWh. The fixed costs of coal and gas generation are 15 and 10~\euro/MWh, respectively. \begin{enumerate}[(a)] - \begin{shaded} - \item Describe the concept of a screening curve and how it helps to determine generation investment, given a demand-duration curve. - \end{shaded} - -A screening curve plots the costs of different generators as a -function of their utilization/capacity/usage factor so that they can -be compared based on their fixed and variable costs. The utilization -factor is plotted along the $x$ axis from 0 to 1, 0 corresponding to -no running time, 1 corresponding to the power plant running 100\% of -the time. The intercept of the curve of each generator with the $y$ -axis is given by the fixed cost $f$ [\euro/MWh] (i.e. the cost with no -variable costs) and the slope is given by the variable cost $c$ -[\euro/MWh]. - -The interception points of the linear curves of the different -generators determine the ranges of utilization factors in which one -generator is cheaper than another. By comparing the screening curves with the demand duration curve, the -correct generator capacities for different utilisation factors can be -determined (e.g. how much baseload power is required, how much peaking -power is required, how much load shedding). - - \begin{shaded}\item Plot the screening curve and find the intersections of the generation technologies.\end{shaded} - First we work out the intersection points of - the generators as a function of their capacity factors (percentage of - time that they operate at full power per year), then we work out the - capacities $K_*$ of the generators. - - The screening curves tell us above which capacity factor it costs less - to run one type of generator rather than another. - - - \begin{table}[!h] - \centering - \begin{tabular}{lrr} - \toprule - Generator & $c_i$ [\euro/MWh] & $f_i$ [\euro/MWh] \\ - \midrule - coal & 2 & 15 \\ - gas & 12 & 10 \\ - load-shedding & 1012 & 0 \\ - \bottomrule - \end{tabular} - \end{table} - - Generators coal and gas intersect at $x_{cg}$ given by - \begin{equation*} - 15 + 2x_{cg} = 10 + 12x_{cg} - \end{equation*} - i.e. $x_{cg}=0.5$. This means that if the coal generator can run more than 50\% of the time, it should be built from an economic perspective. - - Gas generator and load-shedding intersect at $x_{gl}$ given by - \begin{equation*} - 10 + 12x_{gl} = 1012x_{gl} - \end{equation*} - i.e.\ $x_{gl}=1/100$. This means that for 1\% of the time we have load-shedding because it's not economical to cover the rare times of very high load. - - \begin{shaded}\item Compute the long-term equilibrium power plant investment (optimal mix of generation) using PyPSA.\end{shaded} - - The amount of load that is present at least $x_{cg}$ of the time determines $K_{coal}$, which we find by solving based on the load duration curve - \begin{equation*} - 1000-1000x_{cg} = K_{coal} \xRightarrow{x_{cg}=0.5} K_{coal} = 500 - \end{equation*} - - To get the capacity of the gas generator we solve based on the load duration curve - \begin{equation*} - 1000-1000x_{gl}=K_{coal}+ K_{gas} \xRightarrow{x_{cg}=0.5 \text{ and } K_{coal}=500} K_{gas} = 490 - \end{equation*} - - Load above $K_{coal}+ K_{gas}=990$ is shed. Thus, $K_{load-shedding}=10$. - - \begin{shaded}\item Plot the resulting price duration curve and the generation dispatch. Comment!\end{shaded} - cf.\ Jupyter Notebook - \begin{shaded}\item Demonstrate that the zero-profit condition is fulfilled.\end{shaded} - cf.\ Jupyter Notebook - \begin{shaded} - \item While it can be shown that generators recover their cost in theory, name reasons why this might not be the case in reality. - \end{shaded} - Several factors make this theoretical picture quite different in reality: - \begin{itemize} - \item Generation investment is lumpy; i.e. you can often only - build power stations in e.g. 500~MW blocks, not in continuous chunks. - \item Some older generators have sunk costs, i.e. costs which have been incurred once and cannot be recovered, which alters their behaviour (i.e. the $f$ term is not evenly distributed across all hours) - \item Returns on scale in building plant are not taken into account (we did everything linear) - \item Site-specific concerns ignored (e.g. lignite might need to be near a mine and have limited capacity) - \item Variability of production for wind/solar ignored - \item There is considerable uncertainty given load/weather conditions during a year, which makes investment risky; economic downturns reduce electricity demand - \item Fuel cost fluctuations, building delays which cost money - \item Risks from third-parties: Changing costs of other generators, political risks (carbon taxes, Atomausstieg, subsidies for renewables, price caps) - \item Political or administrative constraints on wholesale energy - prices may prevent prices from rising high enough for long enough - to justify generation investment (Missing Money Problem'') - \item Lead-in time for planning and building, behaviour of others, boom-and-bust investment cycles resulting from periods of under- and over-investment in capacity - \item Exercise of market power - \end{itemize} + \begin{shaded} + \item Describe the concept of a screening curve and how it helps to determine generation investment, given a demand-duration curve. + \end{shaded} + + A screening curve plots the costs of different generators as a + function of their utilization/capacity/usage factor so that they can + be compared based on their fixed and variable costs. The utilization + factor is plotted along the $x$ axis from 0 to 1, 0 corresponding to + no running time, 1 corresponding to the power plant running 100\% of + the time. The intercept of the curve of each generator with the $y$ + axis is given by the fixed cost $f$ [\euro/MWh] (i.e. the cost with no + variable costs) and the slope is given by the variable cost $c$ + [\euro/MWh]. + + The interception points of the linear curves of the different + generators determine the ranges of utilization factors in which one + generator is cheaper than another. By comparing the screening curves with the demand duration curve, the + correct generator capacities for different utilisation factors can be + determined (e.g. how much baseload power is required, how much peaking + power is required, how much load shedding). + + \begin{shaded}\item Plot the screening curve and find the intersections of the generation technologies.\end{shaded} + First we work out the intersection points of + the generators as a function of their capacity factors (percentage of + time that they operate at full power per year), then we work out the + capacities $K_*$ of the generators. + + The screening curves tell us above which capacity factor it costs less + to run one type of generator rather than another. + + + \begin{table}[!h] + \centering + \begin{tabular}{lrr} + \toprule + Generator & $c_i$ [\euro/MWh] & $f_i$ [\euro/MWh] \\ + \midrule + coal & 2 & 15 \\ + gas & 12 & 10 \\ + load-shedding & 1012 & 0 \\ + \bottomrule + \end{tabular} + \end{table} + + Generators coal and gas intersect at $x_{cg}$ given by + \begin{equation*} + 15 + 2x_{cg} = 10 + 12x_{cg} + \end{equation*} + i.e. $x_{cg}=0.5$. This means that if the coal generator can run more than 50\% of the time, it should be built from an economic perspective. + + Gas generator and load-shedding intersect at $x_{gl}$ given by + \begin{equation*} + 10 + 12x_{gl} = 1012x_{gl} + \end{equation*} + i.e.\ $x_{gl}=1/100$. This means that for 1\% of the time we have load-shedding because it's not economical to cover the rare times of very high load. + + \begin{shaded}\item Compute the long-term equilibrium power plant investment (optimal mix of generation) using PyPSA.\end{shaded} + + The amount of load that is present at least $x_{cg}$ of the time determines $K_{coal}$, which we find by solving based on the load duration curve + \begin{equation*} + 1000-1000x_{cg} = K_{coal} \xRightarrow{x_{cg}=0.5} K_{coal} = 500 + \end{equation*} + + To get the capacity of the gas generator we solve based on the load duration curve + \begin{equation*} + 1000-1000x_{gl}=K_{coal}+ K_{gas} \xRightarrow{x_{cg}=0.5 \text{ and } K_{coal}=500} K_{gas} = 490 + \end{equation*} + + Load above $K_{coal}+ K_{gas}=990$ is shed. Thus, $K_{load-shedding}=10$. + + \begin{shaded}\item Plot the resulting price duration curve and the generation dispatch. Comment!\end{shaded} + cf.\ Jupyter Notebook + \begin{shaded}\item Demonstrate that the zero-profit condition is fulfilled.\end{shaded} + cf.\ Jupyter Notebook + \begin{shaded} + \item While it can be shown that generators recover their cost in theory, name reasons why this might not be the case in reality. + \end{shaded} + Several factors make this theoretical picture quite different in reality: + \begin{itemize} + \item Generation investment is lumpy; i.e. you can often only + build power stations in e.g. 500~MW blocks, not in continuous chunks. + \item Some older generators have sunk costs, i.e. costs which have been incurred once and cannot be recovered, which alters their behaviour (i.e. the $f$ term is not evenly distributed across all hours) + \item Returns on scale in building plant are not taken into account (we did everything linear) + \item Site-specific concerns ignored (e.g. lignite might need to be near a mine and have limited capacity) + \item Variability of production for wind/solar ignored + \item There is considerable uncertainty given load/weather conditions during a year, which makes investment risky; economic downturns reduce electricity demand + \item Fuel cost fluctuations, building delays which cost money + \item Risks from third-parties: Changing costs of other generators, political risks (carbon taxes, Atomausstieg, subsidies for renewables, price caps) + \item Political or administrative constraints on wholesale energy + prices may prevent prices from rising high enough for long enough + to justify generation investment (Missing Money Problem'') + \item Lead-in time for planning and building, behaviour of others, boom-and-bust investment cycles resulting from periods of under- and over-investment in capacity + \item Exercise of market power + \end{itemize} \end{enumerate} -%%=============== ====================================================== -%\paragraph{Problem II.4 \normalsize (investment, generator and transmission constraints).}~\\ -%%===================================================================== -% -%Two generators are connected to the grid by a single transmission -%line (with no electrical demand on their side of the transmission line). A single company owns both the generators and the transmission line. Generator 1 has a linear cost curve $C(q) = 5 q$ [\euro/h] and a capacity of 300~MW and Generator 2 has a linear cost curve $C(q) = 10 q$ [\euro/h] and a capacity of 900~MW. The transmission line has a capacity of 1000~MW. -% -%Suppose the demand in the grid is always high enough to absorb the -%generation from the two generators and that the market price of -%electricity $\pi$ is never below 15 \euro/MWh and averages 20 -%\euro/MWh. -% -%\begin{enumerate}[(a)] -% \item Determine the full set of equations (objective function and -% constraints) for the generators to optimise their dispatch to -% maximise total economic welfare. -% \item What is the optimal dispatch? -% \item What are the values of the KKT multipliers for all the constraints in terms of $\pi$? -% \item A new turbo-boosting technology can increase the capacity of Generator 1 from 300~MW to 350~MW. At what annualised capital cost would it be efficient to invest in this new technology? -% \item A new high temperature conductor technology can increase the capacity of the transmission line by 200~MW. At what annualised capital cost would it be efficient to invest in this new technology? -%\end{enumerate} + %=============== ====================================================== -\paragraph{Problem V.2 \normalsize (generator dispatch with SciGRID).}~\\ +\paragraph{Solution V.3 \normalsize (generator dispatch with SciGRID).}~\\ %===================================================================== cf. Jupyter Notebook %=============== ====================================================== -\paragraph{Problem V.3 \normalsize (network clustering).}~\\ +\paragraph{Solution V.4 \normalsize (network clustering).}~\\ %===================================================================== -cf. Jupyter Notebook - \end{document}