diff --git a/assets/examples/60_custom_math.iesopt.yaml b/assets/examples/60_custom_math.iesopt.yaml new file mode 100644 index 0000000..23e4617 --- /dev/null +++ b/assets/examples/60_custom_math.iesopt.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/60 + +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 diff --git a/assets/examples/files/60/CustomMath.jl b/assets/examples/files/60/CustomMath.jl new file mode 100644 index 0000000..9cb24b5 --- /dev/null +++ b/assets/examples/files/60/CustomMath.jl @@ -0,0 +1,45 @@ +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") + + JuMP.@variable(model, var_input[t in T], lower_bound=0.0) + # NOTE: This is just a weird example of the possibility to attach new things. + node_output.exp.generation = 1.1 .* JuMP.@variable(model, var_output[t in T], lower_bound=0.0, container=Array) + + JuMP.@constraint( + model, + [t in T], + # NOTE: This could be a more complex mathematical expression, e.g., a piecewise interpolation. + node_output.exp.generation[t] == 0.5 * model[:var_input][t] + ) + + 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 diff --git a/test/src/examples.jl b/test/src/examples.jl index 6865916..600bdf2 100644 --- a/test/src/examples.jl +++ b/test/src/examples.jl @@ -363,3 +363,14 @@ end @test JuMP.value(get_component(model, "grid_tariff_power_consumption_$m").var.value) ≈ check[m] atol = 1e-4 end end + +@testitem "60_custom_math" tags = [:examples] setup = [Dependencies, TestExampleModule] begin + model = TestExampleModule.check(; obj=6725.0) + + check = [2.75, 5.5, 7.0, 8.0, 9.0, 10.0, 5.0, 5.0, 15.0] + vin = JuMP.value.(model[:var_input]) + vout = JuMP.value.(get_component(model, "grid_electricity").exp.generation) + + @test all(vin .≈ 2.0 .* check) + @test all(vout .≈ check) +end