diff --git a/assets/examples/61_piecewise_linear_addon.iesopt.yaml b/assets/examples/61_piecewise_linear_addon.iesopt.yaml new file mode 100644 index 0000000..d9e26da --- /dev/null +++ b/assets/examples/61_piecewise_linear_addon.iesopt.yaml @@ -0,0 +1,41 @@ +config: + general: + version: + core: 2.6.4 + optimization: + problem_type: MILP + snapshots: + count: 9 + solver: + name: highs + paths: + addons: files/61 + +addons: + CustomMath: {} + +carriers: + electricity: {} + gas: {} + +components: + grid_electricity: + type: Node + carrier: electricity + + grid_gas: + type: Node + carrier: gas + + demand_elec: + type: Profile + carrier: electricity + node_from: grid_electricity + value: [2.75, 5.50, 7.00, 8.00, 9.00, 10.00, 5.00, 5.00, 15.00] + + create_gas: + type: Profile + carrier: gas + node_to: grid_gas + mode: create + cost: 50.0 \ No newline at end of file diff --git a/assets/examples/61_piecewise_linear_addon.yaml b/assets/examples/61_piecewise_linear_addon.yaml new file mode 100644 index 0000000..ce1f7ad --- /dev/null +++ b/assets/examples/61_piecewise_linear_addon.yaml @@ -0,0 +1,41 @@ +config: + general: + version: + core: 2.6.3 + optimization: + problem_type: MILP + snapshots: + count: 9 + solver: + name: highs + paths: + addons: files/61 + +addons: + CustomMath: {} + +carriers: + electricity: {} + gas: {} + +components: + grid_electricity: + type: Node + carrier: electricity + + grid_gas: + type: Node + carrier: gas + + demand_elec: + type: Profile + carrier: electricity + node_from: grid_electricity + value: [2.75, 5.50, 7.00, 8.00, 9.00, 10.00, 5.00, 5.00, 15.00] + + create_gas: + type: Profile + carrier: gas + node_to: grid_gas + mode: create + cost: 50.0 \ No newline at end of file diff --git a/assets/examples/files/61/CustomMath.jl b/assets/examples/files/61/CustomMath.jl new file mode 100644 index 0000000..8fba931 --- /dev/null +++ b/assets/examples/files/61/CustomMath.jl @@ -0,0 +1,67 @@ +module IESoptAddon_CustomMath + +using IESopt +import JuMP + +function initialize!(model::JuMP.Model, config::Dict) + # All functions are expected to return `true` if everything went well. + return true +end + +# The following functions are called after they were called for all core components: +# - setup! +# - construct_expressions! +# - construct_variables! +# - construct_constraints! +# - construct_objective! +# +# If you do not need to modify the model during a specific step, you can just not implement the function. + +function construct_variables!(model::JuMP.Model, config::Dict) + T = get_T(model) + + node_input = get_component(model, "grid_gas") + node_output = get_component(model, "grid_electricity") + + # we create here the breakpoints of the inputs let's take 20 BPs + Pmax = 20. + a,b,c = [0.7012, 0.0662, 0.3671 ] # coeffs for efficiency + + function eta(P::Float64) + prel = P/Pmax + return 0.1 + c *( prel^a / (prel^a + b^a) ) + end + function power_input(P::Float64) + return P/eta(P) + end + + output_bp = collect(range(0.0, Pmax, length=10)) # electricity out + input_bp = power_input.(output_bp) # gas in + N = length(input_bp) + ## ====================== + + @assert N == length(output_bp) + + JuMP.@variable(model, var_input[t in T], lower_bound=0.0) + JuMP.@variable(model, var_output[t in T] >= 0.0, container=Array) + + node_output.exp.generation = [1.0 * var_output[t] for t in T] ## IESopt exp fields want AffExpr / Vector{AffExpr}, so make it explicitly affine + + JuMP.@variable(model, 0<= λ[t in T, i in 1:N] <= 1.0) # SOS2 weights PER snapshot + + JuMP.@constraints( model, begin + [t in T], var_input[t] == sum(λ[t,i] * input_bp[i] for i in 1:N) + [t in T], var_output[t] == sum(λ[t,i] * output_bp[i] for i in 1:N) + [t in T], sum(λ[t,i] for i in 1:N) == 1 + end) + JuMP.@constraint( model,[t in T], λ[t, 1:N] in JuMP.SOS2() ) + + for t in T + JuMP.add_to_expression!(node_input.exp.injection[t], model[:var_input][t], -1.0) + JuMP.add_to_expression!(node_output.exp.injection[t], node_output.exp.generation[t], 1.0) + end + + return true +end + +end \ No newline at end of file diff --git a/assets/examples/files/61/efficiency_plot.jl b/assets/examples/files/61/efficiency_plot.jl new file mode 100644 index 0000000..f7c1d96 --- /dev/null +++ b/assets/examples/files/61/efficiency_plot.jl @@ -0,0 +1,34 @@ +using Plots +import JuMP +Pmax = 100. +a,b,c = [0.7012, 0.0662, 0.3671 ] # coeffs for efficiency + +function eta(P::Float64) + prel = P/Pmax + return 0.1 + c *( prel^a / (prel^a + b^a) ) +end + +function eta_const(P::Float64) + return 0.35 +end +P = collect( range(0, Pmax, 110) ) +eta_P = eta.(P) + +p1 = plot(P, eta_P, label="True efficiency") + +input_bp = collect( range(0, Pmax, 20) ) #20 breakpoints +ouptput_bp = eta.(input_bp) + + +plot!(p1, input_bp, ouptput_bp, label="piecewise linear, 20 BPs") +plot!(p1, input_bp, eta_const.(input_bp), label="constant efficiency") + +input_bp = collect( range(0, Pmax, 10) ) #20 breakpoints +ouptput_bp = eta.(input_bp) + +plot!(p1, input_bp, ouptput_bp, label="piecewise linear, 10 BPs") + +input_bp = [0, 5, 10, 15.0, 20, 25, 45, 60, 80, 100] +ouptput_bp = eta.(input_bp) + +plot!(p1, input_bp, ouptput_bp, label="piecewise linear, 10 BPs - not equally spaced") \ No newline at end of file