Skip to content

Commit

Permalink
Documentation scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
YoungFaithful committed Jun 25, 2019
1 parent 8fa15e5 commit 7754d7d
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 4 deletions.
28 changes: 28 additions & 0 deletions docs/src/opt_cep.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,34 @@ Pkg.add("Clp")
using Clp
optimizer=Clp.Optimizer
```

## Scaling
The package features the scaling of variables and equations. Scaling variables, which are used in the numerical model, to `0.01 ≤ x ≤ 100` and scaling equations to `3⋅x = 1` instead of `3000⋅x = 1000` improves the shape of the optimization space and significantly reduces the computational time used to solve the numerical model.

The values are only scaled within the numerical model formulation, where we call the variable `VAR`, but the values are unscaled in the solution, which we call `real-VAR`. The following logic is used to scale the variables:
`real-VAR [EUR, USD, MW, or MWh] = scale[:VAR] ⋅ VAR`
` 0.01 ≤ VAR ≤ 100`
`⇔ 0.01 ≤ real-VAR / scale[:VAR] ≤ 100`

The equations are scaled with the scaling parameter of the first variable, which is `scale[:COST]` in the following example:
` scale[:COST]⋅COST = 10⋅scale[:CAP]⋅CAP`
`⇔ COST = 10⋅(scale[:CAP]/scale[:COST])⋅CAP`

### Change scaling parameters
Changing the scaling parameters is useful if the data you use represents a much smaller or bigger energy system than the ones representing Germany and California provided in this package Determine the right scaling parameters by checking the real-values of COST, CAP, GEN... (real-VAR) in a solution using your data. Select the scaling parameters to match the following:
`0.01 ≤ real-VAR / scale[:VAR] ≤ 100`
Create a dictionary with the new scaling parameters for EACH variable and include it as the optional `scale` input to overwrite the default scale in `run_opt`:
```julia
scale=Dict{Symbol,Int}(:COST => 1e9, :CAP => 1e3, :GEN => 1e3, :SLACK => 1e3, :INTRASTOR => 1e3, :INTERSTOR => 1e6, :FLOW => 1e3, :TRANS =>1e3, :LL => 1e6, :LE => 1e9)
scale_result = run_opt(ts_clust_data,cep_data,optimizer;scale=scale)
```

### Adding another variable
- Extend the default `scale`-dictionary in the `src/optim_problems/run_opt`-file to include the new variable as well.
- Include the new variable in the problem formulation in the `src/optim_problems/opt_cep`-file. Reformulate the equations by dividing them by the scaling parameter of the first variable, which is `scale[:COST]` in the following example:
` scale[:COST]⋅COST = 10⋅scale[:CAP]⋅CAP + 100`
`⇔ COST = 10⋅(scale[:CAP]/scale[:COST])⋅CAP + 100/scale[:COST]`

## Opt Result - A closer look
```@docs
OptResult
Expand Down
8 changes: 8 additions & 0 deletions examples/workflow_example_cep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,11 @@ design_variables=get_cep_design_variables(design_result)

# Use the design variable results for the operational run
operation_result = run_opt(ts_input_data,cep_data,design_result.opt_config,design_variables,optimizer;lost_el_load_cost=1e6,lost_CO2_emission_cost=700)

