# Minimum outputs first, then each plant's remaining capacity in order of cost
order = sortperm(gens[thermal, :VarCost])
widths = gens[thermal, :Pmax][order] .- gens[thermal, :Pmin][order]
heights = gens[thermal, :VarCost][order]
must_run = sum(gens[thermal, :Pmin])
left_edges = must_run .+ [0; cumsum(widths)[1:end-1]]
marginal = findfirst(left_edges .+ widths .>= demand_mw)
stack_price = heights[marginal]
rectangle(w, h, x) = Shape(x .+ [0, w, w, 0], [0, 0, h, h])
p_stack = plot(rectangle(must_run, 2.5, 0), color=:gray60, linewidth=0.5,
xlabel="Cumulative capacity [MW]", ylabel="Marginal cost [\$/MWh]",
xlims=(0, 2500), ylims=(0, 120), xticks=0:500:2500)
for i in eachindex(order)
if i == marginal
bar_color = cb_vermillion # the plant that sets the price
else
bar_color = cb_blue
end
plot!(p_stack, rectangle(widths[i], max(heights[i], 2.5), left_edges[i]),
color=bar_color, alpha=0.6, linewidth=0.5)
end
vline!(p_stack, [demand_mw], color=:black, linestyle=:dash, linewidth=3)
hline!(p_stack, [stack_price], color=cb_vermillion, linestyle=:dot, linewidth=3)
annotate!(p_stack, 300, 9, text("minimum outputs", 14, plot_font))
annotate!(p_stack, demand_mw + 20, 113, text("demand", 16, :left, plot_font))
annotate!(p_stack, 200, stack_price + 6, text("price: \$$(stack_price)/MWh", 16, :left, plot_font))
plot!(p_stack, size=(1200, 370), left_margin=12mm, right_margin=6mm)