# Change scaling parameters
# Changing the scaling parameters is useful if the data you use represents a much smaller or bigger energy system than the ones representing Germany and California provided in this package
# Determine the right scaling parameters by checking the "real" values of COST, CAP, GEN... (real-VAR) in a solution using your data. Select the scaling parameters to match the following:
# 0.01 ≤ VAR ≤ 100, real-VAR = scale[:VAR] ⋅ VAR
# ⇔ 0.01 ≤ real-VAR / scale[:VAR] ≤ 100
scale=Dict{Symbol,Int}(:COST => 1e9, :CAP => 1e3, :GEN => 1e3, :SLACK => 1e3, :INTRASTOR => 1e3, :INTERSTOR => 1e6, :FLOW => 1e3, :TRANS =>1e3, :LL => 1e6, :LE => 1e9)
co2_result = run_opt(ts_clust_data.best_results,cep_data,optimizer;scale=scale, co2_limit=50)
4 changes: 2 additions & 2 deletions src/optim_problems/opt_cep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ function setup_opt_cep_basic_variables!(cep::OptModelCEP,

## VARIABLES ##
# Cost
push!(cep.info,"Variable COST[account, impact, tech] in $(set["impact"].*" "...)") #Note that variable COST is scaled only within the model with the value scale[:COST]
push!(cep.info,"Variable COST[account, impact, tech] in $(set["impact"].*" "...)") #Note that variable COST is scaled only within the model with the value scale[:COST]: Real-COST [`EUR` or `USD`] = scale[:COST] ⋅ COST (numeric variable within model)
@variable(cep.model, COST[account=set["account"],impact=set["impact"],tech=set["tech"]])
# Capacity
push!(cep.info,"Variable CAP[tech_cap, infrastruct, nodes] ≥ 0 in MW") #Note that variable CAP is scaled only within the model with the value scale[:CAP]
push!(cep.info,"Variable CAP[tech_cap, infrastruct, nodes] ≥ 0 in MW") #Note that variable CAP is scaled only within the model with the value scale[:CAP]: Real-CAP ['MW'] = scale[:CAP] ⋅ CAP (numeric variable within model)
@variable(cep.model, CAP[tech=set["tech_cap"],infrastruct=set["infrastruct"] ,node=set["nodes"]]>=0)
# Generation #
push!(cep.info,"Variable GEN[sector, tech_power, t, k, node] in MW") #Note that variable is scaled only within the model
Expand Down
5 changes: 3 additions & 2 deletions src/optim_problems/run_opt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function run_opt(ts_data::ClustData,
end

"""
run_opt(ts_data::ClustData,opt_data::OptDataCEP,optimizer::DataTyple;co2_limit::Number=Inf,lost_el_load_cost::Number=Inf,lost_CO2_emission_cost::Number=Inf,existing_infrastructure::Bool=false,limit_infrastructure::Bool=false,storage::String="none",transmission::Bool=false,descriptor::String="",print_flag::Bool=true,optimizer_config::Dict{Symbol,Any}=Dict{Symbol,Any}(),round_sigdigits::Int=9)
run_opt(ts_data::ClustData,opt_data::OptDataCEP,optimizer::DataTyple;co2_limit::Number=Inf,lost_el_load_cost::Number=Inf,lost_CO2_emission_cost::Number=Inf,existing_infrastructure::Bool=false,limit_infrastructure::Bool=false,storage::String="none",transmission::Bool=false,scale::Dict{Symbol,Int}=Dict{Symbol,Int}(:COST => 1e9, :CAP => 1e3, :GEN => 1e3, :SLACK => 1e3, :INTRASTOR => 1e3, :INTERSTOR => 1e6, :FLOW => 1e3, :TRANS =>1e3, :LL => 1e6, :LE => 1e9),descriptor::String="",print_flag::Bool=true,optimizer_config::Dict{Symbol,Any}=Dict{Symbol,Any}(),round_sigdigits::Int=9)
Wrapper function for type of optimization problem for the CEP-Problem (NOTE: identifier is the type of `opt_data` - in this case OptDataCEP - so identification as CEP problem).
Required elements are:
- `ts_data`: The time-series data, which could either be the original input data or some aggregated time-series data. The `keys(ts_data.data)` need to match the `[time_series_name]-[node]`
Expand All @@ -109,7 +109,8 @@ Options to tweak the model are:
- `lost_CO2_emission_cost`: Number indicating the emission price/kg-CO2 (should be greater than 1e6), give Inf for no LE (Lost Emissions - a variable for emissions that will exceed the limit in order to provide the demand with the installed capacities)
- `existing_infrastructure`: true or false to include or exclude existing infrastructure to the model
- `storage`: String "none" for no storage or "simple" to include simple (only intra-day storage) or "seasonal" to include seasonal storage (inter-day)
Optional elements are:
- `transmission`: Bool `false` If no transmission should be modeled (copperplate assumption), `true` if transmission should be modeled
- `scale`: Dict{Symbol,Int} with a number for each variable (like `:COST`) to scale the variables and equations to similar quantities. Try to acchieve that the numerical model only has to solve numerical variables in a scale of 0.01 and 100. The following equation is used as a relationship between the real value, which is provided in the solution (real-VAR), and the numerical variable, which is used within the model formulation (VAR): real-VAR [`EUR`, `MW` or `MWh`] = scale[:VAR] ⋅ VAR.
- `descriptor`: String with the name of this paricular model like "kmeans-10-co2-500"
- `print_flag`: Bool to decide if a summary of the Optimization result should be printed.
- `optimizer_config`: Each Symbol and the corresponding value in the Dictionary is passed on to the `with_optimizer` function in addition to the `optimizer`. For Gurobi an example Dictionary could look like `Dict{Symbol,Any}(:Method => 2, :OutputFlag => 0, :Threads => 2)` more information can be found in the optimizer specific documentation.
Expand Down

0 comments on commit 7754d7d

Please sign in to comment.