From e7a6a634f5720bebcd979b21b62ad0fd75664db7 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 18 Sep 2023 11:58:14 +0200 Subject: [PATCH 01/33] Introduce window_sum_duration to use within min_res_gen_to_demand_ratio Looks like we need to account for the duration so the constraint can handle different time resolutions. --- src/constraints/constraint_connection_flow_lodf.jl | 2 +- .../constraint_mp_min_res_gen_to_demand_ratio.jl | 12 ++++++++---- src/data_structure/benders_data.jl | 2 +- src/data_structure/preprocess_data_structure.jl | 2 +- src/util/misc.jl | 10 ++++++++++ test/run_spineopt_benders.jl | 7 ++++--- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/constraints/constraint_connection_flow_lodf.jl b/src/constraints/constraint_connection_flow_lodf.jl index 99c4267493..bf7e62b03f 100644 --- a/src/constraints/constraint_connection_flow_lodf.jl +++ b/src/constraints/constraint_connection_flow_lodf.jl @@ -36,7 +36,7 @@ function add_constraint_connection_flow_lodf!(m::Model) - connection_minimum_emergency_capacity(m, conn_mon, s, t) <= + connection_post_contingency_flow(m, connection_flow, conn_cont, conn_mon, s, t, expr_sum) - * connection_availability_factor[(connection=conn_mon, stochastic_scenario=s, analysis_time=t0, t=t)] + * connection_availability_factor[(connection=conn_mon, stochastic_scenario=s, analysis_time=t0, t=t)] <= + connection_minimum_emergency_capacity(m, conn_mon, s, t) ) diff --git a/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl b/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl index ed8348450f..7a7fec8965 100644 --- a/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl +++ b/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl @@ -38,7 +38,9 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) (commodity=comm,) => @constraint( m, + sum( - window_sum(sp_unit_flow(unit=u, node=n, direction=d, stochastic_scenario=s), current_window(m)) + window_sum_duration( + m, sp_unit_flow(unit=u, node=n, direction=d, stochastic_scenario=s), current_window(m) + ) for (u, s) in unit_stochastic_indices(m; unit=unit(is_renewable=true)) for (u, n, d) in unit__to_node(unit=u, node=node__commodity(commodity=comm), _compact=false); init=0 @@ -48,7 +50,8 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) + units_invested_available[u, s, t] - internal_fix_units_invested_available(unit=u, stochastic_scenario=s, t=t, _default=0) ) - * window_sum( + * window_sum_duration( + m, + unit_availability_factor(unit=u, stochastic_scenario=s) * unit_capacity(unit=u, node=n, direction=d, stochastic_scenario=s) * unit_conv_cap_to_flow(unit=u, node=n, direction=d, stochastic_scenario=s), @@ -63,14 +66,15 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) + mp_min_res_gen_to_demand_ratio(commodity=comm) * ( sum( - window_sum(demand(node=n, stochastic_scenario=s), current_window(m)) + window_sum_duration(m, demand(node=n, stochastic_scenario=s), current_window(m)) for (n, s) in node_stochastic_indices( m; node=intersect(indices(demand), node__commodity(commodity=comm)) ); init=0 ) + sum( - window_sum( + window_sum_duration( + m, fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), current_window(m) ) diff --git a/src/data_structure/benders_data.jl b/src/data_structure/benders_data.jl index 4e322448c0..518f68fbd8 100644 --- a/src/data_structure/benders_data.jl +++ b/src/data_structure/benders_data.jl @@ -162,7 +162,7 @@ function save_mp_objective_bounds_and_gap!(m_mp) sp_obj_val = sp_objective_value_bi(benders_iteration=current_bi, _default=0) invest_costs = value(realize(total_costs(m_mp, anything; operations=false))) obj_ub = m_mp.ext[:spineopt].objective_upper_bound[] = sp_obj_val + invest_costs - gap = 2 * (obj_ub - obj_lb) / (obj_ub + obj_lb) + gap = (obj_ub == obj_lb) ? 0 : 2 * (obj_ub - obj_lb) / (obj_ub + obj_lb) push!(m_mp.ext[:spineopt].benders_gaps, gap) end diff --git a/src/data_structure/preprocess_data_structure.jl b/src/data_structure/preprocess_data_structure.jl index bd4b0fe1ef..ccc4119859 100644 --- a/src/data_structure/preprocess_data_structure.jl +++ b/src/data_structure/preprocess_data_structure.jl @@ -289,7 +289,7 @@ function _build_ptdf(connections, nodes, unavailable_connections=Set()) n_from, n_to = connection__from_node(connection=conn, direction=anything) A[node_numbers[n_from], ix] = 1 A[node_numbers[n_to], ix] = -1 - reactance = max(connection_reactance(connection=conn), 1e-6) + reactance = max(connection_reactance(connection=conn, _default=0), 1e-6) if conn in unavailable_connections reactance *= 1e3 end diff --git a/src/util/misc.jl b/src/util/misc.jl index f0fa909064..12c76d4a60 100644 --- a/src/util/misc.jl +++ b/src/util/misc.jl @@ -201,5 +201,15 @@ function print_solution(m, variable_patterns...) println() end +function window_sum_duration(m, ts::TimeSeries, window; init=0) + dur_unit = _model_duration_unit(m.ext[:spineopt].instance) + time_slice_value_iter = ( + (TimeSlice(t1, t2; duration_unit=dur_unit), v) + for (t1, t2, v) in zip(ts.indexes, ts.indexes[2:end], ts.values) + ) + sum(v * duration(t) for (t, v) in time_slice_value_iter if iscontained(start(t), window) && !isnan(v); init=init) +end +window_sum_duration(m, x::Number, window; init=0) = x * duration(window) + init + window_sum(ts::TimeSeries, window; init=0) = sum(v for (t, v) in ts if iscontained(t, window) && !isnan(v); init=init) window_sum(x::Number, window; init=0) = x + init diff --git a/test/run_spineopt_benders.jl b/test/run_spineopt_benders.jl index 73fc0a45fd..35f032dd19 100644 --- a/test/run_spineopt_benders.jl +++ b/test/run_spineopt_benders.jl @@ -354,7 +354,7 @@ function _test_benders_unit_storage() ["node", "node_b", "demand", dem], ["node", "node_a", "node_slack_penalty", penalty], ["temporal_block", "hourly", "block_end", unparse_db_value(Hour(rf + look_ahead))], - ["temporal_block", "investments_hourly", "block_end", unparse_db_value(Hour(rf + look_ahead))], + ["temporal_block", "investments_hourly", "block_end", unparse_db_value(Hour(24 + look_ahead))], ["temporal_block", "hourly", "resolution", unparse_db_value(Hour(res))], ["temporal_block", "investments_hourly", "resolution", unparse_db_value(Hour(res))], ] @@ -699,9 +699,10 @@ function _test_benders_mp_min_res_gen_to_demand_ratio() @test length(cons) == 1 observed_con = constraint_object(only(values(cons))) expected_con = @build_constraint( - ucap * sum(v for (k, v) in invest_vars if start(k.t) >= DateTime(2000)) + only(values(slack_vars)) + + ucap * sum(duration(k.t) * v for (k, v) in invest_vars if start(k.t) >= DateTime(2000)) + + only(values(slack_vars)) >= - dem * mrg2d_ratio + + 24 * dem * mrg2d_ratio ) @test _is_constraint_equal(observed_con, expected_con) using_spinedb(url_out, Y) From 6a9931a491ad95531d2a67769fb94be49862d0c1 Mon Sep 17 00:00:00 2001 From: datejada Date: Fri, 22 Sep 2023 11:28:13 +0200 Subject: [PATCH 02/33] add tutorial file with general structure --- docs/src/tutorial/reserves.md | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/src/tutorial/reserves.md diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md new file mode 100644 index 0000000000..02beac7ad6 --- /dev/null +++ b/docs/src/tutorial/reserves.md @@ -0,0 +1,41 @@ +# Reserve definition tutorial + +This tutorial provides a step-by-step guide to setup a simple energy system including reserve requierements on Spine Toolbox. + +## Introduction + +To get the most out of this tutorial, we suggest first completing the Simple System tutorial, which can be found [here](https://spine-tools.github.io/SpineOpt.jl/latest/tutorial/simple_system/). + +## Guide + +### Entering input data + +#### Importing the SpineOpt database template + +TBD + +#### Creating objects + +TBD + +#### Establishing relationships + +TBD + +#### Specifying object parameter values + +TBD + +#### Specifying relationship parameter values + +TBD + +When you're ready, commit all changes to the database. + +### Executing the workflow + +TBD + +### Examining the results + +TBD From c354e6312f032b0165593b1492984759d07d7cb4 Mon Sep 17 00:00:00 2001 From: Tasqu Date: Mon, 25 Sep 2023 09:18:21 +0300 Subject: [PATCH 03/33] Resolve name conflict, but other issues remain. --- Project.toml | 1 - src/SpineOpt.jl | 3 +++ test/runtests.jl | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 6c1ad82be3..bcf30e8527 100644 --- a/Project.toml +++ b/Project.toml @@ -19,4 +19,3 @@ SpineInterface = "0cda1612-498a-11e9-3c92-77fa82595a4f" [compat] SpineInterface = "0.11.6" julia = "^1.2" -JuMP = "< 1.14" diff --git a/src/SpineOpt.jl b/src/SpineOpt.jl index a9cd0c13de..d5cb48b361 100644 --- a/src/SpineOpt.jl +++ b/src/SpineOpt.jl @@ -33,6 +33,9 @@ import DataStructures: OrderedDict import Dates: CompoundPeriod import LinearAlgebra: BLAS.gemm, LAPACK.getri!, LAPACK.getrf! +# Resolve JuMP and SpineInterface `Parameter` and `parameter_value` conflicts. +import SpineInterface: Parameter, parameter_value + export run_spineopt export rerun_spineopt export run_spineopt_kernel! diff --git a/test/runtests.jl b/test/runtests.jl index b2152740ae..b79607ba54 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -24,6 +24,8 @@ using Dates using JuMP using PyCall +# Resolve JuMP and SpineInterface `Parameter` and `parameter_value` conflicts. +import SpineInterface: Parameter, parameter_value import SpineOpt: time_slice, From 7a7d3c4e10eaf4d92d42fe0d9ea7fc63b9031e47 Mon Sep 17 00:00:00 2001 From: Tasqu Date: Mon, 25 Sep 2023 10:59:06 +0300 Subject: [PATCH 04/33] Fix mystery error by rearranging terms? --- src/constraints/constraint_unit_flow_op_bounds.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/constraints/constraint_unit_flow_op_bounds.jl b/src/constraints/constraint_unit_flow_op_bounds.jl index d93dad47e7..92c546146c 100644 --- a/src/constraints/constraint_unit_flow_op_bounds.jl +++ b/src/constraints/constraint_unit_flow_op_bounds.jl @@ -32,6 +32,10 @@ function add_constraint_unit_flow_op_bounds!(m::Model) + unit_flow_op[u, n, d, op, s, t] <= ( + ordered_unit_flow_op(unit = u, node=n, direction=d, _default=false) ? + unit_flow_op_active[u, n, d, op, s, t] : units_on[u, s, t] + ) + * ( + operating_points[(unit=u, node=n, direction=d, stochastic_scenario=s, analysis_time=t0, i=op)] - ( (op > 1) ? operating_points[ @@ -39,10 +43,6 @@ function add_constraint_unit_flow_op_bounds!(m::Model) ] : 0 ) ) - * ( - ordered_unit_flow_op(unit = u, node=n, direction=d, _default=false) ? - unit_flow_op_active[u, n, d, op, s, t] : units_on[u, s, t] - ) * unit_availability_factor[(unit=u, stochastic_scenario=s, analysis_time=t0, t=t)] * unit_capacity[(unit=u, node=n, direction=d, stochastic_scenario=s, analysis_time=t0, t=t)] * unit_conv_cap_to_flow[(unit=u, node=n, direction=d, stochastic_scenario=s, analysis_time=t0, t=t)] From b1d7e095ad5e20286ac53b29eef149e746d672af Mon Sep 17 00:00:00 2001 From: Tasqu Date: Mon, 25 Sep 2023 16:16:28 +0300 Subject: [PATCH 05/33] Fix units availability constraint unit test? --- src/constraints/constraint_units_available.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/constraints/constraint_units_available.jl b/src/constraints/constraint_units_available.jl index 410dd0aba5..38f1fc534a 100644 --- a/src/constraints/constraint_units_available.jl +++ b/src/constraints/constraint_units_available.jl @@ -32,15 +32,15 @@ function add_constraint_units_available!(m::Model) units_available[u, s, t] for (u, s, t) in units_on_indices(m; unit=u, stochastic_scenario=s, t=t); init=0, ) - <= - + number_of_units[(unit=u, stochastic_scenario=s, analysis_time=t0, t=t)] - + expr_sum( + - expr_sum( units_invested_available[u, s, t1] for (u, s, t1) in units_invested_available_indices( m; unit=u, stochastic_scenario=s, t=t_overlaps_t(m; t=t) ); init=0, ) + <= + number_of_units[(unit=u, stochastic_scenario=s, analysis_time=t0, t=t)] ) for (u, s, t) in constraint_units_available_indices(m) ) From 6107515ff92aaa63156a81b3c8d6ad6acf4bc46c Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 26 Sep 2023 09:27:50 +0200 Subject: [PATCH 06/33] Report solution from the Benders master problem too --- .../constraint_mp_any_invested_cuts.jl | 6 +++--- src/run_spineopt_benders.jl | 20 ++++++++++++++----- src/run_spineopt_standard.jl | 10 ++++------ .../variable_sp_objective_upperbound.jl | 4 ++-- test/run_spineopt_benders.jl | 13 +++++++++++- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/constraints/constraint_mp_any_invested_cuts.jl b/src/constraints/constraint_mp_any_invested_cuts.jl index f1905b674d..9bee6205a2 100644 --- a/src/constraints/constraint_mp_any_invested_cuts.jl +++ b/src/constraints/constraint_mp_any_invested_cuts.jl @@ -34,9 +34,9 @@ function add_constraint_mp_any_invested_cuts!(m::Model) merge!( get!(m.ext[:spineopt].constraints, :mp_any_invested_cut, Dict()), Dict( - (benders_iteration=bi, t=t1) => @constraint( + (benders_iteration=bi, model=i) => @constraint( m, - + sp_objective_upperbound[t1] + + sp_objective_upperbound[i] >= + sp_objective_value_bi(benders_iteration=bi) # operating cost benefit from investments in units @@ -71,7 +71,7 @@ function add_constraint_mp_any_invested_cuts!(m::Model) ) ) for bi in last(benders_iteration()) - for (t1,) in sp_objective_upperbound_indices(m) + for (i,) in sp_objective_upperbound_indices(m) ) ) end \ No newline at end of file diff --git a/src/run_spineopt_benders.jl b/src/run_spineopt_benders.jl index 07dfcc94ce..6538d1a2c1 100644 --- a/src/run_spineopt_benders.jl +++ b/src/run_spineopt_benders.jl @@ -49,7 +49,7 @@ function rerun_spineopt_benders!( j = 1 while optimize @log log_level 0 "\nStarting Benders iteration $j" - optimize_model!(m_mp; log_level=log_level, save_outputs=false) || break + optimize_model!(m_mp; log_level=log_level) || break @timelog log_level 2 "Processing master problem solution" process_master_problem_solution!(m_mp) k = 1 subproblem_solved = nothing @@ -101,6 +101,7 @@ function rerun_spineopt_benders!( j += 1 global current_bi = add_benders_iteration(j) end + write_report(m_mp, url_out; alternative=alternative, log_level=log_level) write_report(m, url_out; alternative=alternative, log_level=log_level) m end @@ -111,8 +112,8 @@ Initialize the given model for SpineOpt Master Problem: add variables, add const function _init_mp_model!(m; log_level=3) @timelog log_level 2 "Adding MP variables...\n" _add_mp_variables!(m; log_level=log_level) @timelog log_level 2 "Adding MP constraints...\n" _add_mp_constraints!(m; log_level=log_level) - #@timelog log_level 2 "Adding MP renewing constraints...\n" _add_mp_renewing_constraints!(m; log_level=log_level) @timelog log_level 2 "Setting MP objective..." _set_mp_objective!(m) + _init_outputs!(m) end """ @@ -174,7 +175,7 @@ end function _add_constraint_sp_objective_upperbound!(m::Model) @fetch sp_objective_upperbound = m.ext[:spineopt].variables m.ext[:spineopt].constraints[:mp_objective] = Dict( - (t=t,) => @constraint(m, sp_objective_upperbound[t] >= 0) for (t,) in sp_objective_upperbound_indices(m) + (model=i,) => @constraint(m, sp_objective_upperbound[i] >= 0) for (i,) in sp_objective_upperbound_indices(m) ) end @@ -185,14 +186,23 @@ Minimize total investment costs plus upperbound on subproblem objective. """ function _set_mp_objective!(m::Model) @fetch sp_objective_upperbound = m.ext[:spineopt].variables + _create_mp_objective_terms!(m) + investment_costs = sum(in_window for (in_window, _bw) in values(m.ext[:spineopt].objective_terms)) @objective( m, Min, - + expr_sum(sp_objective_upperbound[t] for (t,) in sp_objective_upperbound_indices(m); init=0) - + total_costs(m, anything; operations=false) + + expr_sum(sp_objective_upperbound[i] for (i,) in sp_objective_upperbound_indices(m); init=0) + + investment_costs ) end +function _create_mp_objective_terms!(m) + for term in objective_terms(m; operations=false) + func = eval(term) + m.ext[:spineopt].objective_terms[term] = (func(m, anything), 0) + end +end + """ Add benders cuts to master problem. """ diff --git a/src/run_spineopt_standard.jl b/src/run_spineopt_standard.jl index 243a82bd05..05808a5da6 100644 --- a/src/run_spineopt_standard.jl +++ b/src/run_spineopt_standard.jl @@ -330,7 +330,7 @@ end Optimize the given model. If an optimal solution is found, save results and return `true`, otherwise return `false`. """ -function optimize_model!(m::Model; log_level=3, calculate_duals=false, save_outputs=true, iterations=nothing) +function optimize_model!(m::Model; log_level=3, calculate_duals=false, iterations=nothing) write_mps_file(model=m.ext[:spineopt].instance) == :write_mps_always && write_to_file(m, "model_diagnostics.mps") # NOTE: The above results in a lot of Warning: Variable connection_flow[...] is mentioned in BOUNDS, # but is not mentioned in the COLUMNS section. @@ -345,10 +345,8 @@ function optimize_model!(m::Model; log_level=3, calculate_duals=false, save_outp m; iterations=iterations ) calculate_duals && _calculate_duals(m; log_level=log_level) - if save_outputs - @timelog log_level 2 "Postprocessing results..." postprocess_results!(m) - @timelog log_level 2 "Saving outputs..." _save_outputs!(m; iterations=iterations) - end + @timelog log_level 2 "Postprocessing results..." postprocess_results!(m) + @timelog log_level 2 "Saving outputs..." _save_outputs!(m; iterations=iterations) else m.ext[:spineopt].has_results[] = false @warn "no solution available for window $(current_window(m)) - moving on..." @@ -580,7 +578,7 @@ function _value_by_entity_non_aggregated(m, value::Dict, crop_to_window) analysis_time = start(current_window(m)) for (ind, val) in value t_keys = collect(_time_slice_keys(ind)) - t = maximum(ind[k] for k in t_keys) + t = !isempty(t_keys) ? maximum(ind[k] for k in t_keys) : current_window(m) t <= analysis_time && continue crop_to_window && start(t) >= end_(current_window(m)) && continue entity = _drop_key(ind, t_keys...) diff --git a/src/variables/variable_sp_objective_upperbound.jl b/src/variables/variable_sp_objective_upperbound.jl index 39bce6a67f..a83f989cda 100644 --- a/src/variables/variable_sp_objective_upperbound.jl +++ b/src/variables/variable_sp_objective_upperbound.jl @@ -21,6 +21,6 @@ function add_variable_sp_objective_upperbound!(m::Model) add_variable!(m, :sp_objective_upperbound, sp_objective_upperbound_indices) end -function sp_objective_upperbound_indices(m::Model; t=anything, temporal_block=anything) - [(t=first(time_slice(m)),)] +function sp_objective_upperbound_indices(m::Model; kwargs...) + [(model=m.ext[:spineopt].instance,)] end diff --git a/test/run_spineopt_benders.jl b/test/run_spineopt_benders.jl index 35f032dd19..86c675c004 100644 --- a/test/run_spineopt_benders.jl +++ b/test/run_spineopt_benders.jl @@ -93,6 +93,7 @@ function _test_benders_unit() ["output", "units_invested"], ["output", "units_mothballed"], ["output", "units_invested_available"], + ["output", "unit_investment_costs"], ["temporal_block", "investments_hourly"], ] relationships = [ @@ -106,6 +107,7 @@ function _test_benders_unit() ["report__output", ["report_x", "units_invested"]], ["report__output", ["report_x", "units_mothballed"]], ["report__output", ["report_x", "units_invested_available"]], + ["report__output", ["report_x", "unit_investment_costs"]], ] object_parameter_values = [ ["model", "instance", "roll_forward", unparse_db_value(Hour(rf))], @@ -144,6 +146,11 @@ function _test_benders_unit() @test Y.total_costs(model=Y.model(:instance), t=t) == (should_invest ? 60 : 120) end end + @testset "unit_investment_costs" begin + @test Y.objective_unit_investment_costs(model=Y.model(:instance), t=DateTime(2000, 1, 1)) == ( + should_invest ? u_inv_cost : 0 + ) + end @testset "invested" begin @testset for t in DateTime(2000, 1, 1):Hour(6):DateTime(2000, 1, 2) @test Y.units_invested(unit=Y.unit(:unit_ab_alt), t=t) == ( @@ -643,6 +650,7 @@ function _test_benders_mp_min_res_gen_to_demand_ratio() ["output", "units_invested"], ["output", "units_mothballed"], ["output", "units_invested_available"], + ["output", "mp_min_res_gen_to_demand_ratio_slack"], ["temporal_block", "investments_hourly"], ] relationships = [ @@ -657,6 +665,7 @@ function _test_benders_mp_min_res_gen_to_demand_ratio() ["report__output", ["report_x", "units_invested"]], ["report__output", ["report_x", "units_mothballed"]], ["report__output", ["report_x", "units_invested_available"]], + ["report__output", ["report_x", "mp_min_res_gen_to_demand_ratio_slack"]], ] object_parameter_values = [ ["commodity", "electricity", "mp_min_res_gen_to_demand_ratio", mrg2d_ratio], @@ -691,7 +700,7 @@ function _test_benders_mp_min_res_gen_to_demand_ratio() relationship_parameter_values=relationship_parameter_values ) rm(file_path_out; force=true) - m = run_spineopt(url_in, url_out; log_level=3) + m = run_spineopt(url_in, url_out; log_level=0) m_mp = master_problem_model(m) cons = m_mp.ext[:spineopt].constraints[:mp_min_res_gen_to_demand_ratio] invest_vars = m_mp.ext[:spineopt].variables[:units_invested_available] @@ -728,6 +737,8 @@ function _test_benders_mp_min_res_gen_to_demand_ratio() @test Y.units_invested_available(unit=Y.unit(:unit_ab_alt), t=t) == (should_invest ? 1 : 0) end end + t0 = DateTime(2000, 1, 1) + @test Y.mp_min_res_gen_to_demand_ratio_slack(commodity=Y.commodity(:electricity), t=t0) == 0 end end end From ec9451f879eb97f5b69866c0e4ddb62f1ff1c3d2 Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 26 Sep 2023 10:30:03 +0200 Subject: [PATCH 07/33] Fix post processing results --- src/data_structure/postprocess_results.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/data_structure/postprocess_results.jl b/src/data_structure/postprocess_results.jl index 964df4b994..353b786655 100644 --- a/src/data_structure/postprocess_results.jl +++ b/src/data_structure/postprocess_results.jl @@ -36,12 +36,14 @@ function postprocess_results!(m::Model) end function save_connection_avg_throughflow!(m::Model) - @fetch connection_flow = m.ext[:spineopt].values + connection_flow = get(m.ext[:spineopt].values, :connection_flow, nothing) + connection_flow === nothing && return _save_connection_avg_throughflow!(m, :connection_avg_throughflow, connection_flow) end function save_connection_avg_intact_throughflow!(m::Model) - @fetch connection_intact_flow = m.ext[:spineopt].values + connection_intact_flow = get(m.ext[:spineopt].values, :connection_intact_flow, nothing) + connection_intact_flow === nothing && return _save_connection_avg_throughflow!(m, :connection_avg_intact_throughflow, connection_intact_flow) end @@ -83,7 +85,8 @@ function _contingency_is_binding(m, connection_flow, conn_cont, conn_mon, s, t) end function save_contingency_is_binding!(m::Model) - @fetch connection_flow = m.ext[:spineopt].values + connection_flow = get(m.ext[:spineopt].values, :connection_flow, nothing) + connection_flow === nothing && return m.ext[:spineopt].values[:contingency_is_binding] = Dict( ( connection_contingency=conn_cont, connection_monitored=conn_mon, stochastic_path=s, t=t From 67d9a4b18b2e9a886460e029bfa88319315d07e8 Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 26 Sep 2023 15:08:31 +0200 Subject: [PATCH 08/33] Add tests for skipping duals calculation if no integers ...plus minor formatting. --- .../constraint_mp_any_invested_cuts.jl | 6 ++-- src/run_spineopt_benders.jl | 4 +-- src/util/misc.jl | 3 +- .../variable_sp_objective_upperbound.jl | 2 +- test/run_spineopt.jl | 30 +++++++++++++++++++ 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/constraints/constraint_mp_any_invested_cuts.jl b/src/constraints/constraint_mp_any_invested_cuts.jl index 9bee6205a2..d73c5e2fc7 100644 --- a/src/constraints/constraint_mp_any_invested_cuts.jl +++ b/src/constraints/constraint_mp_any_invested_cuts.jl @@ -34,9 +34,9 @@ function add_constraint_mp_any_invested_cuts!(m::Model) merge!( get!(m.ext[:spineopt].constraints, :mp_any_invested_cut, Dict()), Dict( - (benders_iteration=bi, model=i) => @constraint( + (benders_iteration=bi, t=t) => @constraint( m, - + sp_objective_upperbound[i] + + sp_objective_upperbound[t] >= + sp_objective_value_bi(benders_iteration=bi) # operating cost benefit from investments in units @@ -71,7 +71,7 @@ function add_constraint_mp_any_invested_cuts!(m::Model) ) ) for bi in last(benders_iteration()) - for (i,) in sp_objective_upperbound_indices(m) + for (t,) in sp_objective_upperbound_indices(m) ) ) end \ No newline at end of file diff --git a/src/run_spineopt_benders.jl b/src/run_spineopt_benders.jl index 6538d1a2c1..3185c3f346 100644 --- a/src/run_spineopt_benders.jl +++ b/src/run_spineopt_benders.jl @@ -175,7 +175,7 @@ end function _add_constraint_sp_objective_upperbound!(m::Model) @fetch sp_objective_upperbound = m.ext[:spineopt].variables m.ext[:spineopt].constraints[:mp_objective] = Dict( - (model=i,) => @constraint(m, sp_objective_upperbound[i] >= 0) for (i,) in sp_objective_upperbound_indices(m) + (t=t,) => @constraint(m, sp_objective_upperbound[t] >= 0) for (t,) in sp_objective_upperbound_indices(m) ) end @@ -191,7 +191,7 @@ function _set_mp_objective!(m::Model) @objective( m, Min, - + expr_sum(sp_objective_upperbound[i] for (i,) in sp_objective_upperbound_indices(m); init=0) + + expr_sum(sp_objective_upperbound[t] for (t,) in sp_objective_upperbound_indices(m); init=0) + investment_costs ) end diff --git a/src/util/misc.jl b/src/util/misc.jl index 12c76d4a60..cfcfe29deb 100644 --- a/src/util/misc.jl +++ b/src/util/misc.jl @@ -204,8 +204,7 @@ end function window_sum_duration(m, ts::TimeSeries, window; init=0) dur_unit = _model_duration_unit(m.ext[:spineopt].instance) time_slice_value_iter = ( - (TimeSlice(t1, t2; duration_unit=dur_unit), v) - for (t1, t2, v) in zip(ts.indexes, ts.indexes[2:end], ts.values) + (TimeSlice(t1, t2; duration_unit=dur_unit), v) for (t1, t2, v) in zip(ts.indexes, ts.indexes[2:end], ts.values) ) sum(v * duration(t) for (t, v) in time_slice_value_iter if iscontained(start(t), window) && !isnan(v); init=init) end diff --git a/src/variables/variable_sp_objective_upperbound.jl b/src/variables/variable_sp_objective_upperbound.jl index a83f989cda..1c56c49cd5 100644 --- a/src/variables/variable_sp_objective_upperbound.jl +++ b/src/variables/variable_sp_objective_upperbound.jl @@ -22,5 +22,5 @@ function add_variable_sp_objective_upperbound!(m::Model) end function sp_objective_upperbound_indices(m::Model; kwargs...) - [(model=m.ext[:spineopt].instance,)] + [(t=current_window(m),)] end diff --git a/test/run_spineopt.jl b/test/run_spineopt.jl index e03c77b2aa..f12864bc58 100644 --- a/test/run_spineopt.jl +++ b/test/run_spineopt.jl @@ -834,6 +834,35 @@ function _test_time_limit() end end +function _test_only_linear_model_has_duals() + objects = [["output", "bound_units_on"]] + relationships = [["report__output", ["report_x", "bound_units_on"]]] + @testset "linear_model_has_duals" begin + url_in, url_out, file_path_out = _test_run_spineopt_setup() + SpineInterface.import_data(url_in; objects=objects, relationships=relationships) + rm(file_path_out; force=true) + m = run_spineopt(url_in, url_out; log_level=0) + @test has_duals(m) + end + object_parameter_values = [ + ["unit", "unit_ab", "online_variable_type", "unit_online_variable_type_binary"] + ] + @testset "integer_model_doesnt_have_duals" begin + url_in, url_out, file_path_out = _test_run_spineopt_setup() + objects = [["output", "bound_units_on"]] + relationships = [["report__output", ["report_x", "bound_units_on"]]] + object_parameter_values = [ + ["unit", "unit_ab", "online_variable_type", "unit_online_variable_type_binary"] + ] + SpineInterface.import_data( + url_in; objects=objects, relationships=relationships, object_parameter_values=object_parameter_values + ) + rm(file_path_out; force=true) + m = run_spineopt(url_in, url_out; log_level=0) + @test !has_duals(m) + end +end + @testset "run_spineopt" begin _test_rolling() _test_rolling_with_updating_data() @@ -854,4 +883,5 @@ end _test_fix_unit_flow_with_rolling() _test_fix_node_state_using_map_with_rolling() _test_time_limit() + _test_only_linear_model_has_duals() end \ No newline at end of file From f5800486cabffdf6334fd9b71763c4b8985fce38 Mon Sep 17 00:00:00 2001 From: datejada Date: Tue, 26 Sep 2023 16:18:17 +0200 Subject: [PATCH 09/33] First changes in the reserve definition steps in the tutorial --- docs/src/tutorial/reserves.md | 37 +++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 02beac7ad6..95e0d43964 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -1,30 +1,51 @@ # Reserve definition tutorial -This tutorial provides a step-by-step guide to setup a simple energy system including reserve requierements on Spine Toolbox. +This tutorial provides a step-by-step guide to include reserve requirements in a simple energy system with Spine Toolbox for SpineOpt. ## Introduction -To get the most out of this tutorial, we suggest first completing the Simple System tutorial, which can be found [here](https://spine-tools.github.io/SpineOpt.jl/latest/tutorial/simple_system/). +Welcome to our tutorial, where we will walk you through the process of adding a new reserve node in SpineOpt using Spine Toolbox. To get the most out of this tutorial, we suggest first completing the Simple System tutorial, which can be found [here](https://spine-tools.github.io/SpineOpt.jl/latest/tutorial/simple_system/). + +### Model assumptions + +- The reserve node has a requirement of 20MW for upwards reserve +- Power plants 'a' and 'b' can both provide reserve to this node + +![image](../figs_reserves/aaa.png) ## Guide ### Entering input data -#### Importing the SpineOpt database template - -TBD +In this tutorial, you will learn how to add a new reserve node to the Simple System. To begin, please launch the Spine Toolbox and select **File** and then **Open Project** or use the keyboard shortcut **Alt + O** to open the desired project. Afterwards, locate the folder that you saved in the Simple System tutorial and click *Ok*. This will prompt the Simple System workflow to appear in the *Design View* section for you to start working on. #### Creating objects -TBD +- Always in the Spine DB editor, locate the *Object tree* (typically at the top-left). Expand the [root] element if not expanded. +- Right click on the [node] class, and select *Add objects* from the context menu. The *Add objects* dialog will pop up. +- Enter the names for the new reseve node as seen in the image below, then press *Ok*. This will create a new object of class *node*, called *upward\_reserve\_node*. + +![image](../figs_reserves/aaa.png) #### Establishing relationships -TBD +- Always in the Spine DB editor, locate the *Relationship tree* (typically at the bottom-left). Expand the *root* element if not expanded. +- Right click on the *unit\_\_to_node* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. +- Select the names of the two units and their **receiving** nodes, as seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into the *upward\_reserve\_node*. + +![image](../figs_reserves/aaa.png) #### Specifying object parameter values -TBD +- Back to *Object tree*, expand the *node* class and select *upward\_reserve\_node*. +- Locate the *Object parameter* table (typically at the top-center). +- In the *Object parameter* table (typically at the top-center), select the following parameter as seen in the image below: + - *demand* parameter and the *Base* alternative, and enter the value *20*. This will establish that there's a demand of '20' at the reverse node. + - *is_reserve_node* parameter and the *Base* alternative, and enter the value *True*. This will establish that it is a reverse node. + - *upward_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. + - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve provision must be greater or equal than the reserve demand. + +![image](../figs_reserves/aaa.png) #### Specifying relationship parameter values From ff9cf40b30b2e319d835b7b6293555f3695c815a Mon Sep 17 00:00:00 2001 From: Jody Dillon Date: Tue, 26 Sep 2023 18:13:36 +0200 Subject: [PATCH 10/33] Got rid of weighting from sp_unit flow sum demand and uaf only over rep windows --- ...nstraint_mp_min_res_gen_to_demand_ratio.jl | 92 +++++++++++++++++-- src/data_structure/benders_data.jl | 3 +- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl b/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl index 7a7fec8965..849b6d4397 100644 --- a/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl +++ b/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl @@ -50,7 +50,11 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) + units_invested_available[u, s, t] - internal_fix_units_invested_available(unit=u, stochastic_scenario=s, t=t, _default=0) ) - * window_sum_duration( + * uaf_sum(m, u, comm) + for (u, s, t) in units_invested_available_indices(m; unit=unit(is_renewable=true)); + init=0, + #= + window_sum_duration( m, + unit_availability_factor(unit=u, stochastic_scenario=s) * unit_capacity(unit=u, node=n, direction=d, stochastic_scenario=s) @@ -60,24 +64,28 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) for (u, s, t) in units_invested_available_indices(m; unit=unit(is_renewable=true)) for (u, n, d) in unit__to_node(unit=u, node=node__commodity(commodity=comm), _compact=false); init=0, + =# ) + + get(mp_min_res_gen_to_demand_ratio_slack, (comm,), 0) >= + mp_min_res_gen_to_demand_ratio(commodity=comm) - * ( + * window_demand(m, comm) + + #= + ( sum( - window_sum_duration(m, demand(node=n, stochastic_scenario=s), current_window(m)) + #window_sum_duration(m, demand(node=n, stochastic_scenario=s), current_window(m)) + #window_sum(demand(node=n, stochastic_scenario=s), current_window(m)) + window_sum(demand(node=n, stochastic_scenario=s), current_window(m)) for (n, s) in node_stochastic_indices( m; node=intersect(indices(demand), node__commodity(commodity=comm)) ); init=0 ) + sum( - window_sum_duration( - m, - fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), - current_window(m) - ) + #window_sum_duration(m, fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), current_window(m)) + window_sum(fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), current_window(m)) for (n, s) in node_stochastic_indices( m; node=intersect(indices(fractional_demand), node__commodity(commodity=comm)) ) @@ -85,7 +93,75 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) init=0 ) ) + =# ) for comm in indices(mp_min_res_gen_to_demand_ratio) ) end + +function window_demand(m, comm) + + instance = m.ext[:spineopt].instance + + rf = roll_forward(model=instance) + wd = window_duration(model=instance) + + windows = [] + wstart = model_start(model=instance) + for wl in rf + push!(windows, TimeSlice(wstart, wstart + wd)) + wstart += wl + end + + # Compute demand + + regulardemand = sum( + SpineOpt.window_sum(demand(node=n, stochastic_scenario=s), window) + for (n, s) in SpineOpt.node_stochastic_indices( + m; node=intersect(indices(demand), node__commodity(commodity=comm)) + ) + for window in windows; + init=0 + ) # should be 0 + + fracdemand = sum( + SpineOpt.window_sum( + fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), + window + ) + for (n, s) in SpineOpt.node_stochastic_indices( + m; node=intersect(indices(fractional_demand), node__commodity(commodity=comm)) + ) + for ng in groups(n) + for window in windows; + init=0 + ) + regulardemand + fracdemand +end + +function uaf_sum(m, u, comm) + instance = m.ext[:spineopt].instance + + rf = roll_forward(model=instance) + wd = window_duration(model=instance) + + windows = [] + wstart = model_start(model=instance) + for wl in rf + push!(windows, TimeSlice(wstart, wstart + wd)) + wstart += wl + end + + uaf = sum( + SpineOpt.window_sum_duration(m, + unit_availability_factor(unit=u, stochastic_scenario=s) + * unit_capacity(unit=u, node=n, direction=d, stochastic_scenario=s) + * unit_conv_cap_to_flow(unit=u, node=n, direction=d, stochastic_scenario=s), + window + ) + for (u, s) in SpineOpt.unit_stochastic_indices(m; unit=u) + for (u, n, d) in unit__to_node(unit=u, node=node__commodity(commodity=comm), _compact=false) + for window in windows; + init=0 + ) +end \ No newline at end of file diff --git a/src/data_structure/benders_data.jl b/src/data_structure/benders_data.jl index 518f68fbd8..b0065b866a 100644 --- a/src/data_structure/benders_data.jl +++ b/src/data_structure/benders_data.jl @@ -125,7 +125,8 @@ end function _save_sp_unit_flow!(m, win_weight, tail=false) window_values = Dict( - k => win_weight * v for (k, v) in m.ext[:spineopt].values[:unit_flow] if iscontained(k.t, current_window(m)) + #k => win_weight * v for (k, v) in m.ext[:spineopt].values[:unit_flow] if iscontained(k.t, current_window(m)) + k => v for (k, v) in m.ext[:spineopt].values[:unit_flow] if iscontained(k.t, current_window(m)) ) pval_by_ent = _pval_by_entity(window_values) pvals_to_node = Dict( From a63a201412c74b4daa6f35519132d2298865229e Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 27 Sep 2023 09:58:54 +0200 Subject: [PATCH 11/33] Introduce sp_windows to advance work in mp-min-res-gen constraint Also, fix double counting in the uaf term: the uaf for each window was multiplying the potential investments increase for the whole model. But the uaf for each window should only multiply the potential investments increase for that window. If the investments resolution is larger than the window then it doesn't matter I guess, but anyways, this seems more correct. --- ...nstraint_mp_min_res_gen_to_demand_ratio.jl | 110 ++++-------------- src/data_structure/benders_data.jl | 5 +- src/data_structure/temporal_structure.jl | 42 ++++++- 3 files changed, 59 insertions(+), 98 deletions(-) diff --git a/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl b/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl index 849b6d4397..5754768afc 100644 --- a/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl +++ b/src/constraints/constraint_mp_min_res_gen_to_demand_ratio.jl @@ -38,54 +38,52 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) (commodity=comm,) => @constraint( m, + sum( - window_sum_duration( - m, sp_unit_flow(unit=u, node=n, direction=d, stochastic_scenario=s), current_window(m) - ) + window_sum_duration(m, sp_unit_flow(unit=u, node=n, direction=d, stochastic_scenario=s), window) + for window in m.ext[:spineopt].temporal_structure[:sp_windows] for (u, s) in unit_stochastic_indices(m; unit=unit(is_renewable=true)) for (u, n, d) in unit__to_node(unit=u, node=node__commodity(commodity=comm), _compact=false); init=0 ) + sum( - ( + sum( + units_invested_available[u, s, t] - internal_fix_units_invested_available(unit=u, stochastic_scenario=s, t=t, _default=0) + for (u, s, t) in units_invested_available_indices( + m; unit=u, stochastic_scenario=s, t=to_time_slice(m; t=window) + ); + init=0 ) - * uaf_sum(m, u, comm) - for (u, s, t) in units_invested_available_indices(m; unit=unit(is_renewable=true)); - init=0, - #= - window_sum_duration( + * window_sum_duration( m, + unit_availability_factor(unit=u, stochastic_scenario=s) * unit_capacity(unit=u, node=n, direction=d, stochastic_scenario=s) * unit_conv_cap_to_flow(unit=u, node=n, direction=d, stochastic_scenario=s), - t + window ) - for (u, s, t) in units_invested_available_indices(m; unit=unit(is_renewable=true)) + for window in m.ext[:spineopt].temporal_structure[:sp_windows] + for (u, s) in unit_stochastic_indices(m; unit=unit(is_renewable=true)) for (u, n, d) in unit__to_node(unit=u, node=node__commodity(commodity=comm), _compact=false); init=0, - =# ) - + get(mp_min_res_gen_to_demand_ratio_slack, (comm,), 0) >= + mp_min_res_gen_to_demand_ratio(commodity=comm) - * window_demand(m, comm) - - #= - ( + * ( sum( - #window_sum_duration(m, demand(node=n, stochastic_scenario=s), current_window(m)) - #window_sum(demand(node=n, stochastic_scenario=s), current_window(m)) - window_sum(demand(node=n, stochastic_scenario=s), current_window(m)) + window_sum_duration(m, demand(node=n, stochastic_scenario=s), window) + for window in m.ext[:spineopt].temporal_structure[:sp_windows] for (n, s) in node_stochastic_indices( m; node=intersect(indices(demand), node__commodity(commodity=comm)) ); init=0 ) + sum( - #window_sum_duration(m, fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), current_window(m)) - window_sum(fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), current_window(m)) + window_sum_duration( + m, + fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), + window + ) + for window in m.ext[:spineopt].temporal_structure[:sp_windows] for (n, s) in node_stochastic_indices( m; node=intersect(indices(fractional_demand), node__commodity(commodity=comm)) ) @@ -93,75 +91,7 @@ function add_constraint_mp_min_res_gen_to_demand_ratio!(m::Model) init=0 ) ) - =# ) for comm in indices(mp_min_res_gen_to_demand_ratio) ) -end - -function window_demand(m, comm) - - instance = m.ext[:spineopt].instance - - rf = roll_forward(model=instance) - wd = window_duration(model=instance) - - windows = [] - wstart = model_start(model=instance) - for wl in rf - push!(windows, TimeSlice(wstart, wstart + wd)) - wstart += wl - end - - # Compute demand - - regulardemand = sum( - SpineOpt.window_sum(demand(node=n, stochastic_scenario=s), window) - for (n, s) in SpineOpt.node_stochastic_indices( - m; node=intersect(indices(demand), node__commodity(commodity=comm)) - ) - for window in windows; - init=0 - ) # should be 0 - - fracdemand = sum( - SpineOpt.window_sum( - fractional_demand(node=n, stochastic_scenario=s) * demand(node=ng, stochastic_scenario=s), - window - ) - for (n, s) in SpineOpt.node_stochastic_indices( - m; node=intersect(indices(fractional_demand), node__commodity(commodity=comm)) - ) - for ng in groups(n) - for window in windows; - init=0 - ) - regulardemand + fracdemand -end - -function uaf_sum(m, u, comm) - instance = m.ext[:spineopt].instance - - rf = roll_forward(model=instance) - wd = window_duration(model=instance) - - windows = [] - wstart = model_start(model=instance) - for wl in rf - push!(windows, TimeSlice(wstart, wstart + wd)) - wstart += wl - end - - uaf = sum( - SpineOpt.window_sum_duration(m, - unit_availability_factor(unit=u, stochastic_scenario=s) - * unit_capacity(unit=u, node=n, direction=d, stochastic_scenario=s) - * unit_conv_cap_to_flow(unit=u, node=n, direction=d, stochastic_scenario=s), - window - ) - for (u, s) in SpineOpt.unit_stochastic_indices(m; unit=u) - for (u, n, d) in unit__to_node(unit=u, node=node__commodity(commodity=comm), _compact=false) - for window in windows; - init=0 - ) end \ No newline at end of file diff --git a/src/data_structure/benders_data.jl b/src/data_structure/benders_data.jl index b0065b866a..fd0bc27bd4 100644 --- a/src/data_structure/benders_data.jl +++ b/src/data_structure/benders_data.jl @@ -76,7 +76,7 @@ end function process_subproblem_solution!(m, win_weight) _save_sp_marginal_values!(m, win_weight) _save_sp_objective_value!(m, win_weight) - _save_sp_unit_flow!(m, win_weight) + _save_sp_unit_flow!(m) _save_sp_solution!(m) end @@ -123,9 +123,8 @@ function _save_sp_objective_value!(m, win_weight) ) end -function _save_sp_unit_flow!(m, win_weight, tail=false) +function _save_sp_unit_flow!(m, tail=false) window_values = Dict( - #k => win_weight * v for (k, v) in m.ext[:spineopt].values[:unit_flow] if iscontained(k.t, current_window(m)) k => v for (k, v) in m.ext[:spineopt].values[:unit_flow] if iscontained(k.t, current_window(m)) ) pval_by_ent = _pval_by_entity(window_values) diff --git a/src/data_structure/temporal_structure.jl b/src/data_structure/temporal_structure.jl index 5f449d5733..f8ef865452 100644 --- a/src/data_structure/temporal_structure.jl +++ b/src/data_structure/temporal_structure.jl @@ -85,6 +85,21 @@ function _model_duration_unit(instance::Object) get(Dict(:minute => Minute, :hour => Hour), duration_unit(model=instance, _strict=false), Minute) end +function _model_window_duration(instance) + m_start = model_start(model=instance) + m_end = model_end(model=instance) + m_duration = m_end - m_start + w_duration = window_duration(model=instance, _strict=false) + if w_duration === nothing + w_duration = roll_forward(model=instance, i=1, _strict=false) + end + if w_duration === nothing + m_duration + else + min(w_duration, m_duration) + end +end + """ _generate_current_window!(m::Model) @@ -93,12 +108,9 @@ Generate the current window TimeSlice for given model. function _generate_current_window!(m::Model) instance = m.ext[:spineopt].instance w_start = model_start(model=instance) - m_end = model_end(model=instance) - w_duration = window_duration(model=instance, _strict=false) - w_duration = w_duration !== nothing ? w_duration : roll_forward(model=instance, i=1, _strict=false) - w_end = w_duration === nothing ? m_end : min(w_start + w_duration, m_end) + w_end = w_start + _model_window_duration(instance) m.ext[:spineopt].temporal_structure[:current_window] = TimeSlice( - w_start, w_end; duration_unit=_model_duration_unit(m.ext[:spineopt].instance) + w_start, w_end; duration_unit=_model_duration_unit(instance) ) end @@ -407,6 +419,25 @@ function _generate_representative_time_slice!(m::Model) end end +function _generate_sp_windows!(m::Model) + instance = m.ext[:spineopt].instance + w_start = model_start(model=instance) + w_duration = _model_window_duration(instance) + w_end = w_start + w_duration + m.ext[:spineopt].temporal_structure[:sp_windows] = windows = [] + push!(windows, TimeSlice(w_start, w_end; duration_unit=_model_duration_unit(instance))) + i = 1 + while true + rf = roll_forward(model=instance, i=i, _strict=false) + rf in (nothing, Minute(0)) && break + w_end >= model_end(model=instance) && break + w_start += w_duration + w_end += w_duration + push!(windows, TimeSlice(w_start, w_end; duration_unit=_model_duration_unit(instance))) + i += 1 + end +end + """ Find indices in `source` that overlap `t` and return values for those indices in `target`. Used by `to_time_slice`. @@ -459,6 +490,7 @@ Create the master problem temporal structure for SpineOpt benders. """ function generate_master_temporal_structure!(m_mp::Model) _generate_master_window_and_time_slice!(m_mp) + _generate_sp_windows!(m_mp) _generate_output_time_slices!(m_mp) _generate_time_slice_relationships!(m_mp) end From 4514909340a8d448054251e598256b621e83d4ea Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 27 Sep 2023 10:59:40 +0200 Subject: [PATCH 12/33] Fix tests --- src/data_structure/temporal_structure.jl | 4 ++-- test/run_spineopt_benders.jl | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/data_structure/temporal_structure.jl b/src/data_structure/temporal_structure.jl index f8ef865452..d581e8dcef 100644 --- a/src/data_structure/temporal_structure.jl +++ b/src/data_structure/temporal_structure.jl @@ -93,10 +93,10 @@ function _model_window_duration(instance) if w_duration === nothing w_duration = roll_forward(model=instance, i=1, _strict=false) end - if w_duration === nothing + if w_duration === nothing || m_start + w_duration > m_end m_duration else - min(w_duration, m_duration) + w_duration end end diff --git a/test/run_spineopt_benders.jl b/test/run_spineopt_benders.jl index 86c675c004..d1c9c40372 100644 --- a/test/run_spineopt_benders.jl +++ b/test/run_spineopt_benders.jl @@ -708,7 +708,9 @@ function _test_benders_mp_min_res_gen_to_demand_ratio() @test length(cons) == 1 observed_con = constraint_object(only(values(cons))) expected_con = @build_constraint( - + ucap * sum(duration(k.t) * v for (k, v) in invest_vars if start(k.t) >= DateTime(2000)) + + ucap * sum( + duration(k.t) * v for (k, v) in invest_vars if DateTime(2000) <= start(k.t) < DateTime(2000, 1, 2) + ) + only(values(slack_vars)) >= + 24 * dem * mrg2d_ratio From dc512348ff33e18b45a2cd6f16cc965c31947f93 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 27 Sep 2023 11:51:14 +0200 Subject: [PATCH 13/33] Fix sp_windows --- src/data_structure/temporal_structure.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data_structure/temporal_structure.jl b/src/data_structure/temporal_structure.jl index d581e8dcef..4fee1e147b 100644 --- a/src/data_structure/temporal_structure.jl +++ b/src/data_structure/temporal_structure.jl @@ -431,8 +431,8 @@ function _generate_sp_windows!(m::Model) rf = roll_forward(model=instance, i=i, _strict=false) rf in (nothing, Minute(0)) && break w_end >= model_end(model=instance) && break - w_start += w_duration - w_end += w_duration + w_start += rf + w_end += rf push!(windows, TimeSlice(w_start, w_end; duration_unit=_model_duration_unit(instance))) i += 1 end From de1eca4704486c2fc0a9e441058b870bf9d031b6 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 27 Sep 2023 12:00:07 +0200 Subject: [PATCH 14/33] Introduce benders_starting_{units/connections/storages}_invested So the user can fix the investments during the first Benders iteration. --- src/run_spineopt_benders.jl | 43 +++++++++++++ templates/spineopt_template.json | 3 + test/run_spineopt_benders.jl | 103 +++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) diff --git a/src/run_spineopt_benders.jl b/src/run_spineopt_benders.jl index 3185c3f346..af5f02949c 100644 --- a/src/run_spineopt_benders.jl +++ b/src/run_spineopt_benders.jl @@ -47,8 +47,14 @@ function rerun_spineopt_benders!( _init_mp_model!(m_mp; log_level=log_level) max_benders_iterations = max_iterations(model=m_mp.ext[:spineopt].instance) j = 1 + undo_force_starting_investments! = nothing while optimize @log log_level 0 "\nStarting Benders iteration $j" + if j == 1 + undo_force_starting_investments! = _force_starting_investments!(m_mp) + elseif j == 2 + undo_force_starting_investments!() + end optimize_model!(m_mp; log_level=log_level) || break @timelog log_level 2 "Processing master problem solution" process_master_problem_solution!(m_mp) k = 1 @@ -227,3 +233,40 @@ end _unfix(v::VariableRef) = is_fixed(v) && unfix(v) _unfix(::Call) = nothing + +""" +Force starting investments and return a function to be called without arguments to undo the operation. +""" +function _force_starting_investments!(m::Model) + callbacks = vcat( + _do_force_starting_investments!(m, :units_invested_available, benders_starting_units_invested), + _do_force_starting_investments!(m, :connections_invested_available, benders_starting_connections_invested), + _do_force_starting_investments!(m, :storages_invested_available, benders_starting_storages_invested), + ) + () -> for c in callbacks c() end +end + +function _do_force_starting_investments!(m::Model, variable_name::Symbol, benders_starting_invested::Parameter) + callbacks = [] + for (ind, var) in m.ext[:spineopt].variables[variable_name] + start(ind.t) >= start(current_window(m)) || continue + starting_invested = benders_starting_invested(; ind..., _strict=false) + starting_invested === nothing && continue + push!(callbacks, () -> unfix(var)) + if has_lower_bound(var) + x = lower_bound(var) + push!(callbacks, () -> set_lower_bound(var, x)) + end + if has_upper_bound(var) + x = upper_bound(var) + push!(callbacks, () -> set_upper_bound(var, x)) + end + if is_fixed(var) + x = fix_value(var) + push!(callbacks, () -> fix(var, x; force=true)) + end + fix(var, starting_invested; force=true) + end + callbacks +end + diff --git a/templates/spineopt_template.json b/templates/spineopt_template.json index 6a09f9ed4f..ed6a79a0a9 100644 --- a/templates/spineopt_template.json +++ b/templates/spineopt_template.json @@ -135,6 +135,7 @@ ["commodity", "mp_min_res_gen_to_demand_ratio_slack_penalty", null, null, "Penalty for violating the minimum renewable generation to demand ratio."], ["commodity", "is_active", true, "boolean_value_list", "If false, the object is excluded from the model if the tool filter object activity control is specified"], ["connection", "candidate_connections", null, null, "The number of connections that may be invested in"], + ["connection", "benders_starting_connections_invested", null, null, "Fixes the number of connections invested during the first Benders iteration"], ["connection", "forced_availability_factor", null, null, "Availability factor due to outages/deratings."], ["connection", "connection_availability_factor", 1.0, null, "Availability of the `connection`, acting as a multiplier on its `connection_capacity`. Typically between 0-1."], ["connection", "connection_contingency", null, "boolean_value_list", "A boolean flag for defining a contingency `connection`."], @@ -178,6 +179,7 @@ ["model", "window_weight", 1, null, "The weight of the window in the rolling subproblem"], ["node", "balance_type", "balance_type_node", "balance_type_list", "A selector for how the `:nodal_balance` constraint should be handled."], ["node", "candidate_storages", null, null, "Determines the maximum number of new storages which may be invested in"], + ["node", "benders_starting_storages_invested", null, null, "Fixes the number of storages invested during the first Benders iteration"], ["node", "demand", 0.0, null, "Demand for the `commodity` of a `node`. Energy gains can be represented using negative `demand`."], ["node", "downward_reserve", false, null, "Identifier for `node`s providing downward reserves"], ["node", "fix_node_state", null, null, "Fixes the corresponding `node_state` variable to the provided value. Can be used for e.g. fixing boundary conditions."], @@ -234,6 +236,7 @@ ["temporal_block", "weight", 1.0, null, "Weighting factor of the temporal block associated with the objective function"], ["temporal_block", "representative_periods_mapping", null, null, "Map from date time to representative temporal block name"], ["unit", "candidate_units", null, null, "Number of units which may be additionally constructed"], + ["unit", "benders_starting_units_invested", null, null, "Fixes the number of units invested during the first Benders iteration"], ["unit", "curtailment_cost", null, null, "Costs for curtailing generation. Essentially, accrues costs whenever `unit_flow` not operating at its maximum available capacity. E.g. EUR/MWh"], ["unit", "fix_units_invested", null, null, "Fix the value of the `units_invested` variable."], ["unit", "fix_units_invested_available", null, null, "Fix the value of the `units_invested_available` variable"], diff --git a/test/run_spineopt_benders.jl b/test/run_spineopt_benders.jl index d1c9c40372..72f25b1080 100644 --- a/test/run_spineopt_benders.jl +++ b/test/run_spineopt_benders.jl @@ -745,11 +745,114 @@ function _test_benders_mp_min_res_gen_to_demand_ratio() end end +function _test_benders_starting_units_invested() + @testset "benders_starting_units_invested" begin + benders_gap = 1e-6 # needed so that we get the exact master problem solution + mip_solver_options_benders = unparse_db_value(Map(["HiGHS.jl"], [Map(["mip_rel_gap"], [benders_gap])])) + res = 6 + dem = ucap = 10 + rf = 6 + look_ahead = 3 + vom_cost_ = 2 + vom_cost_alt = vom_cost_ / 2 + op_cost_no_inv = ucap * vom_cost_ * (24 + look_ahead) + op_cost_inv = ucap * vom_cost_alt * (24 + look_ahead) + do_not_inv_cost = op_cost_no_inv - op_cost_inv # minimum cost at which investment is not profitable, 270.0 + u_inv_cost = do_not_inv_cost + 1 # needed, not sure why + @testset for (max_iters, should_invest) in ((10, false), (1, true)) + url_in, url_out, file_path_out = _test_run_spineopt_benders_setup() + objects = [ + ["unit", "unit_ab_alt"], + ["output", "total_costs"], + ["output", "units_invested"], + ["output", "units_mothballed"], + ["output", "units_invested_available"], + ["output", "unit_investment_costs"], + ["temporal_block", "investments_hourly"], + ] + relationships = [ + ["unit__to_node", ["unit_ab_alt", "node_b"]], + ["units_on__temporal_block", ["unit_ab_alt", "hourly"]], + ["units_on__stochastic_structure", ["unit_ab_alt", "deterministic"]], + ["model__temporal_block", ["instance", "investments_hourly"]], + ["model__default_investment_temporal_block", ["instance", "investments_hourly"]], + ["model__default_investment_stochastic_structure", ["instance", "deterministic"]], + ["report__output", ["report_x", "total_costs"]], + ["report__output", ["report_x", "units_invested"]], + ["report__output", ["report_x", "units_mothballed"]], + ["report__output", ["report_x", "units_invested_available"]], + ["report__output", ["report_x", "unit_investment_costs"]], + ] + object_parameter_values = [ + ["model", "instance", "roll_forward", unparse_db_value(Hour(rf))], + ["model", "instance", "model_type", "spineopt_benders"], + ["model", "instance", "max_iterations", max_iters], + ["model", "instance", "db_mip_solver_options", mip_solver_options_benders], + ["node", "node_b", "demand", dem], + ["unit", "unit_ab_alt", "number_of_units", 0], + ["unit", "unit_ab_alt", "candidate_units", 1], + ["unit", "unit_ab_alt", "benders_starting_units_invested", 1], + ["unit", "unit_ab_alt", "unit_investment_variable_type", "unit_investment_variable_type_integer"], + ["unit", "unit_ab_alt", "online_variable_type", "unit_online_variable_type_integer"], + ["unit", "unit_ab_alt", "unit_investment_cost", u_inv_cost], + ["temporal_block", "hourly", "block_end", unparse_db_value(Hour(rf + look_ahead))], + ["temporal_block", "investments_hourly", "block_end", unparse_db_value(Hour(24 + look_ahead))], + ["temporal_block", "hourly", "resolution", unparse_db_value(Hour(res))], + ["temporal_block", "investments_hourly", "resolution", unparse_db_value(Hour(res))], + ] + relationship_parameter_values = [ + ["unit__to_node", ["unit_ab", "node_b"], "unit_capacity", ucap], + ["unit__to_node", ["unit_ab", "node_b"], "vom_cost", vom_cost_], + ["unit__to_node", ["unit_ab_alt", "node_b"], "unit_capacity", ucap], + ["unit__to_node", ["unit_ab_alt", "node_b"], "vom_cost", vom_cost_alt], + ] + SpineInterface.import_data( + url_in; + objects=objects, + relationships=relationships, + object_parameter_values=object_parameter_values, + relationship_parameter_values=relationship_parameter_values + ) + rm(file_path_out; force=true) + run_spineopt(url_in, url_out; log_level=0) + using_spinedb(url_out, Y) + @testset "total_cost" begin + for t in DateTime(2000, 1, 1):Hour(6):DateTime(2000, 1, 1, 23) + @test Y.total_costs(model=Y.model(:instance), t=t) == (should_invest ? 60 : 120) + end + end + @testset "unit_investment_costs" begin + @test Y.objective_unit_investment_costs(model=Y.model(:instance), t=DateTime(2000, 1, 1)) == ( + should_invest ? u_inv_cost : 0 + ) + end + @testset "invested" begin + @testset for t in DateTime(2000, 1, 1):Hour(6):DateTime(2000, 1, 2) + @test Y.units_invested(unit=Y.unit(:unit_ab_alt), t=t) == ( + should_invest && t == DateTime(2000, 1, 1) ? 1 : 0 + ) + end + end + @testset "mothballed" begin + @testset for t in DateTime(2000, 1, 1):Hour(6):DateTime(2000, 1, 2) + @test Y.units_mothballed(unit=Y.unit(:unit_ab_alt), t=t) == 0 + end + end + @testset "available" begin + @testset for t in DateTime(2000, 1, 1):Hour(6):DateTime(2000, 1, 2) + @test Y.units_invested_available(unit=Y.unit(:unit_ab_alt), t=t) == (should_invest ? 1 : 0) + end + end + end + end +end + @testset "run_spineopt_benders" begin _test_benders_unit() _test_benders_storage() _test_benders_rolling_representative_periods() _test_benders_rolling_representative_periods_yearly_investments_multiple_units() _test_benders_mp_min_res_gen_to_demand_ratio() + _test_benders_starting_units_invested() # FIXME: _test_benders_unit_storage() end \ No newline at end of file From 11de5c64c9aac49646c7609e21189a0667d074f9 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 27 Sep 2023 13:05:12 +0200 Subject: [PATCH 15/33] Introduce min_iterations --- src/run_spineopt_benders.jl | 3 ++- templates/spineopt_template.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/run_spineopt_benders.jl b/src/run_spineopt_benders.jl index af5f02949c..b834de4b18 100644 --- a/src/run_spineopt_benders.jl +++ b/src/run_spineopt_benders.jl @@ -45,6 +45,7 @@ function rerun_spineopt_benders!( log_level=log_level ) _init_mp_model!(m_mp; log_level=log_level) + min_benders_iterations = min_iterations(model=m_mp.ext[:spineopt].instance) max_benders_iterations = max_iterations(model=m_mp.ext[:spineopt].instance) j = 1 undo_force_starting_investments! = nothing @@ -91,7 +92,7 @@ function rerun_spineopt_benders!( @log log_level 1 "Objective upper bound: $(@sprintf("%.5e", m_mp.ext[:spineopt].objective_upper_bound[])); " gap = last(m_mp.ext[:spineopt].benders_gaps) @log log_level 1 "Gap: $(@sprintf("%1.4f", gap * 100))%" - if gap <= max_gap(model=m_mp.ext[:spineopt].instance) + if gap <= max_gap(model=m_mp.ext[:spineopt].instance) && j >= min_benders_iterations @log log_level 1 "Benders tolerance satisfied, terminating..." break end diff --git a/templates/spineopt_template.json b/templates/spineopt_template.json index ed6a79a0a9..34058de2b1 100644 --- a/templates/spineopt_template.json +++ b/templates/spineopt_template.json @@ -160,6 +160,7 @@ ["model", "duration_unit", "hour", "duration_unit_list", "Defines the base temporal unit of the `model`. Currently supported values are either an `hour` or a `minute`."], ["model", "is_active", true, "boolean_value_list", "If false, the object is excluded from the model if the tool filter object activity control is specified"], ["model", "max_gap", 0.05, null, "Specifies the maximum optimality gap for the model. Currently only used for the master problem within a decomposed structure"], + ["model", "min_iterations", 1.0, null, "Specifies the minimum number of iterations for the model. Currently only used for the master problem within a decomposed structure"], ["model", "max_iterations", 10.0, null, "Specifies the maximum number of iterations for the model. Currently only used for the master problem within a decomposed structure"], ["model", "max_mga_iterations", null, null, "Define the number of mga iterations, i.e. how many alternative solutions will be generated."], ["model", "max_mga_slack", 0.05, null, "Defines the maximum slack by which the alternative solution may differ from the original solution (e.g. 5% more than initial objective function value)"], From 737ba95a217dcf1980b4a948164b25b61b930520 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 28 Sep 2023 09:03:22 +0200 Subject: [PATCH 16/33] Fix docs to work with latest Documenter.jl --- docs/make.jl | 1 + docs/src/tutorial/case_study_a5.md | 60 +++++++++---------- docs/src/tutorial/simple_system.md | 32 +++++----- docs/src/tutorial/tutorialTwoHydro.md | 85 ++++++++++++++------------- 4 files changed, 90 insertions(+), 88 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 66ae7a3436..621dd564de 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -75,5 +75,6 @@ makedocs( sitename="SpineOpt.jl", format=Documenter.HTML(prettyurls=get(ENV, "CI", nothing) == "true"), # uncomment to deploy locally pages=pages, + warnonly=true ) deploydocs(repo="github.com/spine-tools/SpineOpt.jl.git", versions=["stable" => "v^", "v#.#"]) diff --git a/docs/src/tutorial/case_study_a5.md b/docs/src/tutorial/case_study_a5.md index 3317ca6b39..7f00e852a4 100644 --- a/docs/src/tutorial/case_study_a5.md +++ b/docs/src/tutorial/case_study_a5.md @@ -68,13 +68,13 @@ power station in the river is modelled using the following elements: Below is a schematic of the model. For clarity, only the Rebnis station is presented in full detail: -![image](../figs_a5/case_study_a5_schematic.png) +![image](figs_a5/case_study_a5_schematic.png) In order to run this tutorial you must first execute some preliminary -steps from the [Simple System](../../simple_system/) tutorial. +steps from the [Simple System](simple_system.md) tutorial. Specifically, execute all steps from the -[guide](../../simple_system/index.html#guide), up to and including the step of -[importing the spineopt database template](../../simple_system/index.html#importing-the-spineopt-database-template). +[guide](simple_system.md#guide), up to and including the step of +[importing the spineopt database template](simple_system.md#importing-the-spineopt-database-template). It is advisable to go through the whole tutorial in order to familiarise yourself with Spine. @@ -85,10 +85,10 @@ yourself with Spine. ### Importing the SpineOpt database template -- Download [the SpineOpt database template](../../../templates/spineopt_template.json) (right click on the link, then select *Save link as...*) +- Download [the SpineOpt database template](https://raw.githubusercontent.com/spine-tools/SpineOpt.jl/master/templates/spineopt_template.json) (right click on the link, then select *Save link as...*) - Select the *input* Data Store item in the *Design View*. - Go to *Data Store Properties* and hit **Open editor**. This will open the newly created database in the *Spine DB Editor*, looking similar to image below. - ![image](../figs_a5/case_study_a5_spine_db_editor_empty.png) + ![image](figs_a5/case_study_a5_spine_db_editor_empty.png) !!! note The Spine DB editor is a dedicated interface within Spine Toolbox for visualizing and managing Spine databases. - Press **Alt + F** to display the editor menu, select **File -> Import...**, @@ -116,7 +116,7 @@ yourself with Spine. There are two options in this tutorial to enter data in the Database. The first one is to enter data manually and the second to - [use the importer](../index.html#Using-the-Importer) functionality. These are described in the + [use the importer](../index.md#Using-the-Importer) functionality. These are described in the next two subsections respectively and produce similar models. The model created when using the importer creates a model with two-segments efficiency curves for converting water to electricity (while the model @@ -147,7 +147,7 @@ yourself with Spine. Kvistforsen_pwr_plant - Go to *Object tree* (on the top left of the window, usually), right-click on `unit` and select **Add objects** from the context menu. This will open the *Add objects* dialog. - Select the first cell under the **object name** column and press **Ctrl+V**. This will paste the list of plant names from the clipboard into that column; the **object class name** column will be filled automatically with ‘unit‘. The form should now be looking similar to this: - ![image](../figs_a5/add_power_plant_units.png) + ![image](figs_a5/add_power_plant_units.png) - Click **Ok**. - Back in the *Spine DB Editor*, under *Object tree*, double click on `unit` to confirm that the objects are effectively there. - Commit changes with the message ‘Add power plants’. @@ -240,16 +240,16 @@ yourself with Spine. - To specify the general behaviour of our model, stay in the *Spine DB Editor* and enter model parameter values as follows: - Select the model parameter value data (i.e. select all, **Ctrl+A**) from the file below and copy it to the clipboard (**Ctrl+C**): - [cs-a5-model-parameter-values.txt](../../data/cs-a5-model-parameter-values.txt) + [cs-a5-model-parameter-values.txt](data/cs-a5-model-parameter-values.txt) - Select `instance` in the *Object tree* and inspect the table in *Object parameter value* (on the top-center of the window, usually). Make sure that the columns in the table are ordered as follows (drag and drop columns if you need to change their order): object_class_name | object_name | parameter_name | alternative_name | value | database - Select the first cell under `object_class_name` and press **Ctrl+V**. This will paste the model parameter value data from the clipboard into the table. The form should be looking like this: - ![image](../figs_a5/case_study_a5_model_parameters.png) + ![image](figs_a5/case_study_a5_model_parameters.png) - Specify the resolution of our temporal block `some_week` in the same way using the data below: - [cs-a5-temporal_block-parameter-values.txt](../../data/cs-a5-temporal_block-parameter-values.txt) + [cs-a5-temporal_block-parameter-values.txt](data/cs-a5-temporal_block-parameter-values.txt) - Specify the behaviour of all system nodes with the data below, where: - `demand` represents the local inflow (negative in most cases). @@ -261,7 +261,7 @@ yourself with Spine. that there aren't any loses). - `node_state_cap` is the maximum level of the reservoirs. To do this in one single step, simply select `node` in the *Object tree* and paste the following values in the first empty cell: - [cs-a5-node-parameter-values.txt](../../data/cs-a5-node-parameter-values.txt) + [cs-a5-node-parameter-values.txt](data/cs-a5-node-parameter-values.txt) #### Establishing relationships @@ -275,7 +275,7 @@ yourself with Spine. common electricity node. Both the power plants and the electricity load belong to the class `unit`. - Select the list of unit and node names from below and copy it to the clipboard (**Ctrl+C**). - [cs-a5-unit__from_node.txt](../../data/cs-a5-unit__from_node.txt) + [cs-a5-unit__from_node.txt](data/cs-a5-unit__from_node.txt) - In the *Spine DB Editor*, go to *Relationship tree* (on the bottom left of the window, usually), right-click on `unit__from_node` and select **Add relationships** from the @@ -284,7 +284,7 @@ yourself with Spine. **Ctrl+V**. This will paste the list of plant and node names from the clipboard into the table. The form should be looking like this: - ![image](../figs_a5/add_pwr_plant_water_from_node.png) + ![image](figs_a5/add_pwr_plant_water_from_node.png) - Click **Ok**. - Back in the *Spine DB Editor*, under *Relationship tree*, double click on `unit__from_node` to confirm that the relationships are @@ -297,7 +297,7 @@ yourself with Spine. a power plant releases water to the station's lower water node, and that the power plants supply electricity to the common electricity node. Use the following data and do as before: - [cs-a5-unit__to_node.txt](../../data/cs-a5-unit__to_node.txt) + [cs-a5-unit__to_node.txt](data/cs-a5-unit__to_node.txt) !!! note At this point, you might be wondering what's the purpose of the @@ -315,13 +315,13 @@ yourself with Spine. discharged, it is taken from the *lower* water node of the station, if spilled it is taken from the *upper* water node of the station. Use the following data and do as before: - [cs-a5-connection__from_node.txt](../../data/cs-a5-connection__from_node.txt) + [cs-a5-connection__from_node.txt](data/cs-a5-connection__from_node.txt) - Create relationships of the class `connection__to_node` to represent that both discharge and spill are released into the *upper* node of the next downstream station. Use the following data and do as before: - [cs-a5-connection__to_node.txt](../../data/cs-a5-connection__to_node.txt) + [cs-a5-connection__to_node.txt](data/cs-a5-connection__to_node.txt) !!! note At this point, you might be wondering what's the purpose of the @@ -338,7 +338,7 @@ yourself with Spine. water, for electricity nodes with respect to electricity. This way, you link all nodes to either the commocity `water` or the commodity `electricity`. Use the following data and do as before: - [cs-a5-node__commodity.txt](../../data/cs-a5-node__commodity.txt) + [cs-a5-node__commodity.txt](data/cs-a5-node__commodity.txt) - Define that all nodes in our model have to be balanced at each time step. To do this, you create a relationship of the class @@ -363,20 +363,20 @@ yourself with Spine. - Finally, the values of all parameters have to be entered. Specify the capacity of all hydropower plants, and their respective variable operating cost by entering `unit__from_node` parameter values as follows: - - Select the data from the text-box below and copy it to the clipboard (**Ctrl+C**): [cs-a5-unit__from_node-relationship-parameter-values.txt](../../data/cs-a5-unit__from_node-relationship-parameter-values.txt) + - Select the data from the text-box below and copy it to the clipboard (**Ctrl+C**): [cs-a5-unit__from_node-relationship-parameter-values.txt](data/cs-a5-unit__from_node-relationship-parameter-values.txt) - In the *Spine DB Editor*, go to *Relationship tree* (on the bottom left of the window, usually), and click on `unit__from_node`. Then, go to *Relationship parameter value* (on the bottom-center of the window, usually). Make sure that the columns in the table are ordered as follows (drag and drop columns if you need to change their order): relationship_class_name | object_name_list | parameter_name | alternative_name | value | database - Select the first cell under `relationship_class_name` and press **Ctrl+V**. This will paste the parameter value data from the clipboard into the table. - Specify the conversion ratio between discharged water and generated electricity for each hydropower station as well as a similar conversion rate (set to 1) to represent that water cannot be lost between upper and lower water nodes. Use the following data to enter the parameter values `unit__from_node`: - [cs-a5-unit\_\_node\_\_node-relationship-parameter-values.txt](../../data/cs-a5-unit__node__node-relationship-parameter-values.txt) + [cs-a5-unit\_\_node\_\_node-relationship-parameter-values.txt](data/cs-a5-unit__node__node-relationship-parameter-values.txt) - Specify the average discharge and spillage in the first hours of the simulation. Use the following data to enter the parameter values `connection__from_node`: - [cs-a5-connection__from_node-relationship-parameter-values.txt](../../data/cs-a5-connection__from_node-relationship-parameter-values.txt) + [cs-a5-connection__from_node-relationship-parameter-values.txt](data/cs-a5-connection__from_node-relationship-parameter-values.txt) - Finally, specify the delay (the time it takes for the water to run between water nodes) and the transfer ratio (being equal to 1) of different water connections. Use the following data to enter the parameter values `connection__node_node`: - [cs-a5-connection\_\_node\_\_node-relationship-parameter-values.txt](../../data/cs-a5-connection__node__node-relationship-parameter-values.txt) + [cs-a5-connection\_\_node\_\_node-relationship-parameter-values.txt](data/cs-a5-connection__node__node-relationship-parameter-values.txt) - When you're ready, commit all changes to the database via the main menu (**Alt + F**). @@ -385,7 +385,7 @@ yourself with Spine. #### Additional Steps for Project Setup -- Drag the Data Connection icon ![image](../figs_a5/file-alt.png) from the tool bar and drop it into the +- Drag the Data Connection icon ![image](figs_a5/file-alt.png) from the tool bar and drop it into the Design View. This will open the *Add Data connection dialogue*. Type in ‘Data Connection’ and click on **Ok**. - To import the model into the Spine database, you need to create an @@ -395,7 +395,7 @@ yourself with Spine. will pop-up. - Type ‘Import Model’ as the name of the specification. Save the specification by using **Ctrl+S** and close the window. -- Drag the newly created Import Model Importer item icon ![image](../figs_a5/database-import.png) +- Drag the newly created Import Model Importer item icon ![image](figs_a5/database-import.png) from the tool bar and drop it into the *Design View*. This will open the Add Importer dialogue. Type in ‘Import Model’ and click on **Ok**. @@ -403,13 +403,13 @@ yourself with Spine. one of the Data Connection’s connectors and then on one of the Importer’s connectors. Connect similarly the importer with the input database. Now the project should look similar to this: - ![image](../figs_a5/items_connections.png) + ![image](figs_a5/items_connections.png) - From the main menu, select **File -> Save project**. #### Importing the model -- Download [the data](../../data/a5.xlsx) - and [the accompanying mapping](../../data/A5_importer_specification.json) +- Download [the data](data/a5.xlsx) + and [the accompanying mapping](data/A5_importer_specification.json) (right click on the links, then select *Save link as...*). - Add a reference to the file containing the model. - Select the *Data Connection item* in the *Design View* to show the *Data Connection properties* window (on the right side of the window usually). @@ -419,7 +419,7 @@ yourself with Spine. ## Executing the workflow Once the workflow is defined and input data is in place, the project is -ready to be executed. Hit the **Execute project** button ![image](../figs_a5/play-circle.png) +ready to be executed. Hit the **Execute project** button ![image](figs_a5/play-circle.png) on the tool bar. You should see ‘Executing All Directed Acyclic Graphs’ printed in the @@ -432,7 +432,7 @@ is complete. Select the output data store and open the Spine DB editor. -![image](../figs_a5/case_study_a5_output.png) +![image](figs_a5/case_study_a5_output.png) To checkout the flow on the electricity load (i.e., the total @@ -443,7 +443,7 @@ double-click the first cell under `value`. The *Parameter value editor* will pop up. You should see something like this: -![image](../figs_a5/case_study_a5_output_electricity_load_unit_flow.png) +![image](figs_a5/case_study_a5_output_electricity_load_unit_flow.png) !!! note diff --git a/docs/src/tutorial/simple_system.md b/docs/src/tutorial/simple_system.md index baa5685df0..0849caba30 100644 --- a/docs/src/tutorial/simple_system.md +++ b/docs/src/tutorial/simple_system.md @@ -20,7 +20,7 @@ system on Spine Toolbox. - The demand at the electricity node is 150 MWh. - The fuel node is able to provide infinite energy. -![image](../figs_simple_system/simple_system_schematic.png) +![image](figs_simple_system/simple_system_schematic.png) ### Installation and upgrades @@ -53,7 +53,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur - Go to *Data Store Properties* and hit **Open editor**. This will open the newly created database in the *Spine DB editor*, looking similar to this: -![image](../figs_a5/case_study_a5_spine_db_editor_empty.png) +![image](figs_a5/case_study_a5_spine_db_editor_empty.png) !!! note The *Spine DB editor* is a dedicated interface within Spine Toolbox @@ -91,7 +91,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur then press *Ok*. This will create two objects of class *node*, called *fuel\_node* and *electricity\_node*. -![image](../figs_simple_system/simple_system_add_nodes.png) +![image](figs_simple_system/simple_system_add_nodes.png) - Right click on the *unit* class, and select *Add objects* from the context menu. The *Add objects* dialog will pop @@ -106,7 +106,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur then press *Ok*. This will create two objects of class *unit*, called *power\_plant\_a* and *power\_plant\_b*. -![image](../figs_simple_system/simple_system_add_units.png) +![image](figs_simple_system/simple_system_add_units.png) !!! note To modify an object after you enter it, right click on it and select @@ -126,7 +126,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* take energy from the *fuel\_node*. -![image](../figs_simple_system/simple_system_add_unit__from_node_relationships.png) +![image](figs_simple_system/simple_system_add_unit__from_node_relationships.png) - Right click on the *unit\_\_to_node* class, and select *Add relationships* from the context menu. The *Add relationships* @@ -136,7 +136,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into the *electricity\_node*. -![image](../figs_simple_system/simple_system_add_unit__to_node_relationships.png) +![image](figs_simple_system/simple_system_add_unit__to_node_relationships.png) - Right click on the *report\_\_output* class, and select *Add relationships* from the context menu. The *Add relationships* @@ -147,7 +147,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur then press *Ok*. This will tell SpineOpt to write the value of the *unit\_flow* optimization variable to the output database, as part of *report1*. -![image](../figs_simple_system/simple_system_add_report__output_relationships.png) +![image](figs_simple_system/simple_system_add_report__output_relationships.png) !!! note In SpineOpt, outputs represent optimization variables that can be @@ -165,7 +165,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur alternative, and enter the value *100* as seen in the image below. This will establish that there's a demand of '100' at the electricity node. -![image](../figs_simple_system/simple_system_electricity_demand.png) +![image](figs_simple_system/simple_system_electricity_demand.png) - Select *fuel\_node* in the *Object tree*. @@ -174,7 +174,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur alternative, and enter the value *balance\_type\_none* as seen in the image below. This will establish that the fuel node is not balanced, and thus provide as much fuel as needed. -![image](../figs_simple_system/simple_system_fuel_balance_type.png) +![image](figs_simple_system/simple_system_fuel_balance_type.png) #### Specifying relationship parameter values @@ -186,7 +186,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur *Base* alternative, and enter the value *25* as seen in the image below. This will set the operating cost for *power\_plant\_a*. -![image](../figs_simple_system/simple_system_power_plant_a_vom_cost.png) +![image](figs_simple_system/simple_system_power_plant_a_vom_cost.png) - Select *power\_plant\_b | fuel\_node* in the *Relationship tree*. @@ -196,7 +196,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur alternative, and enter the value *50* as seen in the image below. This will set the operating cost for *power\_plant\_b*. -![image](../figs_simple_system/simple_system_power_plant_b_vom_cost.png) +![image](figs_simple_system/simple_system_power_plant_b_vom_cost.png) - In *Relationship tree*, expand the *unit\_\_to_node* class and select *power\_plant\_a | electricity\_node*. @@ -206,7 +206,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur alternative, and enter the value *100* as seen in the image below. This will set the capacity for *power\_plant\_a*. -![image](../figs_simple_system/simple_system_power_plant_a_capacity.png) +![image](figs_simple_system/simple_system_power_plant_a_capacity.png) - Select *power\_plant\_b | electricity\_node* in the *Relationship tree*. @@ -216,7 +216,7 @@ If you are not sure whether you have the latest version, please upgrade to ensur alternative, and enter the value *200* as seen in the image below. This will set the capacity for *power\_plant\_b*. -![image](../figs_simple_system/simple_system_power_plant_b_capacity.png) +![image](figs_simple_system/simple_system_power_plant_b_capacity.png) - In *Relationship tree*, select the *unit\_\_node\_\_node* class, and come back to the @@ -232,14 +232,14 @@ If you are not sure whether you have the latest version, please upgrade to ensur electricity for *power\_plant\_a* and *power\_plant\_b* to *0.7* and *0.8*, respectively. It should like the image below. -![image](../figs_simple_system/simple_system_fix_ratio_out_in_unit_flow.png) +![image](figs_simple_system/simple_system_fix_ratio_out_in_unit_flow.png) When you're ready, commit all changes to the database. ### Executing the workflow - Go back to Spine Toolbox's main window, and hit the **Execute - project** button ![image](../figs_a5/play-circle.png) from the tool bar. + project** button ![image](figs_a5/play-circle.png) from the tool bar. You should see 'Executing All Directed Acyclic Graphs' printed in the *Event log* (at the bottom left by default). @@ -261,4 +261,4 @@ When you're ready, commit all changes to the database. the bottom. - The *Pivot table* will be populated with results from the SpineOpt run. It will look something like the image below. -![image](../figs_simple_system/simple_system_results_pivot_table.png) \ No newline at end of file +![image](figs_simple_system/simple_system_results_pivot_table.png) \ No newline at end of file diff --git a/docs/src/tutorial/tutorialTwoHydro.md b/docs/src/tutorial/tutorialTwoHydro.md index c35245679b..4e62a8a636 100644 --- a/docs/src/tutorial/tutorialTwoHydro.md +++ b/docs/src/tutorial/tutorialTwoHydro.md @@ -21,15 +21,15 @@ upstream power plant follows the river route and becomes available to the downstream power plant. -![A system of two hydropower plants.](../figs_two_hydro/two_hydro.png) +![A system of two hydropower plants.](figs_two_hydro/two_hydro.png) *A system of two hydropower plants* In order to run this tutorial you must first execute some preliminary -steps from the [Simple System](../../simple_system/index.html) tutorial. +steps from the [Simple System](simple_system.md) tutorial. Specifically, execute all steps from the -[guide](../../simple_system/index.html#guide), up to and including the step of -[importing-the-spineopt-database-template](../../simple_system/index.html#importing-the-spineopt-database-template). +[guide](simple_system.md#guide), up to and including the step of +[importing-the-spineopt-database-template](simple_system.md#importing-the-spineopt-database-template). It is advisable to go through the whole tutorial in order to familiarise yourself with Spine. @@ -61,11 +61,12 @@ Toolbox). Since we are modelling a hydropower system we will have to define two commodities, water and electricity. In the Spine DB editor, locate the *Object tree*, expand the root element if -required, right click on the commodity class, and select *Add objects* from the context menu. In the *Add objects* dialogue that should pop up, enter +required, right click on the commodity class, and select *Add objects* from the context menu. +In the *Add objects* dialogue that should pop up, enter the object names for the commodities as you see in the image below and then press Ok. -![image](../figs_two_hydro/two_hydro_commodities.png) +![image](figs_two_hydro/two_hydro_commodities.png) *Defining commodities.* @@ -75,7 +76,7 @@ Follow a similar path to add nodes, right click on the node class, and select *Add objects* from the context menu. In the dialogue, enter the node names as shown: -![image](../figs_two_hydro/two_hydro_nodes.png) +![image](figs_two_hydro/two_hydro_nodes.png) *Defining nodes.* @@ -93,7 +94,7 @@ Similarly, add connections, right click on the connection class, select *Add objects* from the context menu and add the following connections: -![image](../figs_two_hydro/two_hydro_connections.png) +![image](figs_two_hydro/two_hydro_connections.png) *Defining connections.* @@ -109,7 +110,7 @@ another, you need a unit. You guessed it! Right click on the unit class, select *Add objects* from the context menu and add the following units: -![image](../figs_two_hydro/two_hydro_units.png) +![image](figs_two_hydro/two_hydro_units.png) *Defining units.* @@ -128,7 +129,7 @@ required, right click on the *node\_\_commodity* class, and select *Add relation *Add relationships* dialogue, enter the following relationships as you see in the image below and then press Ok. -![image](../figs_two_hydro/two_hydro_node_commodities.png) +![image](figs_two_hydro/two_hydro_node_commodities.png) *Introducing node\_\_commodity relationships.* @@ -137,14 +138,14 @@ following relationships as you see in the image below and then press Ok. Next step is to define the topology of flows between the nodes. To do that insert the following relationships in the *connection\_\_from\_node* class: -![image](../figs_two_hydro/two_hydro_connection_from_node.png) +![image](figs_two_hydro/two_hydro_connection_from_node.png) *Introducing connection\_\_from\_node relationships.* as well as the following the following *connection\_\_node_node* relationships as you see in the figure: -![Introducing connection__node_node relationships.](../figs_two_hydro/two_hydro_connection_node_node.png) +![Introducing connection__node_node relationships.](figs_two_hydro/two_hydro_connection_node_node.png) *Introducing connection\_\_node\_node relationships.* @@ -154,20 +155,20 @@ To define the topology of the units and be able to introduce their parameters later on, you need to define the following relationships in the *unit\_\_from\_node* class: -![Introducing unit__from_node relationships.](../figs_two_hydro/two_hydro_unit_from_node.png) +![Introducing unit__from_node relationships.](figs_two_hydro/two_hydro_unit_from_node.png) *Introducing unit\_\_from\_node relationships.* in the *unit\_\_node_node* class: -![Introducing unit__node_node relationships.](../figs_two_hydro/two_hydro_unit_node_node.png) +![Introducing unit__node_node relationships.](figs_two_hydro/two_hydro_unit_node_node.png) *Introducing unit\_\_node\_node relationships.* and in the *unit\_\_to\_node* class as you see in the following figure: -![Introducing unit__to_node relationships.](../figs_two_hydro/two_hydro_unit_to_node.png) +![Introducing unit__to_node relationships.](figs_two_hydro/two_hydro_unit_to_node.png) *Introducing unit\_\_to\_node relationships.* @@ -178,7 +179,7 @@ variables to the output database you need to specify them in the form of *report\_output* relationships. Add the following relationships to the *report\_output* class: -![Introducing report outputs with report_output relationships.](../figs_two_hydro/two_hydro_report.png) +![Introducing report outputs with report_output relationships.](figs_two_hydro/two_hydro_report.png) *Introducing report outputs with report\_output relationships.* @@ -191,7 +192,7 @@ need to introduce respective parameter values. To introduce object parameter values first select the *model* class in the Object tree and enter the following values in the *Object parameter value* pane: -![Defining model execution parameters.](../figs_two_hydro/two_hydro_model_parameters.png) +![Defining model execution parameters.](figs_two_hydro/two_hydro_model_parameters.png) *Defining model execution parameters.* @@ -223,7 +224,7 @@ this time selecting the *node* class from the *Object tree*, we need to add the following entries: -![Defining model execution parameters.](../figs_two_hydro/two_hydro_node_parameters.png) +![Defining model execution parameters.](figs_two_hydro/two_hydro_node_parameters.png) *Defining model execution parameters.* @@ -265,7 +266,7 @@ resolution we select the *temporal\_block* class in the *Object tree* and we set the *resolution* parameter value to *1h* as shown in the figure: -![Setting the temporal resolution of the model.](../figs_two_hydro/two_hydro_temporal_block.png) +![Setting the temporal resolution of the model.](figs_two_hydro/two_hydro_temporal_block.png) *Setting the temporal resolution of the model.* @@ -277,7 +278,7 @@ this we need to select the *connection\_\_node\_node* class in the Relationship tree and add the following entries in the *Relationship parameter value* pane, as shown next: -![Defining discharge and spillage ratio flows.](../figs_two_hydro/two_hydro_connection_node_node_parameters.png) +![Defining discharge and spillage ratio flows.](figs_two_hydro/two_hydro_connection_node_node_parameters.png) *Defining discharge and spillage ratio flows.* @@ -287,7 +288,7 @@ Similarly, for each one of the *unit\_\_from_node*, *unit\_\_node_node*, and *un add the the maximal water that can be discharged by each hydropower plant: -![Setting the maximal water discharge of each plant.](../figs_two_hydro/two_hydro_unit_from_node_parameters.png) +![Setting the maximal water discharge of each plant.](figs_two_hydro/two_hydro_unit_from_node_parameters.png) *Setting the maximal water discharge of each plant.* @@ -300,7 +301,7 @@ select all values, copy, and paste them, after having selected the value cell of the corresponding row. You can plot and edit the timeseries data by double clicking on the same cell afterwards: -![Previewing and editing the electricity prices timeseries.](../figs_two_hydro/two_hydro_vom_cost.png) +![Previewing and editing the electricity prices timeseries.](figs_two_hydro/two_hydro_vom_cost.png) *Previewing and editing the electricity prices timeseries.* @@ -310,19 +311,19 @@ ratios between the nodes. Assuming that water is not "lost" from the discharged water with a given efficiency we define the following parameter values for each hydropower plant, in the *unit\_\_node_node* class: -![Defining conversion efficiencies.](../figs_two_hydro/two_hydro_unit_node_node_parameters.png) +![Defining conversion efficiencies.](figs_two_hydro/two_hydro_unit_node_node_parameters.png) *Defining conversion efficiencies.* Lastly, we can define the maximal electricity production of each plant by inserting the following *unit\_\_to\_node* relationship parameter values: -![Setting the maximal electricity production of each plant.](../figs_two_hydro/two_hydro_unit_to_node_parameters.png) +![Setting the maximal electricity production of each plant.](figs_two_hydro/two_hydro_unit_to_node_parameters.png) *Setting the maximal electricity production of each plant.* Hooray! You can now commit the database, close the Spine DB Editor and -run your model! Go to the main Spine window and click on Execute ![image](../figs_a5/play-circle.png). +run your model! Go to the main Spine window and click on Execute ![image](figs_a5/play-circle.png). ### Examining the results @@ -339,7 +340,7 @@ examine closer and retrieve the data, as shown in the next figure. The *unit\_flow* variable of the *electricity\_load* unit represents the total electricity production in the system: -![Total electricity produced in the system.](../figs_two_hydro/two_hydro_results_electricity.png) +![Total electricity produced in the system.](figs_two_hydro/two_hydro_results_electricity.png) *Total electricity produced in the system.* @@ -347,7 +348,7 @@ Now, take to a minute to reflect on how you could retrieve the data representing the water that is discharged by each hydropower plant as shown in the next figure: -![Water discharge of SprÃ¥nget hydropower plant.](../figs_two_hydro/two_hydro_results_discharge.png) +![Water discharge of SprÃ¥nget hydropower plant.](figs_two_hydro/two_hydro_results_discharge.png) *Water discharge of SprÃ¥nget hydropower plant.* @@ -406,20 +407,20 @@ to the downstream plant and this should be taken into account. To model the value of stored water we need to make some additions and modifications to the initial model. -- First, add a new node (see [adding nodes](../index.html#Nodes)) and give it a +- First, add a new node (see [adding nodes](../index.md#Nodes)) and give it a name (e.g., *stored\_water*). This node will accumulate the water stored in the reservoirs at the end of the planning horizon. Associate the node with the water - commodity (see [node__commodity](../index.html#Assinging-commodities-to-nodes)). + commodity (see [node__commodity](../index.md#Assinging-commodities-to-nodes)). -- Add three more units (see [adding units](../index.html#Units)); two will +- Add three more units (see [adding units](../index.md#Units)); two will transfer the water at the end of the planning horizon in the new node that we just added (e.g., *SprÃ¥nget\_stored\_water*, *Fallet\_stored\_water*), and one will be used as a *sink* introducing the value of stored water in the objective function (e.g., *value\_stored\_water*). - To establish the topology of the new units and nodes (see - [adding unit relationships](../index.html#Placing-the-units-in-the-model)): + [adding unit relationships](../index.md#Placing-the-units-in-the-model)): - add one *unit\_\_from_node* relationship, between the *value\_stored\_water* unit from the *stored\_water* node, another one between the *SprÃ¥nget\_stored\_water* unit from @@ -452,7 +453,7 @@ modifications to the initial model. and the *electricity\_load* and set 0 as the price of electricity for the last hour *2021-01-02T00:00:00*. The price is set to zero to ensure no electricity is sold during this hour. - ![Modify the fix_node_state parameter value of SprÃ¥nget_upper and Fallet_upper nodes.](../figs_two_hydro/two_hydro_fix_node_state.png) + ![Modify the fix_node_state parameter value of SprÃ¥nget_upper and Fallet_upper nodes.](figs_two_hydro/two_hydro_fix_node_state.png) *Modify the fix\_node\_state parameter value of SprÃ¥nget\_upper and Fallet\_upper nodes.* - Finally, we need to add some relationship parameter values for the new units: @@ -466,7 +467,7 @@ modifications to the initial model. imposed a zero cost for all the optimisation horizon, while we use an assumed future electricity value for the additional time step at the end of the horizon. - ![Adding vom_cost parameter value on the value_stored_water unit.](../figs_two_hydro/two_hydro_max_stored_water_unit_values.png) + ![Adding vom_cost parameter value on the value_stored_water unit.](figs_two_hydro/two_hydro_max_stored_water_unit_values.png) *Adding vom\_cost parameter value on the value\_stored\_water unit.* - Add two *fix\_ratio\_out\_in\_unit\_flow* parameter values as you see in the figure bellow. The efficiency of @@ -477,11 +478,11 @@ modifications to the initial model. the water from SprÃ¥nget's reservoir will be used both by Fallet and SprÃ¥nget plant, therefore we use the sum of the two efficiencies in the parameter value of *SprÃ¥nget\_stored\_water*. - ![Adding fix_ratio_out_in_unit_flow parameter values on the SprÃ¥nget_stored_water and Fallet_stored_water units.](../figs_two_hydro/two_hydro_max_stored_water_unit_node_node.png) + ![Adding fix_ratio_out_in_unit_flow parameter values on the SprÃ¥nget_stored_water and Fallet_stored_water units.](figs_two_hydro/two_hydro_max_stored_water_unit_node_node.png) *Adding fix\_ratio\_out\_in\_unit\_flow parameter values on the SprÃ¥nget\_stored\_water and Fallet\_stored\_water units.* You can now commit your changes in the database, execute the project and -[examine the results](../index.html#Examining-the-results)! As an exercise, try to retrieve +[examine the results](../index.md#Examining-the-results)! As an exercise, try to retrieve the value of stored water as it is calculated by the model. ## Spillage Constraints - Minimisation of Spilt Water @@ -493,7 +494,7 @@ level. At the same time, to avoid wasting water that could be used for producing electricity, we could explicitly impose the spillage minimisation to be added in the objective function. -- Add one unit (see [adding units](../index.html#Units)) to impose the spillage +- Add one unit (see [adding units](../index.md#Units)) to impose the spillage constraints to each plant and name it (for example *SprÃ¥nget\_spill*). - Remove the *SprÃ¥nget\_to\_Fallet\_spill* @@ -502,7 +503,7 @@ minimisation to be added in the objective function. **Remove**). - To establish the topology of the unit (see - [adding unit relationships](../index.html#Placing-the-units-in-the-model)): + [adding unit relationships](../index.md#Placing-the-units-in-the-model)): - Add a *unit\_\_from_node* relationship, between the *SprÃ¥nget\_spill* unit from the *SprÃ¥nget\_upper* node, - add a *unit\_\_node\_\_node* @@ -516,7 +517,7 @@ minimisation to be added in the objective function. percentage of the *unit\_capacity*) to impose a minimum, and the *vom\_cost* to penalise the water that is spilt: - ![Setting minimum (the minimal value is defined as percentage of capacity), maximum, and spillage penalty.](../figs_two_hydro/two_hydro_min_spill_unit_node_node.png) + ![Setting minimum (the minimal value is defined as percentage of capacity), maximum, and spillage penalty.](figs_two_hydro/two_hydro_min_spill_unit_node_node.png) *Setting minimum (the minimal value is defined as percentage of capacity), maximum, and spillage penalty.* @@ -524,10 +525,10 @@ minimisation to be added in the objective function. define the *fix\_ratio\_out\_in\_unit\_flow* parameter value of the *min\_spillage|Fallet\_upper|SprÃ¥nget\_upper* relationship to **1** (see - [adding unit relationships](../index.html#Placing-the-units-in-the-model)). + [adding unit relationships](../index.md#Placing-the-units-in-the-model)). Commit your changes in the database, execute the project and -[examine the results](../index.html#Examining-the-results)! As an exercise, you can perform +[examine the results](../index.md#Examining-the-results)! As an exercise, you can perform this process for and Fallet plant (you would also need to add another water node, downstream of Fallet). @@ -541,10 +542,10 @@ to do is set a demand in the form of a timeseries to the *electricity\_node*. timeseries](https://raw.githubusercontent.com/spine-tools/Spine-Toolbox/master/docs/source/data/contracted_load.txt), to the *demand* parameter value of the *electricity\_node* (see - [adding node parameter values](../index.html#Defining-node-parameter-values)). + [adding node parameter values](../index.md#Defining-node-parameter-values)). Commit your changes in the database, execute the project and -[examine the results](../index.html#Examining-the-results)! +[examine the results](../index.md#Examining-the-results)! This concludes the tutorial, we hope that you enjoyed building hydropower systems in Spine as much as we do! From 3909a784814c2220d7dde9d85e5fb53be209573b Mon Sep 17 00:00:00 2001 From: Tasqu Date: Thu, 28 Sep 2023 10:12:44 +0300 Subject: [PATCH 17/33] .gitignore Manifests --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 7c0c99014a..7391dda00e 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ docs/src/concept_reference/relationship_classes.md docs/src/concept_reference/Object Classes.md docs/src/concept_reference/Parameter Value Lists.md docs/src/concept_reference/Relationship Classes.md +test/Manifest.toml +Manifest.toml From 765d1d15df0390fe803b58c4fc4a565a724fa20d Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 28 Sep 2023 09:22:57 +0200 Subject: [PATCH 18/33] Increment HTML size threshold --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 621dd564de..8f1f7baaf2 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -73,7 +73,7 @@ SpineOpt.populate_empty_chapters!(pages, joinpath(path, "src")) # Create and deploy the documentation makedocs( sitename="SpineOpt.jl", - format=Documenter.HTML(prettyurls=get(ENV, "CI", nothing) == "true"), # uncomment to deploy locally + format=Documenter.HTML(prettyurls=get(ENV, "CI", nothing) == "true", size_threshold=409600), # uncomment to deploy locally pages=pages, warnonly=true ) From 72b557ee3daec988e33436053394a236fa9bcb5c Mon Sep 17 00:00:00 2001 From: Tasqu Date: Thu, 28 Sep 2023 10:24:45 +0300 Subject: [PATCH 19/33] Bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index bcf30e8527..f239c30961 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SpineOpt" uuid = "0d8fc150-4032-4b6e-9540-20efcb304861" authors = ["Spine Project consortium "] -version = "0.6.15" +version = "0.6.16" [deps] Arrow = "69666777-d1a9-59fb-9406-91d4454c9d45" From 21aad84c2bbd39d8a7055701c43f44f2e786e960 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 28 Sep 2023 14:27:03 +0200 Subject: [PATCH 20/33] Introduce equal_investments and min_max_entities_invested_available Re #760 --- src/SpineOpt.jl | 3 +- ...tment_group_entities_invested_available.jl | 103 ++++++++++ ...int_investment_group_equal_investments.jl} | 52 +++-- .../constraint_unit_flow_op_bounds.jl | 3 +- src/run_spineopt_benders.jl | 4 +- src/run_spineopt_standard.jl | 4 +- ...variable_connections_invested_available.jl | 4 +- .../variable_storages_invested_available.jl | 4 +- .../variable_units_invested_available.jl | 3 +- templates/spineopt_template.json | 3 + .../constraint_investment_group.jl | 192 ++++++++++++++++++ test/runtests.jl | 1 + 12 files changed, 347 insertions(+), 29 deletions(-) create mode 100644 src/constraints/constraint_investment_group_entities_invested_available.jl rename src/constraints/{constraint_entity_investment_group.jl => constraint_investment_group_equal_investments.jl} (68%) create mode 100644 test/constraints/constraint_investment_group.jl diff --git a/src/SpineOpt.jl b/src/SpineOpt.jl index d5cb48b361..6c5274da33 100644 --- a/src/SpineOpt.jl +++ b/src/SpineOpt.jl @@ -187,7 +187,8 @@ include("constraints/constraint_node_voltage_angle.jl") include("constraints/constraint_connection_unitary_gas_flow.jl") include("constraints/constraint_mp_any_invested_cuts.jl") include("constraints/constraint_mp_min_res_gen_to_demand_ratio.jl") -include("constraints/constraint_entity_investment_group.jl") +include("constraints/constraint_investment_group_equal_investments.jl") +include("constraints/constraint_investment_group_entities_invested_available.jl") export unit_flow_indices diff --git a/src/constraints/constraint_investment_group_entities_invested_available.jl b/src/constraints/constraint_investment_group_entities_invested_available.jl new file mode 100644 index 0000000000..6749519e2b --- /dev/null +++ b/src/constraints/constraint_investment_group_entities_invested_available.jl @@ -0,0 +1,103 @@ +############################################################################# +# Copyright (C) 2017 - 2023 Spine Project +# +# This file is part of SpineOpt. +# +# Spine Model is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Spine Model is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +############################################################################# + +""" + add_constraint_investment_group_minimum_entities_invested_available!(m::Model) + +Force number of entities invested available in a group to be greater than the minimum. +""" +function add_constraint_investment_group_minimum_entities_invested_available!(m::Model) + t0 = _analysis_time(m) + m.ext[:spineopt].constraints[:investment_group_minimum_entities_invested_available] = Dict( + (investment_group=ig, stochastic_scenario=s, t=t) => @constraint( + m, + _group_entities_invested_available(m, ig, s, t) + >= + minimum_entities_invested_available[(investment_group=ig, stochastic_scenario=s, analysis_time=t0, t=t)] + ) + for ig in indices(minimum_entities_invested_available) + for (s, t) in _entities_invested_available_s_t(m) + ) +end + +""" + add_constraint_investment_group_maximum_entities_invested_available!(m::Model) + +Force number of entities invested available in a group to be lower than the maximum. +""" +function add_constraint_investment_group_maximum_entities_invested_available!(m::Model) + t0 = _analysis_time(m) + m.ext[:spineopt].constraints[:investment_group_maximum_entities_invested_available] = Dict( + (investment_group=ig, stochastic_scenario=s, t=t) => @constraint( + m, + _group_entities_invested_available(m, ig, s, t) + <= + maximum_entities_invested_available[(investment_group=ig, stochastic_scenario=s, analysis_time=t0, t=t)] + ) + for ig in indices(maximum_entities_invested_available) + for (s, t) in _entities_invested_available_s_t(m) + ) +end + +function _entities_invested_available_s_t(m) + [ + (stochastic_scenario=s, t=t) + for (t, path) in t_lowest_resolution_path( + m, + vcat( + units_invested_available_indices(m), + connections_invested_available_indices(m), + storages_invested_available_indices(m) + ) + ) + for s in path + ] +end + +function _group_entities_invested_available(m, ig, s, t) + @fetch ( + units_invested_available, connections_invested_available, storages_invested_available + ) = m.ext[:spineopt].variables + ( + + expr_sum( + units_invested_available[u, s, t] + for (u, s, t) in units_invested_available_indices( + m; unit=unit__investment_group(investment_group=ig), stochastic_scenario=s, t=t_in_t(m; t_long=t) + ); + init=0 + ) + + expr_sum( + connections_invested_available[conn, s, t] + for (conn, s, t) in connections_invested_available_indices( + m; + connection=connection__investment_group(investment_group=ig), + stochastic_scenario=s, + t=t_in_t(m; t_long=t) + ); + init=0 + ) + + expr_sum( + storages_invested_available[n, s, t] + for (n, s, t) in storages_invested_available_indices( + m; node=node__investment_group(investment_group=ig), stochastic_scenario=s, t=t_in_t(m; t_long=t) + ); + init=0 + ) + ) +end \ No newline at end of file diff --git a/src/constraints/constraint_entity_investment_group.jl b/src/constraints/constraint_investment_group_equal_investments.jl similarity index 68% rename from src/constraints/constraint_entity_investment_group.jl rename to src/constraints/constraint_investment_group_equal_investments.jl index 67b90f06f1..66d9229395 100644 --- a/src/constraints/constraint_entity_investment_group.jl +++ b/src/constraints/constraint_investment_group_equal_investments.jl @@ -18,70 +18,78 @@ ############################################################################# """ - add_constraint_entity_investment_group!(m::Model) + add_constraint_investment_group_equal_investments!(m::Model) Force investment variables for first entity in the group and all other entities in the group to be equal. """ -function add_constraint_entity_investment_group!(m::Model) +function add_constraint_investment_group_equal_investments!(m::Model) @fetch ( units_invested_available, connections_invested_available, storages_invested_available ) = m.ext[:spineopt].variables - m.ext[:spineopt].constraints[:entity_investment_group] = Dict( + + m.ext[:spineopt].constraints[:investment_group_equal_investments] = Dict( (investment_group=ig, entity1=e, entity2=other_e, stochastic_scenario=s, t=t) => @constraint( m, + expr_sum( units_invested_available[e, s, t] - for (e, s, t) in units_invested_available_indices(m; unit=e, stochastic_scenario=s, t=t); + for (e, s, t) in units_invested_available_indices( + m; unit=e, stochastic_scenario=s, t=t_in_t(m; t_long=t) + ); init=0 ) + expr_sum( connections_invested_available[e, s, t] for (e, s, t) in connections_invested_available_indices( - m; connection=e, stochastic_scenario=s, t=t + m; connection=e, stochastic_scenario=s, t=t_in_t(m; t_long=t) ); init=0 ) + expr_sum( storages_invested_available[e, s, t] - for (e, s, t) in storages_invested_available_indices(m; node=e, stochastic_scenario=s, t=t); + for (e, s, t) in storages_invested_available_indices( + m; node=e, stochastic_scenario=s, t=t_in_t(m; t_long=t) + ); init=0 ) == + expr_sum( units_invested_available[other_e, s, t] - for (other_e, s, t) in units_invested_available_indices(m; unit=other_e, stochastic_scenario=s, t=t); + for (other_e, s, t) in units_invested_available_indices( + m; unit=other_e, stochastic_scenario=s, t=t_in_t(m; t_long=t) + ); init=0 ) + expr_sum( connections_invested_available[other_e, s, t] for (other_e, s, t) in connections_invested_available_indices( - m; connection=other_e, stochastic_scenario=s, t=t + m; connection=other_e, stochastic_scenario=s, t=t_in_t(m; t_long=t) ); init=0 ) + expr_sum( storages_invested_available[other_e, s, t] - for (other_e, s, t) in storages_invested_available_indices(m; node=other_e, stochastic_scenario=s, t=t); + for (other_e, s, t) in storages_invested_available_indices( + m; node=other_e, stochastic_scenario=s, t=t_in_t(m; t_long=t) + ); init=0 ) ) - for ig in investment_group() + for ig in investment_group(equal_investments=true) for e in _first_entity_investment_group(ig) - for (e, s, t) in vcat( - units_invested_available_indices(m; unit=e), - connections_invested_available_indices(m; connection=e), - storages_invested_available_indices(m; node=e) - ) - for other_e in setdiff(_all_entities_investment_group(ig), e) - for (other_e, s, t) in vcat( - units_invested_available_indices(m; unit=other_e, stochastic_scenario=s, t=t), - connections_invested_available_indices(m; connection=other_e, stochastic_scenario=s, t=t), - storages_invested_available_indices(m; node=other_e, stochastic_scenario=s, t=t), + for other_e in setdiff(entity_investment_group(ig), e) + for (t, path) in t_lowest_resolution_path( + m, + vcat( + units_invested_available_indices(m; unit=[e, other_e]), + connections_invested_available_indices(m; connection=[e, other_e]), + storages_invested_available_indices(m; node=[e, other_e]) + ) ) + for s in path ) end -function _all_entities_investment_group(ig) +function entity_investment_group(ig) vcat( unit__investment_group(investment_group=ig), connection__investment_group(investment_group=ig), @@ -90,6 +98,6 @@ function _all_entities_investment_group(ig) end function _first_entity_investment_group(ig) - entities = _all_entities_investment_group(ig) + entities = entity_investment_group(ig) isempty(entities) ? () : first(entities) end \ No newline at end of file diff --git a/src/constraints/constraint_unit_flow_op_bounds.jl b/src/constraints/constraint_unit_flow_op_bounds.jl index 92c546146c..371355a7ab 100644 --- a/src/constraints/constraint_unit_flow_op_bounds.jl +++ b/src/constraints/constraint_unit_flow_op_bounds.jl @@ -46,7 +46,8 @@ function add_constraint_unit_flow_op_bounds!(m::Model) * unit_availability_factor[(unit=u, stochastic_scenario=s, analysis_time=t0, t=t)] * unit_capacity[(unit=u, node=n, direction=d, stochastic_scenario=s, analysis_time=t0, t=t)] * unit_conv_cap_to_flow[(unit=u, node=n, direction=d, stochastic_scenario=s, analysis_time=t0, t=t)] - ) for (u, n, d) in indices(unit_capacity) + ) + for (u, n, d) in indices(unit_capacity) for (u, n, d, op, s, t) in unit_flow_op_indices(m; unit=u, node=n, direction=d) ) end diff --git a/src/run_spineopt_benders.jl b/src/run_spineopt_benders.jl index b834de4b18..0d5dc1adde 100644 --- a/src/run_spineopt_benders.jl +++ b/src/run_spineopt_benders.jl @@ -160,7 +160,9 @@ function _add_mp_constraints!(m; log_level=3) add_constraint_storage_lifetime!, add_constraint_storages_invested_transition!, add_constraint_storages_invested_available!, - add_constraint_entity_investment_group!, + add_constraint_investment_group_equal_investments!, + add_constraint_investment_group_minimum_entities_invested_available!, + add_constraint_investment_group_maximum_entities_invested_available!, ) name = name_from_fn(add_constraint!) @timelog log_level 3 "- [$name]" add_constraint!(m) diff --git a/src/run_spineopt_standard.jl b/src/run_spineopt_standard.jl index 05808a5da6..a8c53248d2 100644 --- a/src/run_spineopt_standard.jl +++ b/src/run_spineopt_standard.jl @@ -209,7 +209,9 @@ function _add_constraints!(m; add_constraints=m -> nothing, log_level=3) add_constraint_node_voltage_angle!, add_constraint_max_node_voltage_angle!, add_constraint_min_node_voltage_angle!, - add_constraint_entity_investment_group!, + add_constraint_investment_group_equal_investments!, + add_constraint_investment_group_minimum_entities_invested_available!, + add_constraint_investment_group_maximum_entities_invested_available!, ) name = name_from_fn(add_constraint!) @timelog log_level 3 "- [$name]" add_constraint!(m) diff --git a/src/variables/variable_connections_invested_available.jl b/src/variables/variable_connections_invested_available.jl index 8f99b78c36..a8e030156a 100644 --- a/src/variables/variable_connections_invested_available.jl +++ b/src/variables/variable_connections_invested_available.jl @@ -34,7 +34,9 @@ function connections_invested_available_indices( unique( (connection=conn, stochastic_scenario=s, t=t) for (conn, tb) in connection__investment_temporal_block( - connection=connection, temporal_block=temporal_block, _compact=false + connection=intersect(indices(candidate_connections), connection), + temporal_block=temporal_block, + _compact=false ) for (conn, s, t) in connection_investment_stochastic_time_indices( m; connection=conn, stochastic_scenario=stochastic_scenario, temporal_block=tb, t=t diff --git a/src/variables/variable_storages_invested_available.jl b/src/variables/variable_storages_invested_available.jl index 812507cef6..6fd3b9befb 100644 --- a/src/variables/variable_storages_invested_available.jl +++ b/src/variables/variable_storages_invested_available.jl @@ -33,7 +33,9 @@ function storages_invested_available_indices( node=members(node) unique( (node=n, stochastic_scenario=s, t=t) - for (n, tb) in node__investment_temporal_block(node=node, temporal_block=temporal_block, _compact=false) + for (n, tb) in node__investment_temporal_block( + node=intersect(indices(candidate_storages), node), temporal_block=temporal_block, _compact=false + ) for (n, s, t) in node_investment_stochastic_time_indices( m; node=n, stochastic_scenario=stochastic_scenario, temporal_block=tb, t=t ) diff --git a/src/variables/variable_units_invested_available.jl b/src/variables/variable_units_invested_available.jl index d43384893b..51fa87b04c 100644 --- a/src/variables/variable_units_invested_available.jl +++ b/src/variables/variable_units_invested_available.jl @@ -33,7 +33,8 @@ function units_invested_available_indices( unit = members(unit) unique( (unit=u, stochastic_scenario=s, t=t) - for (u, tb) in unit__investment_temporal_block(unit=unit, temporal_block=temporal_block, _compact=false) + for (u, tb) in unit__investment_temporal_block( + unit=intersect(indices(candidate_units), unit), temporal_block=temporal_block, _compact=false) for (u, s, t) in unit_investment_stochastic_time_indices( m; unit=u, stochastic_scenario=stochastic_scenario, temporal_block=tb, t=t ) diff --git a/templates/spineopt_template.json b/templates/spineopt_template.json index 34058de2b1..17a158474b 100644 --- a/templates/spineopt_template.json +++ b/templates/spineopt_template.json @@ -157,6 +157,9 @@ ["connection", "connections_invested_big_m_mga", null, null, "big_m_mga should be chosen as small as possible but sufficiently large. For units_invested_mga an appropriate big_m_mga would be twice the candidate connections."], ["connection", "connections_invested_mga", false, "boolean_value_list", "Defines whether a certain variable (here: connections_invested) will be considered in the maximal-differences of the mga objective"], ["connection", "connections_invested_mga_weight", 1, null, "Used to scale mga variables. For weightd sum mga method, the length of this weight given as an Array will determine the number of iterations."], + ["investment_group", "equal_investments", false, "boolean_value_list", "Whether all entities in the group must have the same investment decision."], + ["investment_group", "minimum_entities_invested_available", null, null, "Lower bound on the number of entities invested available in the group at any point in time."], + ["investment_group", "maximum_entities_invested_available", null, null, "Upper bound on the number of entities invested available in the group at any point in time."], ["model", "duration_unit", "hour", "duration_unit_list", "Defines the base temporal unit of the `model`. Currently supported values are either an `hour` or a `minute`."], ["model", "is_active", true, "boolean_value_list", "If false, the object is excluded from the model if the tool filter object activity control is specified"], ["model", "max_gap", 0.05, null, "Specifies the maximum optimality gap for the model. Currently only used for the master problem within a decomposed structure"], diff --git a/test/constraints/constraint_investment_group.jl b/test/constraints/constraint_investment_group.jl new file mode 100644 index 0000000000..637fbf0d55 --- /dev/null +++ b/test/constraints/constraint_investment_group.jl @@ -0,0 +1,192 @@ + +############################################################################# +# Copyright (C) 2017 - 2018 Spine Project +# +# This file is part of SpineOpt. +# +# SpineOpt is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SpineOpt is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +############################################################################# + +function _test_constraint_investment_group_setup() + url_in = "sqlite://" + test_data = Dict( + :objects => [ + ["model", "instance"], + ["temporal_block", "investments_two_hourly"], + ["temporal_block", "investments_four_hourly"], + ["stochastic_structure", "investments_deterministic"], + ["stochastic_structure", "investments_stochastic"], + ["stochastic_scenario", "parent"], + ["stochastic_scenario", "child"], + ["node", "node_a"], + ["node", "node_b"], + ["node", "node_c"], + ["unit", "unit_ab"], + ["connection", "connection_bc"], + ["investment_group", "ig"], + ], + :relationships => [ + ["model__temporal_block", ["instance", "investments_two_hourly"]], + ["model__temporal_block", ["instance", "investments_four_hourly"]], + ["model__default_temporal_block", ["instance", "investments_four_hourly"]], + ["model__stochastic_structure", ["instance", "investments_deterministic"]], + ["model__stochastic_structure", ["instance", "investments_stochastic"]], + ["model__default_stochastic_structure", ["instance", "investments_stochastic"]], + ["stochastic_structure__stochastic_scenario", ["investments_deterministic", "parent"]], + ["stochastic_structure__stochastic_scenario", ["investments_stochastic", "parent"]], + ["stochastic_structure__stochastic_scenario", ["investments_stochastic", "child"]], + ["parent_stochastic_scenario__child_stochastic_scenario", ["parent", "child"]], + ["node__investment_temporal_block", ["node_a", "investments_two_hourly"]], + ["node__investment_temporal_block", ["node_b", "investments_four_hourly"]], + ["node__investment_temporal_block", ["node_c", "investments_two_hourly"]], + ["node__investment_stochastic_structure", ["node_a", "investments_stochastic"]], + ["node__investment_stochastic_structure", ["node_b", "investments_deterministic"]], + ["node__investment_stochastic_structure", ["node_c", "investments_deterministic"]], + ["unit__investment_temporal_block", ["unit_ab", "investments_four_hourly"]], + ["unit__investment_stochastic_structure", ["unit_ab", "investments_deterministic"]], + ["connection__investment_temporal_block", ["connection_bc", "investments_four_hourly"]], + ["connection__investment_stochastic_structure", ["connection_bc", "investments_deterministic"]], + ["unit__from_node", ["unit_ab", "node_a"]], + ["unit__to_node", ["unit_ab", "node_b"]], + ["connection__from_node", ["connection_bc", "node_b"]], + ["connection__to_node", ["connection_bc", "node_c"]], + ["unit__investment_group", ["unit_ab", "ig"]], + ["connection__investment_group", ["connection_bc", "ig"]], + ["node__investment_group", ["node_c", "ig"]], + ], + :object_parameter_values => [ + ["model", "instance", "model_start", Dict("type" => "date_time", "data" => "2000-01-01T00:00:00")], + ["model", "instance", "model_end", Dict("type" => "date_time", "data" => "2000-01-01T04:00:00")], + ["model", "instance", "duration_unit", "hour"], + ["model", "instance", "model_type", "spineopt_standard"], + ["node", "node_c", "has_state", true], + ["node", "node_c", "node_state_cap", 100], + ["node", "node_c", "candidate_storages", 2], + ["node", "node_c", "storage_investment_cost", 1000], + ["unit", "unit_ab", "candidate_units", 3], + ["unit", "unit_ab", "unit_investment_cost", 1000], + ["connection", "connection_bc", "candidate_connections", 1], + ["connection", "connection_bc", "connection_investment_cost", 1000], + ["temporal_block", "investments_two_hourly", "resolution", Dict("type" => "duration", "data" => "2h")], + ["temporal_block", "investments_four_hourly", "resolution", Dict("type" => "duration", "data" => "4h")], + ["model", "instance", "db_mip_solver", "HiGHS.jl"], + ["model", "instance", "db_lp_solver", "HiGHS.jl"], + ], + :relationship_parameter_values => [ + [ + "stochastic_structure__stochastic_scenario", + ["stochastic", "parent"], + "stochastic_scenario_end", + Dict("type" => "duration", "data" => "1h"), + ] + ], + ) + _load_test_data(url_in, test_data) + url_in +end + +function _test_equal_investments() + @testset "equal_investments" begin + url_in = _test_constraint_investment_group_setup() + unit_availability_factor = 0.5 + object_parameter_values = [ + ["investment_group", "ig", "equal_investments", true], + ] + SpineInterface.import_data(url_in; object_parameter_values=object_parameter_values) + m = run_spineopt(url_in; log_level=0, optimize=true) + constraint = m.ext[:spineopt].constraints[:investment_group_equal_investments] + unit_ab = unit(:unit_ab) + connection_bc = connection(:connection_bc) + node_c = node(:node_c) + parent = stochastic_scenario(:parent) + t4h = first(time_slice(m; temporal_block=temporal_block(:investments_four_hourly))) + key_head = (investment_group=investment_group(:ig), entity1=unit_ab) + key_tail = (stochastic_scenario=parent, t=t4h) + u_ab_inv_avail = m.ext[:spineopt].variables[:units_invested_available][unit_ab, parent, t4h] + conn_bc_inv_avail = [m.ext[:spineopt].variables[:connections_invested_available][connection_bc, parent, t4h]] + node_c_inv_avail = [ + m.ext[:spineopt].variables[:storages_invested_available][node_c, parent, t] + for t in time_slice(m; temporal_block=temporal_block(:investments_two_hourly)) + ] + @testset for entity2 in (connection_bc, node_c) + con_key = (; key_head..., entity2=entity2, key_tail...) + observed_con = constraint_object(constraint[con_key]) + other_inv_avail = Dict(connection_bc => conn_bc_inv_avail, node_c => node_c_inv_avail)[entity2] + expected_con = @build_constraint(u_ab_inv_avail == sum(other_inv_avail)) + @test _is_constraint_equal(observed_con, expected_con) + end + end +end + +function _test_minimum_entities_invested_available() + @testset "minimum_entities_invested_available" begin + url_in = _test_constraint_investment_group_setup() + unit_availability_factor = 0.5 + object_parameter_values = [ + ["investment_group", "ig", "minimum_entities_invested_available", 3], + ] + SpineInterface.import_data(url_in; object_parameter_values=object_parameter_values) + m = run_spineopt(url_in; log_level=0, optimize=true) + constraint = m.ext[:spineopt].constraints[:investment_group_minimum_entities_invested_available] + unit_ab = unit(:unit_ab) + connection_bc = connection(:connection_bc) + node_c = node(:node_c) + parent = stochastic_scenario(:parent) + t4h = first(time_slice(m; temporal_block=temporal_block(:investments_four_hourly))) + con_key = (investment_group=investment_group(:ig), stochastic_scenario=parent, t=t4h) + u_ab_inv_avail = m.ext[:spineopt].variables[:units_invested_available][unit_ab, parent, t4h] + conn_bc_inv_avail = m.ext[:spineopt].variables[:connections_invested_available][connection_bc, parent, t4h] + node_c_inv_avail = [ + m.ext[:spineopt].variables[:storages_invested_available][node_c, parent, t] + for t in time_slice(m; temporal_block=temporal_block(:investments_two_hourly)) + ] + observed_con = constraint_object(constraint[con_key]) + expected_con = @build_constraint(u_ab_inv_avail + conn_bc_inv_avail + sum(node_c_inv_avail) >= 3) + @test _is_constraint_equal(observed_con, expected_con) + end +end + +function _test_maximum_entities_invested_available() + @testset "maximum_entities_invested_available" begin + url_in = _test_constraint_investment_group_setup() + unit_availability_factor = 0.5 + object_parameter_values = [ + ["investment_group", "ig", "maximum_entities_invested_available", 8], + ] + SpineInterface.import_data(url_in; object_parameter_values=object_parameter_values) + m = run_spineopt(url_in; log_level=0, optimize=true) + constraint = m.ext[:spineopt].constraints[:investment_group_maximum_entities_invested_available] + unit_ab = unit(:unit_ab) + connection_bc = connection(:connection_bc) + node_c = node(:node_c) + parent = stochastic_scenario(:parent) + t4h = first(time_slice(m; temporal_block=temporal_block(:investments_four_hourly))) + con_key = (investment_group=investment_group(:ig), stochastic_scenario=parent, t=t4h) + u_ab_inv_avail = m.ext[:spineopt].variables[:units_invested_available][unit_ab, parent, t4h] + conn_bc_inv_avail = m.ext[:spineopt].variables[:connections_invested_available][connection_bc, parent, t4h] + node_c_inv_avail = [ + m.ext[:spineopt].variables[:storages_invested_available][node_c, parent, t] + for t in time_slice(m; temporal_block=temporal_block(:investments_two_hourly)) + ] + observed_con = constraint_object(constraint[con_key]) + expected_con = @build_constraint(u_ab_inv_avail + conn_bc_inv_avail + sum(node_c_inv_avail) <= 8) + @test _is_constraint_equal(observed_con, expected_con) + end +end + +@testset "investment_group" begin + # _test_equal_investments() + _test_minimum_entities_invested_available() + _test_maximum_entities_invested_available() +end diff --git a/test/runtests.jl b/test/runtests.jl index b79607ba54..4b1f29d38f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -105,6 +105,7 @@ end include("constraints/constraint_node.jl") include("constraints/constraint_connection.jl") include("constraints/constraint_user_constraint.jl") + include("constraints/constraint_investment_group.jl") include("objective/objective.jl") include("util/misc.jl") include("util/docs_utils.jl") From 730639d2ef60743ce0965de9b6c493d582fbd881 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 28 Sep 2023 15:51:50 +0200 Subject: [PATCH 21/33] Implement min_max_capacity_invested_available for investment groups Re #760 --- Project.toml | 2 +- src/SpineOpt.jl | 1 + ...tment_group_capacity_invested_available.jl | 124 ++++++++++++++++++ src/run_spineopt_benders.jl | 2 + src/run_spineopt_standard.jl | 2 + templates/spineopt_template.json | 12 +- .../constraint_investment_group.jl | 72 ++++++---- 7 files changed, 184 insertions(+), 31 deletions(-) create mode 100644 src/constraints/constraint_investment_group_capacity_invested_available.jl diff --git a/Project.toml b/Project.toml index f239c30961..47cc489a1c 100644 --- a/Project.toml +++ b/Project.toml @@ -17,5 +17,5 @@ Requires = "ae029012-a4dd-5104-9daa-d747884805df" SpineInterface = "0cda1612-498a-11e9-3c92-77fa82595a4f" [compat] -SpineInterface = "0.11.6" +SpineInterface = "0.11.9" julia = "^1.2" diff --git a/src/SpineOpt.jl b/src/SpineOpt.jl index 6c5274da33..2b9882f8e7 100644 --- a/src/SpineOpt.jl +++ b/src/SpineOpt.jl @@ -189,6 +189,7 @@ include("constraints/constraint_mp_any_invested_cuts.jl") include("constraints/constraint_mp_min_res_gen_to_demand_ratio.jl") include("constraints/constraint_investment_group_equal_investments.jl") include("constraints/constraint_investment_group_entities_invested_available.jl") +include("constraints/constraint_investment_group_capacity_invested_available.jl") export unit_flow_indices diff --git a/src/constraints/constraint_investment_group_capacity_invested_available.jl b/src/constraints/constraint_investment_group_capacity_invested_available.jl new file mode 100644 index 0000000000..076cbff535 --- /dev/null +++ b/src/constraints/constraint_investment_group_capacity_invested_available.jl @@ -0,0 +1,124 @@ +############################################################################# +# Copyright (C) 2017 - 2023 Spine Project +# +# This file is part of SpineOpt. +# +# Spine Model is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Spine Model is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +############################################################################# + +""" + add_constraint_investment_group_minimum_capacity_invested_available!(m::Model) + +Force capacity invested available in a group to be greater than the minimum. +""" +function add_constraint_investment_group_minimum_capacity_invested_available!(m::Model) + t0 = _analysis_time(m) + m.ext[:spineopt].constraints[:investment_group_minimum_capacity_invested_available] = Dict( + (investment_group=ig, stochastic_scenario=s, t=t) => @constraint( + m, + _group_capacity_invested_available(m, ig, s, t) + >= + minimum_capacity_invested_available[(investment_group=ig, stochastic_scenario=s, analysis_time=t0, t=t)] + ) + for ig in indices(minimum_capacity_invested_available) + for (s, t) in _capacity_entities_invested_available_s_t(m) + ) +end + +""" + add_constraint_investment_group_maximum_capacity_invested_available!(m::Model) + +Force capacity invested available in a group to be lower than the maximum. +""" +function add_constraint_investment_group_maximum_capacity_invested_available!(m::Model) + t0 = _analysis_time(m) + m.ext[:spineopt].constraints[:investment_group_maximum_capacity_invested_available] = Dict( + (investment_group=ig, stochastic_scenario=s, t=t) => @constraint( + m, + _group_capacity_invested_available(m, ig, s, t) + <= + maximum_capacity_invested_available[(investment_group=ig, stochastic_scenario=s, analysis_time=t0, t=t)] + ) + for ig in indices(maximum_capacity_invested_available) + for (s, t) in _capacity_entities_invested_available_s_t(m) + ) +end + +function _capacity_entities_invested_available_s_t(m) + [ + (stochastic_scenario=s, t=t) + for (t, path) in t_lowest_resolution_path( + m, vcat(units_invested_available_indices(m), connections_invested_available_indices(m)) + ) + for s in path + ] +end + +function _group_capacity_invested_available(m, ig, s, t) + t0 = _analysis_time(m) + @fetch units_invested_available, connections_invested_available = m.ext[:spineopt].variables + ( + + expr_sum( + + units_invested_available[u, s, t] + * unit_capacity[(unit=u, node=n, direction=d, stochastic_scenario=s, analysis_time=t0, t=t)] + for (u, s, t) in units_invested_available_indices( + m; unit=unit__investment_group(investment_group=ig), stochastic_scenario=s, t=t_in_t(m; t_long=t) + ) + for (u, n, d) in Iterators.flatten( + ( + indices( + unit_capacity; + unit=u, + node=unit__from_node__investment_group(unit=u, investment_group=ig), + direction=direction(:from_node), + ), + indices( + unit_capacity; + unit=u, + node=unit__to_node__investment_group(unit=u, investment_group=ig), + direction=direction(:to_node), + ), + ) + ); + init=0 + ) + + expr_sum( + + connections_invested_available[conn, s, t] + * connection_capacity[(connection=conn, node=n, direction=d, stochastic_scenario=s, analysis_time=t0, t=t)] + for (conn, s, t) in connections_invested_available_indices( + m; + connection=connection__investment_group(investment_group=ig), + stochastic_scenario=s, + t=t_in_t(m; t_long=t) + ) + for (conn, n, d) in Iterators.flatten( + ( + indices( + connection_capacity; + connection=conn, + node=connection__from_node__investment_group(connection=conn, investment_group=ig), + direction=direction(:from_node), + ), + indices( + connection_capacity; + connection=conn, + node=connection__to_node__investment_group(connection=conn, investment_group=ig), + direction=direction(:to_node), + ), + ) + ); + init=0 + ) + ) +end \ No newline at end of file diff --git a/src/run_spineopt_benders.jl b/src/run_spineopt_benders.jl index 0d5dc1adde..a77599cba0 100644 --- a/src/run_spineopt_benders.jl +++ b/src/run_spineopt_benders.jl @@ -163,6 +163,8 @@ function _add_mp_constraints!(m; log_level=3) add_constraint_investment_group_equal_investments!, add_constraint_investment_group_minimum_entities_invested_available!, add_constraint_investment_group_maximum_entities_invested_available!, + add_constraint_investment_group_minimum_capacity_invested_available!, + add_constraint_investment_group_maximum_capacity_invested_available!, ) name = name_from_fn(add_constraint!) @timelog log_level 3 "- [$name]" add_constraint!(m) diff --git a/src/run_spineopt_standard.jl b/src/run_spineopt_standard.jl index a8c53248d2..9cceeb1b50 100644 --- a/src/run_spineopt_standard.jl +++ b/src/run_spineopt_standard.jl @@ -212,6 +212,8 @@ function _add_constraints!(m; add_constraints=m -> nothing, log_level=3) add_constraint_investment_group_equal_investments!, add_constraint_investment_group_minimum_entities_invested_available!, add_constraint_investment_group_maximum_entities_invested_available!, + add_constraint_investment_group_minimum_capacity_invested_available!, + add_constraint_investment_group_maximum_capacity_invested_available!, ) name = name_from_fn(add_constraint!) @timelog log_level 3 "- [$name]" add_constraint!(m) diff --git a/templates/spineopt_template.json b/templates/spineopt_template.json index 17a158474b..a52a88aea7 100644 --- a/templates/spineopt_template.json +++ b/templates/spineopt_template.json @@ -16,10 +16,13 @@ ], "relationship_classes": [ ["connection__from_node", ["connection", "node"], "Defines the `nodes` the `connection` can take input from, and holds most `connection_flow` variable specific parameters.", 280378317271897], + ["connection__from_node__investment_group", ["connection", "node", "investment_group"], "Indicates which connection capacities are included in the capacity invested available of an investment group"], ["connection__from_node__user_constraint", ["connection", "node", "user_constraint"], "when specified this relationship allows the relevant flow connection flow variable to be included in the specified user constraint"], + ["connection__investment_group", ["connection", "investment_group"], "Indicates that a `connection` belongs in an `investment_group`."], ["connection__investment_stochastic_structure", ["connection", "stochastic_structure"], "Defines the stochastic structure of the connections investments variable"], ["connection__investment_temporal_block", ["connection", "temporal_block"], "Defines the temporal resolution of the connections investments variable"], ["connection__node__node", ["connection", "node", "node"], "Holds parameters spanning multiple `connection_flow` variables to and from multiple `nodes`."], + ["connection__to_node__investment_group", ["connection", "node", "investment_group"], "Indicates which connection capacities are included in the capacity invested available of an investment group"], ["connection__to_node", ["connection", "node"], "Defines the `nodes` the `connection` can output to, and holds most `connection_flow` variable specific parameters.", 280378317271898], ["connection__to_node__user_constraint", ["connection", "node", "user_constraint"], "when specified this relationship allows the relevant flow connection flow variable to be included in the specified user constraint"], ["connection__user_constraint", ["connection", "user_constraint"], "Relationship required to involve a connections investment variables in a user_constraint"], @@ -31,6 +34,7 @@ ["model__stochastic_structure", ["model", "stochastic_structure"], "Defines which `stochastic_structure`s are included in which `model`s."], ["model__temporal_block", ["model", "temporal_block"], "Defines which `temporal_block`s are included in which `model`s."], ["node__commodity", ["node", "commodity"], "Define a `commodity` for a `node`. Only a single `commodity` is permitted per `node`"], + ["node__investment_group", ["node", "investment_group"], "Indicates that a `node` belongs in a `investment_group`."], ["node__investment_stochastic_structure", ["node", "stochastic_structure"], "defines the stochastic structure for node related investments, currently only storages"], ["node__investment_temporal_block", ["node", "temporal_block"], "defines the temporal resolution for node related investments, currently only storages"], ["node__node", ["node", "node"], "Holds parameters for direct interactions between two `nodes`, e.g. `node_state` diffusion coefficients."], @@ -42,17 +46,17 @@ ["stochastic_structure__stochastic_scenario", ["stochastic_structure", "stochastic_scenario"], "Defines which `stochastic_scenarios` are included in which `stochastic_structure`, and holds the parameters required for realizing the structure in combination with the `temporal_blocks`."], ["unit__commodity", ["unit", "commodity"], "Holds parameters for `commodities` used by the `unit`."], ["unit__from_node", ["unit", "node"], "Defines the `nodes` the `unit` can take input from, and holds most `unit_flow` variable specific parameters.", 281470681805657], + ["unit__from_node__investment_group", ["unit", "node", "investment_group"], "Indicates which unit capacities are included in the capacity invested available of an investment group"], ["unit__from_node__user_constraint", ["unit", "node", "user_constraint"], "Defines which input `unit_flows` are included in the `user_constraint`, and holds their parameters."], + ["unit__investment_group", ["unit", "investment_group"], "Indicates that a `unit` belongs in an `investment_group`."], ["unit__investment_stochastic_structure", ["unit", "stochastic_structure"], "Sets the stochastic structure for investment decisions - overrides `model__default_investment_stochastic_structure`."], ["unit__investment_temporal_block", ["unit", "temporal_block"], "Sets the temporal resolution of investment decisions - overrides `model__default_investment_temporal_block`"], ["unit__node__node", ["unit", "node", "node"], "Holds parameters spanning multiple `unit_flow` variables to and from multiple `nodes`."], ["unit__to_node", ["unit", "node"], "Defines the `nodes` the `unit` can output to, and holds most `unit_flow` variable specific parameters.", 281470681805658], + ["unit__to_node__investment_group", ["unit", "node", "investment_group"], "Indicates which unit capacities are included in the capacity invested available of an investment group"], ["unit__to_node__user_constraint", ["unit", "node", "user_constraint"], "Defines which output `unit_flows` are included in the `user_constraint`, and holds their parameters."], ["unit__user_constraint", ["unit", "user_constraint"], "Defines which `units_on` variables are included in the `user_constraint`, and holds their parameters."], ["units_on__stochastic_structure", ["unit", "stochastic_structure"], "Defines which specific `stochastic_structure` is used for the `units_on` variable of the `unit`. Only one `stochastic_structure` is permitted per `unit`."], - ["unit__investment_group", ["unit", "investment_group"], "Indicates that a `unit` belongs in an `investment_group`."], - ["connection__investment_group", ["connection", "investment_group"], "Indicates that a `connection` belongs in an `investment_group`."], - ["node__investment_group", ["node", "investment_group"], "Indicates that a `node` belongs in a `investment_group`."], ["units_on__temporal_block", ["unit", "temporal_block"], "Defines which specific `temporal_blocks` are used by the `units_on` variable of the `unit`."] ], "parameter_value_lists": [ @@ -160,6 +164,8 @@ ["investment_group", "equal_investments", false, "boolean_value_list", "Whether all entities in the group must have the same investment decision."], ["investment_group", "minimum_entities_invested_available", null, null, "Lower bound on the number of entities invested available in the group at any point in time."], ["investment_group", "maximum_entities_invested_available", null, null, "Upper bound on the number of entities invested available in the group at any point in time."], + ["investment_group", "minimum_capacity_invested_available", null, null, "Lower bound on the capacity invested available in the group at any point in time."], + ["investment_group", "maximum_capacity_invested_available", null, null, "Upper bound on the capacity invested available in the group at any point in time."], ["model", "duration_unit", "hour", "duration_unit_list", "Defines the base temporal unit of the `model`. Currently supported values are either an `hour` or a `minute`."], ["model", "is_active", true, "boolean_value_list", "If false, the object is excluded from the model if the tool filter object activity control is specified"], ["model", "max_gap", 0.05, null, "Specifies the maximum optimality gap for the model. Currently only used for the master problem within a decomposed structure"], diff --git a/test/constraints/constraint_investment_group.jl b/test/constraints/constraint_investment_group.jl index 637fbf0d55..c4ee1da031 100644 --- a/test/constraints/constraint_investment_group.jl +++ b/test/constraints/constraint_investment_group.jl @@ -99,12 +99,9 @@ end function _test_equal_investments() @testset "equal_investments" begin url_in = _test_constraint_investment_group_setup() - unit_availability_factor = 0.5 - object_parameter_values = [ - ["investment_group", "ig", "equal_investments", true], - ] + object_parameter_values = [["investment_group", "ig", "equal_investments", true]] SpineInterface.import_data(url_in; object_parameter_values=object_parameter_values) - m = run_spineopt(url_in; log_level=0, optimize=true) + m = run_spineopt(url_in; log_level=0, optimize=false) constraint = m.ext[:spineopt].constraints[:investment_group_equal_investments] unit_ab = unit(:unit_ab) connection_bc = connection(:connection_bc) @@ -129,15 +126,15 @@ function _test_equal_investments() end end -function _test_minimum_entities_invested_available() - @testset "minimum_entities_invested_available" begin +function _test_min_max_entities_invested_available() + @testset "min_max_entities_invested_available" begin url_in = _test_constraint_investment_group_setup() - unit_availability_factor = 0.5 object_parameter_values = [ ["investment_group", "ig", "minimum_entities_invested_available", 3], + ["investment_group", "ig", "maximum_entities_invested_available", 8], ] SpineInterface.import_data(url_in; object_parameter_values=object_parameter_values) - m = run_spineopt(url_in; log_level=0, optimize=true) + m = run_spineopt(url_in; log_level=0, optimize=false) constraint = m.ext[:spineopt].constraints[:investment_group_minimum_entities_invested_available] unit_ab = unit(:unit_ab) connection_bc = connection(:connection_bc) @@ -151,42 +148,63 @@ function _test_minimum_entities_invested_available() m.ext[:spineopt].variables[:storages_invested_available][node_c, parent, t] for t in time_slice(m; temporal_block=temporal_block(:investments_two_hourly)) ] - observed_con = constraint_object(constraint[con_key]) + observed_con = constraint_object( + m.ext[:spineopt].constraints[:investment_group_minimum_entities_invested_available][con_key] + ) expected_con = @build_constraint(u_ab_inv_avail + conn_bc_inv_avail + sum(node_c_inv_avail) >= 3) @test _is_constraint_equal(observed_con, expected_con) + observed_con = constraint_object( + m.ext[:spineopt].constraints[:investment_group_maximum_entities_invested_available][con_key] + ) + expected_con = @build_constraint(u_ab_inv_avail + conn_bc_inv_avail + sum(node_c_inv_avail) <= 8) + @test _is_constraint_equal(observed_con, expected_con) end end -function _test_maximum_entities_invested_available() - @testset "maximum_entities_invested_available" begin +function _test_min_max_capacity_invested_available() + @testset "min_max_capacity_invested_available" begin url_in = _test_constraint_investment_group_setup() - unit_availability_factor = 0.5 object_parameter_values = [ - ["investment_group", "ig", "maximum_entities_invested_available", 8], + ["investment_group", "ig", "minimum_capacity_invested_available", 300], + ["investment_group", "ig", "maximum_capacity_invested_available", 800], ] - SpineInterface.import_data(url_in; object_parameter_values=object_parameter_values) - m = run_spineopt(url_in; log_level=0, optimize=true) - constraint = m.ext[:spineopt].constraints[:investment_group_maximum_entities_invested_available] + relationships = [ + ("unit__from_node__investment_group", ("unit_ab", "node_a", "ig")), + ("connection__to_node__investment_group", ("connection_bc", "node_c", "ig")), + ] + relationship_parameter_values = [ + ("unit__from_node", ("unit_ab", "node_a"), "unit_capacity", 150), + ("connection__to_node", ("connection_bc", "node_c"), "connection_capacity", 250), + ] + SpineInterface.import_data( + url_in; + object_parameter_values=object_parameter_values, + relationship_parameter_values=relationship_parameter_values, + relationships=relationships, + ) + m = run_spineopt(url_in; log_level=0, optimize=false) unit_ab = unit(:unit_ab) connection_bc = connection(:connection_bc) - node_c = node(:node_c) parent = stochastic_scenario(:parent) t4h = first(time_slice(m; temporal_block=temporal_block(:investments_four_hourly))) con_key = (investment_group=investment_group(:ig), stochastic_scenario=parent, t=t4h) u_ab_inv_avail = m.ext[:spineopt].variables[:units_invested_available][unit_ab, parent, t4h] conn_bc_inv_avail = m.ext[:spineopt].variables[:connections_invested_available][connection_bc, parent, t4h] - node_c_inv_avail = [ - m.ext[:spineopt].variables[:storages_invested_available][node_c, parent, t] - for t in time_slice(m; temporal_block=temporal_block(:investments_two_hourly)) - ] - observed_con = constraint_object(constraint[con_key]) - expected_con = @build_constraint(u_ab_inv_avail + conn_bc_inv_avail + sum(node_c_inv_avail) <= 8) + observed_con = constraint_object( + m.ext[:spineopt].constraints[:investment_group_minimum_capacity_invested_available][con_key] + ) + expected_con = @build_constraint(150 * u_ab_inv_avail + 250 * conn_bc_inv_avail >= 300) + @test _is_constraint_equal(observed_con, expected_con) + observed_con = constraint_object( + m.ext[:spineopt].constraints[:investment_group_maximum_capacity_invested_available][con_key] + ) + expected_con = @build_constraint(150 * u_ab_inv_avail + 250 * conn_bc_inv_avail <= 800) @test _is_constraint_equal(observed_con, expected_con) end end @testset "investment_group" begin - # _test_equal_investments() - _test_minimum_entities_invested_available() - _test_maximum_entities_invested_available() + _test_equal_investments() + _test_min_max_entities_invested_available() + _test_min_max_capacity_invested_available() end From 2a0e467b1a01f275dbb93b7834d73a8b3fb72b06 Mon Sep 17 00:00:00 2001 From: datejada Date: Fri, 29 Sep 2023 18:01:27 +0200 Subject: [PATCH 22/33] Second set of changes to the reserve tutorial --- docs/src/tutorial/reserves.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 95e0d43964..2bc51dd0ea 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -27,6 +27,13 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys ![image](../figs_reserves/aaa.png) +- Right click on the *node* class, and select *Add object group* from the context menu. The *Add object group* dialog will pop up. In the *Group name* field write *upward\_reserve\_group* to refer to this group. Then, add as a members of the group the nodes *electricity\_node* and *upward\_reserve\_node*, as shown in the image below; then press *Ok*. + +!!! note +In SpineOpt, groups of nodes allow the user to create constraints that involve variables from its members. Later in this tutorial, the group named *upward\_reserve\_group* will help to link the flow variables for electricity production and reserve provision. + +![image](../figs_reserves/aaa.png) + #### Establishing relationships - Always in the Spine DB editor, locate the *Relationship tree* (typically at the bottom-left). Expand the *root* element if not expanded. @@ -35,6 +42,12 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys ![image](../figs_reserves/aaa.png) +- Right click on the *report\_\_output* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. + +- Enter *report1* under *report*, and *variable\_om\_costs* under *output*. Repete the same procedure in the second line to add the *res\_proc\_costs* under *output* as seen in the image below; then press *Ok*. This will write the total *vom\_cost* and *procurement reserve cost* values in the objective function to the output database as a part of *report1*. + +![image](../figs_reserves/aaa.png) + #### Specifying object parameter values - Back to *Object tree*, expand the *node* class and select *upward\_reserve\_node*. @@ -49,7 +62,20 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys #### Specifying relationship parameter values -TBD +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_a | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *unit\_capacity* parameter and the *Base* alternative, and enter the value *100* as seen in the image below. This will set the capacity to provide reserve for *power\_plant\_a*. + +!!! note +The value is equal to the unit capacity defined for the electricity node. However, the value can be lower if the unit cannot provide reserves with its total capacity. + +![image](../figs_reserves/aaa.png) + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *unit\_capacity* parameter and the *Base* alternative, and enter the value *200* as seen in the image below. This will set the capacity to provide reserve for *power\_plant\_b*. + +![image](../figs_reserves/aaa.png) When you're ready, commit all changes to the database. From 9fcb03356d4ebdc6efb250b3fea439271f24dc38 Mon Sep 17 00:00:00 2001 From: datejada Date: Fri, 29 Sep 2023 19:52:45 +0200 Subject: [PATCH 23/33] Trird set of changes to the reserve tutorial --- docs/src/tutorial/reserves.md | 79 ++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 2bc51dd0ea..9c316b98b8 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -30,7 +30,7 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys - Right click on the *node* class, and select *Add object group* from the context menu. The *Add object group* dialog will pop up. In the *Group name* field write *upward\_reserve\_group* to refer to this group. Then, add as a members of the group the nodes *electricity\_node* and *upward\_reserve\_node*, as shown in the image below; then press *Ok*. !!! note -In SpineOpt, groups of nodes allow the user to create constraints that involve variables from its members. Later in this tutorial, the group named *upward\_reserve\_group* will help to link the flow variables for electricity production and reserve provision. +In SpineOpt, groups of nodes allow the user to create constraints that involve variables from its members. Later in this tutorial, the group named *upward\_reserve\_group* will help to link the flow variables for electricity production and reserve procurement. ![image](../figs_reserves/aaa.png) @@ -38,7 +38,7 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - Always in the Spine DB editor, locate the *Relationship tree* (typically at the bottom-left). Expand the *root* element if not expanded. - Right click on the *unit\_\_to_node* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. -- Select the names of the two units and their **receiving** nodes, as seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into the *upward\_reserve\_node*. +- Select the names of the two units and their **receiving** nodes, as seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into both the *upward\_reserve\_node* and the *upward\_reserve\_group*. ![image](../figs_reserves/aaa.png) @@ -56,7 +56,13 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - *demand* parameter and the *Base* alternative, and enter the value *20*. This will establish that there's a demand of '20' at the reverse node. - *is_reserve_node* parameter and the *Base* alternative, and enter the value *True*. This will establish that it is a reverse node. - *upward_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. - - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve provision must be greater or equal than the reserve demand. + - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve procurement must be greater or equal than the reserve demand. + +![image](../figs_reserves/aaa.png) + +- Select *upward\_reserve\_group* in the *Object tree*. + +- In the *Object parameter* table, select the *balance\_type* parameter and the *Base* alternative, and enter the value *balance\_type\_none* as seen in the image below. This will establish that there is no need create an extra balance between the members of the group. ![image](../figs_reserves/aaa.png) @@ -77,12 +83,75 @@ The value is equal to the unit capacity defined for the electricity node. Howeve ![image](../figs_reserves/aaa.png) +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_a | upward\_reserve\_group*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the following parameter as seen in the image below: + - *unit\_capacity* parameter and the *Base* alternative, and enter the value *100*. This will set the total capacity for *power\_plant\_a* in the group. + - *ramp\_up\_limit* parameter and the *Base* alternative, and enter the value *1*. This will set the ramping up capacity to 100% of the unit capacity for *power\_plant\_a*. + +!!! note +The *ramp\_up\_limit* parameter triggers the [Splitting unit flows into ramps]@(ref) constraint, which links the unit's flow and reserve variables. + +![image](../figs_reserves/aaa.png) + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_group*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the following parameter as seen in the image below: + - *unit\_capacity* parameter and the *Base* alternative, and enter the value *200*. This will set the total capacity for *power\_plant\_b* in the group. + - *ramp\_up\_limit* parameter and the *Base* alternative, and enter the value *1*. This will set the ramping up capacity to 100% of the unit capacity for *power\_plant\_b*. + When you're ready, commit all changes to the database. ### Executing the workflow -TBD +- Go back to Spine Toolbox's main window, and hit the **Execute project** button ![image](../figs_simple_system/play-circle.png) from the tool bar. You should see 'Executing All Directed Acyclic Graphs' printed in the *Event log* (at the bottom left by default). + +- Select the 'Run SpineOpt' Tool. You should see the output from SpineOpt in the *Julia Console* after clicking the *object activity control*. ### Examining the results -TBD +- Select the output data store and open the Spine DB editor. You can already inspect the fields in the displayed tables or use a pivot table. + +- For the pivot table, press **Alt + F** for the shortcut to the hamburger menu, and select **Pivot -> Index**. + +- Select *report\_\_unit\_\_node\_\_direction\_\_stochastic\_scenario* under **Relationship tree**, and the first cell under **alternative** in the *Frozen table*. + +- Under alternative in the Frozen table, you can choose results from different runs. Pick the run you want to view. If the workflow has been run several times, the most recent run will usually be found at the bottom. + +- The *Pivot table* will be populated with results from the SpineOpt run. It will look something like the image below. + +![image](../figs_reserves/aaa.png) + +As anticipated, the *power\_plant\_b* is supplying the necessary reserve due to its surplus capacity, while *power\_plant\_a* is operating at full capacity. Additionally, in this model, we have not allocated a cost for reserve procurement. One way to double-check it is by selecting *report\_\_model* under **Relationship tree** and look at the costs the *Pivot table*, see image below. + +![image](../figs_reserves/aaa.png) + +So, is it possible to assign costs to this reserve procurement in SpineOpt? Yes, it is indeed possible. + +#### Specifying a reserve procurement cost value + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_a | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *reserve\_procurement\_cost* parameter and the *Base* alternative, and enter the value *5* as seen in the image below. This will set the cost of providing reserve for *power\_plant\_a*. + +![image](../figs_reserves/aaa.png) + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *reserve\_procurement\_cost* parameter and the *Base* alternative, and enter the value *35* as seen in the image below. This will set the cost of providing reserve for *power\_plant\_b*. + +![image](../figs_reserves/aaa.png) + +**Don't forget to commit the new changes to the database!** + +#### Executing the worflow and examining the results again + +- Go back to Spine Toolbox's main window, and hit again the **Execute project** button as before. + +- Select the output data store and open the Spine DB editor. You can inspect results as before, which should look like the image below. + +![image](../figs_reserves/aaa.png) + +Since the cost of reserve procurement is way cheaper in *power\_plant\_a* than in *power\_plant\_b*, then the optimal solution is to reduce the production of electricity in *power\_plant\_a* to provide reserve with this unit rather than *power\_plant\_b* as before. By looking at the total costs, we can see that the reserve procurement costs are no longer zero. + +![image](../figs_reserves/aaa.png) From 7ecc962cb03c0585c756d68d43c1f79aeed5fa07 Mon Sep 17 00:00:00 2001 From: datejada Date: Mon, 2 Oct 2023 09:33:00 +0200 Subject: [PATCH 24/33] Add png files and links to them in the tutorial --- ...s_tutorial_power_plant_a_ramp_up_limit.png | Bin 0 -> 9333 bytes ...ial_power_plant_a_res_procurement_cost.png | Bin 0 -> 9688 bytes ...utorial_power_plant_a_reserve_capacity.png | Bin 0 -> 7127 bytes ...s_tutorial_power_plant_b_ramp_up_limit.png | Bin 0 -> 9446 bytes ...ial_power_plant_b_res_procurement_cost.png | Bin 0 -> 9781 bytes ...utorial_power_plant_b_reserve_capacity.png | Bin 0 -> 7230 bytes ..._tutorial_report__output_relationships.png | Bin 0 -> 13277 bytes .../reserves_tutorial_reserve_group.png | Bin 0 -> 10669 bytes ...rves_tutorial_reserve_group_parameters.png | Bin 0 -> 5754 bytes .../reserves_tutorial_reserve_node.png | Bin 0 -> 8701 bytes ...erves_tutorial_reserve_node_parameters.png | Bin 0 -> 10698 bytes .../reserves_tutorial_results_pivot_table.png | Bin 0 -> 27520 bytes ...orial_results_pivot_table_reserve_cost.png | Bin 0 -> 27930 bytes ...eserves_tutorial_results_report__model.png | Bin 0 -> 7084 bytes ...ial_results_report__model_reserve_cost.png | Bin 0 -> 7620 bytes .../reserves_tutorial_schematic.png | Bin 0 -> 27664 bytes ...s_tutorial_unit__to_node_relationships.png | Bin 0 -> 19508 bytes docs/src/tutorial/reserves.md | 34 +++++++++--------- 18 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_res_procurement_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_report__output_relationships.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group_parameters.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node_parameters.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model_reserve_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_schematic.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_unit__to_node_relationships.png diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png new file mode 100644 index 0000000000000000000000000000000000000000..2990dd5727585107dea592476711d4e212df0409 GIT binary patch literal 9333 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 Fe*gzHDEHbzI~;M$95bK?VTUF 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png new file mode 100644 index 0000000000000000000000000000000000000000..fb4c731b39f00c806dffde08378fc59d91e47224 GIT binary patch literal 7127 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 Yy+8~PPY1kW?z^$*>)g`DLhe8PUwB}1o&W#< literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png new file mode 100644 index 0000000000000000000000000000000000000000..1955d05672edb1a661a8a42bed2f25b9163452a3 GIT binary patch literal 9446 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png new file mode 100644 index 0000000000000000000000000000000000000000..a821af444911163bb6725e4468f212208f57b453 GIT binary patch literal 9781 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png new file mode 100644 index 0000000000000000000000000000000000000000..be405fcd102f57669b417b7dd6eb9d7eb9ec9cf5 GIT binary patch literal 7230 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_report__output_relationships.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_report__output_relationships.png new file mode 100644 index 0000000000000000000000000000000000000000..0343307405281427df1a56d614f3320bbf5786a8 GIT binary patch literal 13277 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group.png new file mode 100644 index 0000000000000000000000000000000000000000..83cf7d03fb3e6175f0fd32a810ac37c24d39b8a8 GIT binary patch literal 10669 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⪼3ipkuWJP0pa;KcAZEk&hG$*b!?kv)$? zos`|0se49^ zZ-9}lvYES6Cqb80_N@r-vhU(+c_OO*WOMm~x+n~a{ThR`PnSAr>c{t7@xe(^{iw}l zM$Dy?_(;@iNWv@XL&YY0c-%?}WGu|b-(2bH3DS^u=IhifuvAt9FY0ONUpDs*pE}wh z>N~?F0&-vueF{OW~|L zl9wOPzG~ppY(Hx6hdMzl>~+%6iFm^R_)N-=?R5~0UWS?73}P9M>)rn46ca{VxMyl( zDci%a+4<^mp9sZGMPFE)jrQ7)#Qu;bmYr|8f}s4&dHum}7nnhL+vvok>D{{;N^Y9V zvpjqk2VAUql53dZGh~zVr+IcAU%zJA50hEAU?rbF;@1?x39g$P$bw0&m6yoa1_x*v zhcTAUzc>GL=XhqT*q!TYBYx39TFsQ{hcZfJ(A8}gXd!Z&)jt|CJ`b=|6$CxT=K9Fp zDVPh&ejan*omj>?goyCLkd zkF5R-7`*;he;eih5KktII7KE;K4Yk`!`ADX$zO46FnH(lf807hvF*q_N*Rs(xeGFq z)gZ!JerhIVk@aaNu6zBdF+ha&1~PYr?Hc;H74N}ZbM3&KVd#VlWv*%CFq8an>C82% zT1LqjY|*1T6q5HmHt+>dc&AJ6R2o6?TTGRDYOXq%Rp2#}-5A=-bl<#JIQ81r8uQET zQ;Kw)CJI~HN7Uhkp*XUe0oB?BfEuX-J~!TR#oL=&j|aJejC}#@M{-9aue1 z*Mt0+u!&szny^0OmH}_OtH6nKqgmiINbuQ*U$vjTBPhBT?Uwz;vr3+x>xfCu?c}C$ zA5o*Hcz1%!H-R*CVC#rQz?mlPs?O28Qop41#2tMrRx2Xh2rY(vfq~Y^)wR;{ktOnj z!JwhC=W6s~bK<*S@maANfFRvtbY@-WKD;SQk{?RkBMPNmVcK=Zd#(o-BQQb__VpI% zFhid>WaD+z)I2G@UKI>4)2y023^#aaZaqA52M$#u?7OACXnsYfdDYmL5n+rtw1>DK z20YX~swSkX`hB*`BRZEge2&k`z~&deYUlYtT1firx4y8?DxTU~6o$UD#B&vTpVovi z*W*C5p+?86?a8AB_nv!P3~2w>aeT*g9o~jS@nuaAS@hBDmUBQcqJSh;13ApEo$y`& zba2a_8XknU&G;*OtH7GHh=RS;kd`C%Y9R+)a)Dsbd+yp=q zrcd90=(0xo00Hk{B8gCnR;jI$rW^fw5Yp?o3p&CN>iiYD-~Ja^Aj`;l_gY}d`tpb8 za6(dz`kA%lmhSa_3yeZ_>2v2DxSU%F#D`xi8ULUG{N@me^v6E9M;*5pE4iZxsSlu1 z)a7>anASKO+LTw%Z2Q{CCOL^hZ5O}*Y^@Psn`W8Kpj-inkd8qlcKqW@!kq?kR)3he zPDePHlVutCMfs~GF9qtyTjFfJW4pf|u{ybMTbr!kK5CKae@IO1_y2ehT|(XO{x2Us z-Y-tV=xmiyPAe&ivSrN@2luQi0CqA3JB;XYgJHtAYdN0Aod@R0Y^EH s-EF<-b?a`1p$$%(<(1%@)VIy0*KBoK8l(7*U2bp~8<^{t>N-UI2PMBeHUIzs literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node_parameters.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node_parameters.png new file mode 100644 index 0000000000000000000000000000000000000000..e37a307f3969f421e0db207600df0c340f469933 GIT binary patch literal 10698 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 Ce2D}A literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table.png new file mode 100644 index 0000000000000000000000000000000000000000..6adde62a57bd46bb4527a68892f280b92d1877b1 GIT binary patch literal 27520 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 F`!})Ccai`A literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png new file mode 100644 index 0000000000000000000000000000000000000000..ed17d4580e30f05aecd8a1cbbeb13df779b95e96 GIT binary patch literal 27930 zcmeFZc{r5q|NpO$goHu}6-mXUvV|FvkS(dK8B0=j#+qd;$xbU}Eed7NGPW_Y3=upUi%=|{neRqG}_x=99KcD0CJ&x}mzvIx+VP>xDI_Esk>%1PX=ks}rx~8wm zu}@$h0|Ntxw$|nA3=F$R85njc@7+UxMW}^Ci~ip($aT$2427LS^YmYs?A7$t7#KA$nOX_-P87;}^W4?85sGrvC7)Kveq+(Y>KNKanZNE{sA6Mbw-7!Y{qKcJko9aF64X zdPLlIC+_=iJ1;&L+?(R^>-`yILw3r~k6x-ODW1>%^*NU_PSuk16Z|-Y?e{~@-K&Of zk8)g!du8vQ z1a9KV*t??=my4&G{K34${* zrOb|ue>mZb$TkmDkB5ldtKRI8`#CN%TAL4g;E@51lq@Z3+QMiMTrAzF^F`o*=M?T? zL`l!%Dd9hch+**E{Dz?U{d9lC*C&|mwY8#W4^OD1rlCmP0X^{8_M-ZidxYwkVF;V+ zP=(ijj2|HEk3PNhX7T7hj^97pmj4M;i?(weADT`m#otsmXC)O-7X~L(w6D7kuru; zd9fXiSmBFqto3Va2?weaJ@zMCoj97bwy!EpJ${ypz&7Anw3o*f`o;itdgmP4tuwWk zTriKb{4P^=%Z;9HXc`93_0T__!+Dq6L$Qc{{^@(dhKOK2V)R-31|NC7_R{iv*sF&Y zou{Y0_bVoA_5!SW;Ky`pDgQSwcgI^Ax;Y<#ZHHyFL*17#u7G}#Ao9CyKFr+%v-3h8 z^ezC`XZvfs^xa|$d|-K$xc*7^oO}`pjDQE!P=$ar56XN*5*C)xGlD`F0zliIly|1` z31@YTu*hckORS=G7}5iqhyT_@p82 zfwsV!PqifHNzJuLGP6^)@xv$>qALe;$iqP7i`aRHB-*J33cp-8SV7~31tFpEhyQe8 z`6P21#hI!!`n=`E-%X>ZgH`KPgXg!V&0VM>l9CCh{`QLWxqK7`Y3)|d4BC~le8_ro z39vrz7e3O%a-Ov+)wp%(?+5vkG`+=2KZaxkKF`aTuJ^IARk{ewcr{5`{lx2mC)(og1)pe(b-0 zxZ)K{OUn_A2-m;8h~kyE^Hhhaj%uKi$4Wm_6B|RURW z&ayKOgPyJj>O_fud}}epHMnA%OsF2wUJ$2}vW#;r>Q8F-7jSOe5+9C0 zH$o+-in^k{?fO_GsG7<>3#|)kM}YLxms*et*SMB&$Q3T((o>K;!K|R);YlrjoRriq3+r3OiWhyAZBMq*$$64^ z{+qzCCjtzxvkan$=^s3@>*Jn{GY_yMn_Vlu_W#tn>&bntpgeaMhnVeEBPXlI>LDiE zQVVf;c!^)XeKLI0qP$NIbb*5UsDWpU)K@}zomOkesFKcL0xy_SZVMnQ7 zxi z?W;ocG6lw6`!goaIOS$F`4u$Ep)75kH9AYSt~lbqI1PK>M~%$;RQD&lEIL`&n)gVd zmc~5NFHGZy3B>k~RF$F^6oNVNeC7ncQDL8j*MCDGeC#Gs3*uO*O z!YBwDi2Bd+`Qs%3Vi~9Ke(}x%FdDCv*+*U!1B@R z5-J>vLfd3Xa(HZ~CR-33MV%Y-1hKvAL6!4`WNZ;^JAfh?cx!{bf4Se&f6ctfxw->) zRp&g#1C{N+juj7`S?q70d7xb#I%bDUt{&`O^#%X)Ah|sL+BAE`T#WXvX<7bjRX6Wv z=%>{wJy`0Cl=(C1Dx0qm-Wl1$DZ{6NdX5MV2Gm`s6rpA-$##w+v?S-`M$cKyKBZcP zUA#=YcA!6f%UFj=IDyFYkKgTRc4Q=|79;Y+vPVx@8k_!BIDIKyU zEG`{W0@wa_x$)t&?gQ?qnals{YZX9488=(&+ zN)+X^mBq??-ZlMP(c`UC>z|bAOFj>M9i$TpPuuxn>b(Xemd+%3T`X&Rt5SDX2u8V4 zgOlG66D*>WOwlEgFUO}nfIBPjfG6mUa_LgS38z{*ztrsuJe%;iee50En_836iy# zB~d1FumDm(*d4+2(Ig@-eo(VnNrEk9*{?o(OHGUy<_s8AafWeN3qfnBPJJp*eVOwl z#)1yYjiSVbTU78HSpfy}W9K!$zIrEF9UfnjPZrg2c!}tJxHRH9oGhzT7g#ajTzLb} zhLYc#vW$u$Ip_Iq8UE-=&Z8n*cd_0Tv;YckbiJ+o=rPNQkCRKK4cS|pO;bbBFjN~R z*~Olkw;JwxjQI4Xh*(s~ww4}otvBEQ^DSu@{e(r@g__6l8>T-7z+MtiC(_GymM`sO zmHX9jV3FQ+HY1nJQq{&6V1@Rvv&1D-N;wvgh4kLyHnK(aIT$$aU2D&4%i=RD`xXrw zd*(7_H+6Jx?Z8?9@3*t%bvIo_XnR^EOuB7<;4U^d03~i<($&GtLL|@W9u(H zP!SwaQc*Bx+z|rhd^e>gKGGZsE0n$#xsc-~kqOm*-~q7Rqr zZG&4?FuivUX1YK%pr(G0a=P8*+iv6Zt&1LCDoX}F;|gp758#43OfZ|8PVF{MU;Oi> zU)Zal6))bS(F@8duw>SukcR7 zm-nO`CRU5X_&&mqdnB!ySN5cW+1r;^PvW*5cR65g91WYi;W>QCBz^1afD7t|t!;wj z#}95Bmdc#cPm)fKZEID?SuTk8yF~)J44rySioePUJ(mgvuFq$DqEljF9 z!RxXAu<7IkU=ULJGPUfYXM6+M3Z;N}ksh)haNuoklamg-v8w_pul;2$Kd&R_%wuD< zV*LtPHfM)LY;@lsJfpNC`WbD%$Y6xw*TMLrv-?wCmOW5ClXTHicl#7=P!YZ7^pG+6 z@VkBFFDW9w#^#jnYQB`}&7n}^7>H8NzU-}IZPgXELIa-utFJDd@VL>_k@Pj_qdbvA zGb{UDRCpq7xyn>m-|WamP3yp7`&9H*lxjX_=yYl5YbnBh^2iJS%X$;ojLsw2{RCxJfd-%}7kDW2CfaSXU!StA{2a>7*_;d(nzwj?uo-z%^J>3vZ4h(Yzp=|V@~{UHC%RLmPi)5$4`%|$nn z=BA$L{iEBlYc&h}I#XfCE~cj-9q*V|H1|F06h2(zgI)C5G+}Zy0|Fpb+Vv5e1`>-yL(S3nj+-w-)c0+!Y0pcMF0T zAB$4yK9-8*Z)ObTfSF6^3Ju-#hl*3BwV?QtirEpHm{T>TUR`eV>p`^HWtkl@rBez@;-t0rgEl2->jVIG8(gzSubj?3yOZl$ z?aF$;I^)pXSsM|0#mG$83aG6jo5l@L+Ij{R(odUl-7cC~D-Fdf1L$>|0$n4364CQP zSLgx)3%xq0YZ9XJqoMY$wTDq_p(C9kJB&al$>1m$h^{?^(rdl}Pqy?b{9R=fn}-t1 zPbOlZm)oxm=&u-v(94OH{5bh3zhC;t4)y+d_Ik%^X4HW1`E+{Q(inf1ISh2w<7aCh z=)uMZ1zeG9wW2V{ucFOra*30!Ziv#QgWP#uWuvJMU%JfVz5hokCFP5-09#7;6EBp# zJdUpe|Ez*mtelARQcH=Y;KC$fJX;+CZVA4^wj4`r9~iT*pPKF2BAm-*^q=GfJ~j!| zi#q216a-~OqYI1VS3aBdNckorho`P@(^j8e7I(^5bnomfUlAsc3$whr`wlY1|Ck?r zUHz8lqsm;Ap~OC>%gw>*(Ej4Uv3=lTNeq6q2bH$cTCFjQU_(|Up z5EAYbSb4<7(1<>_mAyM(?XS2nN?XiO(VQCf*bE9}WVz~OyJo8J^n_AB51~=dY0LxY zN%Xz8#*KQRqo|qO-u}n}i;b;-*Ggk5-M`LWyZ4~6Y~-ggGpzZyvwb@;xw4(VlO zFp`^M--N`#htm=-t`-+( zFB~*qOAYAscQjnxwtMoFd}Q4?{PD`FVu!z@6|~M6)gl0gm{)4Q-cAe*^Jd%TFR2FL z(xv($W}P$`DAJ5KQrHy*m%8uSm~8IBU5I?Affhtw>*q`0Xom}$_o3$s_dGHF zqPa9i9wD>*PzHEJuaDqlP6IxWDol-SsAdIpXS>OzUvN!Hk?R{FARPjbH6u! zhQy!4U&Q6*+}%HrLD)bQY;bOOtH^Wkn7P>9CTNsEo}u>0@yIuu#g7T((#Ep|1=)EX zA86vPC3!q?ALE-9{U{!}rVwyTZER2AWt`tbTIgl?IepgC-g$ibX^l*58A)OZn!OKU z+9o{m3qlh2&g?B$tKU7rcZf2w$m!D^1TePLFaTekGBPi_YS;u}H#l*{3~eHq&$%>M z0FUOh%TgTnt2%lqm3P?Cxa_^l3y3VnPI@H-QU?$|V!7)^$)V-@evVb|BZE#+`J_Jr zrb`J%!YPV30qhxa07SH<-usIc_!#dAdwFAjnGc3`B8BO@q0$1#xkrg-#op_B9pFk)gf+dZ7+@a zeLvrAopZxtt1+KGBJyu{>ad>n`37u_QmK%!xprqURhi{TH^Lhs4AW=|@pp+q=G+Az zFjuIN`MMSdPq@vp)@&ef>XEK>bCoQ5VDnt!`6Z-N%=w&+syg2QU*>C@_Ek{4-=&oH zz3q-i+Uxq@hQ>-c#QSJz8&2}>TaImy!KQ4eXSb((EjCma_ubL+ulRg8a`Oqm{dVvX z!GJRQ1PX($(13U7eNrk);yW@+65A@8I9+sP(G+-t+8|(#<5lqLSlH*C4Y{-(>&dH7 zy<1mE-c}KaltemSuBj*oVV5$@WmYtaBNue9TF(+SBpttT&TEe~}hEudN#AVE5mS5eHG}E+<#co}^<#;s-Y|0|TArmTxtr=8~Tq6YK z4(Br~U8!?gyd8x?T^J2T5Q)@`2*+CEsj7N6_Bxlzf|Vik)Taf)?4~7hY03;4YoY0jal-M32>_P4pk^?VsRV0tXW~ zZ4XiI+q#;v%2cS1ew$`TZnq{?>RYw!$#AZwZGvc+e#Dv&by;0@%tgvEGUkBv)q;AG zI(X0i3(#d@PKPm6ikz@nKK6q9b*m|p!aX=&@VMzHL}sI!I+qc1ukyv( zN|0Mnzx}FT$KA>7l`%!Si~@a~?XR}CfvkC3Q9*sTblitPVXkL6U)0*x8_%3PHh(GMQe+@Hee5y!s;2wwR-^p6s6=1O|?jDwm+Hp43)X(%swV(ud8cubvI?Lid({>Iqge6sNBw@zHu~;pe4L37UQS(QwyhSuU*{Uo;`6OsVRdF zqC+)af_z3~twpH$%xZ8+6#By*YlA|(-!ekjCm~dElD1Z?M+BJ(EQ8h~sLfa?4YXap zE;fnUeg(yn(c3Vnc$_egJ;vkiPcv%==E@%8>B7O}e2gjC){xRt-^9D3aYe+cCrxk} zftQC?QSl&ZQBDpQtshO<>L}G@{F4P~lF7?ipPGh6=>CBk-K!e$v~83k$a+s?mnDp+>(s}Pz_{ycksvgTgI7LkTqarQytXjB}S)&|~m z><8f`EPI}{?5;}vMW6sZ*o9^ouc7Xa@!O_F?ad&|7ecYF6p?-e2~3&6B4{Gp5&h6D zc^VuGCb!elY7*%bFMRu4uly+N;e}DuK2QD<&YyVgNXnpM5PpN< zx}r({0RR8#h0Iris_JSj3UT-E$!JanBI@9Emgu^iiBE2UWXckmyn1fhX72=k^?jO1 zBYa&qI>ilo5}0ld%aufSB-LZ0C=D> z6{EmWH)97~XaY-$rloE^W{5XUMX8U-OR0$eFnjimUm{8*m2Hlk1gvgvrUL4(x7 zl4dZO)2TYk7M(c$0aVp`epCAj?E+8Op4nJiJK%CRM8*w0S=U}P?zF|@6*2uVvAE3g zX}gj^E6Z&~-XSy7Usj zB;&(cQlN<^lXon(eXabiLPtNmb+gqw)qHy`n^0MC;C8;dh~Lx6>R3p=TH$+=LHLFW zM%RS1+~y!>h%so4@uHtl@WudN$PlLg#ZU4-D=Rh(0CH?3D@FRErbbhRw5U>+gKdnR zdhv-m9L>yR54H5uj^|c~KBeRfutBi7?CH9?*MmQEf4*j=doo9QeIPWha0AJj+WHw;=HyEMk3urJH*c3&Rp zxqqnhvgt=;+P$iR4YD`eknabR_HJ`Vf(U)}ea)|_?zXRl%>og3SmsN&5(7bm zs^{bGBzoeBag&(UqpPR%_Wze+Vccw$VpF^ba7Ia#sd|Ev|8Y{_+{p z#YJ%>V%lh z&)IuKUM^i~Q8|`R@GO;SX7R2*t`t8GKWXgP_F5QOzM`zif*YH4psyU+D#IkE?JX|h zWPH=gr0Id}nEjA|rrZ-B$@yW+iH+yv~>RQg7)H0EPL2o$5(E)1}T%LxGL_x+VpZqYqAE>+g0& zc+ZbGQbgAX`@feAzy@_Rb+cFi#axki11v9d({~Anw<1)O43+*_CUhJE+)cLM-2Sv9 zmsDdMd`IqjQX+}mDw{0F#S5f~$}JKqaE|_u{j%3yQzYyw~P+ zUIP_-UT}DIvXAw%zD_qVKJ4-QW(aZ!=pU<{myfK;eJd>>@YVc zgsths=5U7}Zp*HOYq$6St}Y)bccqD;z$bnxH*b#^Sqt5~r$AUf%C-vxYhH-C%3V!T zL$`Zab{*Wss02om1480tuss3#{k)kmdL!oPXE)U2-<9}D&ZolgPSzM} zuDXU<#=o9DdUuzza+yj0eTYOOvc!U8jBO!(2-s`t+*?;)T8*(;^rCcw_$I!6h%FS+ z$Wba`aAuPe^PjGQzI@LJ%o&5^vq(MI))*h17V0k>hbS;Asw$vr>ewFFC}5agkD`lk zIJXcrmssCgmTNRd*-^ILitRdLIyT}5#AxgZe&1`1kRJH!XQg-2f`G@WXra%c=T2g8 zo?zV^6jril>|%ZHWcysm%2x2WjjCnh6(FvN*ktvhbaj(tAToIQ!c;(!z7-MWJRu&U ze|cJVOdBnZ(ztCsoIAj}SSygV6q5^abHPWDW1b(OPqSN9KECV#jp^498=e}B{^-RH zg%*GA3)+LWv}5lE?HwP#Ha6-lU?H3ZHA2(bahBWnow!&XSE@E8s@q1V8Cno_=-`OE z$}&5Z0~QGY^#^3RdVQfQW7qH#XZpMm#yWswwfgQ$kTZNM#}^rXD_rI3o^xG3sWC^Q$)@ejJQ?!wxqd z?nA|WzY{^l^JDSuD%^wZ{V;-R>}O?IQw$;Q`t`EaP)Y3?(9e#mRfDQ}Ux==9t0np#Mr$`VYZ3 zBXb@oKo6y<{cBe4uUfIyiO21~7dG{O77o9k?`Drw2fpB;o_xqp3Ho>D1t+`Qk9L*H zeEBQks2KCND*4^tfF6VMbp1_|{{1a_aA(*5V$@Y$5?re|TLs6BJSV90d-Yu1^bC z&0ncJNJG?$RlO#@-H%Z;N@(<-3-cG!5}N)lZ$qm-Ox@0(V|O>q$kIO;+p?_-*6Y-U zjG75L$8UL^@kTMP)9-5e#*Q8-IoE1FcYqM3Q;j0wSiPhpD?U17lkO;_Hvl9(=#gS} zft$EC8j)`7lVF=&Ua3T%uK;qIi?~FXH-Y3vGg@pZZdCSrRRM^)5JvHelFc(h+RxIk zI`_VMEH*!q$Ef=xu*d@N7FEw7Z>wsZTFdJ?dt(v*R?1d(>31Ic_^47Mep&u6GBz0c z>MGuC;cL#yL7-hvAdl||?yz}AOXdE>D0*X3mTilXb~DXLV}e&>+J%^-N6G%m1Inv5 zHY)uUbBlu|b+9>rkM7EX^V*pVkOE&9L6c|^_h^{j0jBCBhct;!H$IHz{V4A#FZyEu2RqUaet>T;;rI1YhcdQ z@u6s9?HNd;&EdrdF+Nw!OQr2}RA9(x5nNlL2w+xFDA1l}Au?K1Fv>W!WTbrGWVyRA z6Ev+E2;BRQ*%|nO0IxYyZxI7z0Z##I*Y?kSdoD$|_Kl@j9;s&`2IK&q4LXQV*Mur= zI&NA<#Sm>$P?XqvRlV0NUMjRf?DVc!Dh>2B^s1}1XGgogK!m$4IT zPp9#b$t!Z!jwLY{z0R4pD#qM?XN4^J_9g_?L3QI>B6`f+Twm9?04xs|Zkg8rkHTY* z%B@1~e{9Y%w2v@4Ss@2(;CI?v5-w-TR5Ko*{g_XBX>@mNU@>y&-S&R$1rb{)CvJAM zaVW86Lt0_~RzUgz%Uw>(1D}tI$jC?I3~_VPcl9@K&whY3jwld!5DRTY!53nO2ajcuk-Cm~|l5 zJP=l7U7pQ8dAu+j^I3Y`FeR^Dn5TV*R^9e&#|K1VcQ5+d_~Os(rD{Yd0zXq7No|fS z{)wC~5XH#PuoDvIw?B1y>PKcg>DCA}E6_|obgjTh)HbYA*iAF=;%Le9X3R)=|ShI_VbpFP_3Q}1fPV7>l%e6-Bpq(!2Dx6NTqi6`X*4Y)1YR6a?gCSl412uqRIaB_c zA>Z?l31NKZSN!#7g>CCgU@{Ftvb_g&pz{@8C_DOS@*W+S|2 zePf9oL^aHaO(R{ih7urwf=xCV}-MKsGwVhy=)iI)TY-AMFG`Xu5 zG1kKy{+o2Ix2tn5ZMZ=v^cv|a)%gC|61O(aQ*IR(`$%29U1L?w0dpop8+0+6+0a-) zJ^Q9b7)S{}HdHQ}ui?TpG=>E13#%y@Q^ziCLSE!B!5G>s2gB@NK*;U~ts&|Onm(T_ zN}*4_&Ui?yJ49cX$&F~vZbn;VWS<+c!(tBV%G+^)g zzKN*`b!}1R*lG3P6OXFSK)0Se^qx>h5iImJJ9>k-+{cKEJgPy3J0 z(i4NPIcInMDbPZrv$yX38A13DvGSkU%$P3tw!paMMwvqYRZ4~4uYM<4R~~8e$7Yr@ zPv6wd*NMNK54!cbF*5LPwuodP{$Ie#-(wp8rH?|1?Sz>bk3a+U7)5T}7Ga4%AaAH} za3YOJ>s!MF0>K$CWGGtYF>luSm@9?^7h)xAGtW0^1jb)9JS)6*K2TOsqQlG4xlD1nzhpp# zuZyTj8;KpQWOgcfHNdBdfY1Ri*=6gxp0-cbON@XfPX%Y)n5Rz3K%SOzxWS+&tkSRt zZtoN*Tmc-}4~v94Rf7_W`lCwU%&bz#d-gvcK+cxBiB&zv#*imY$hj(tRQoIE`bA;d z-lZPzn6XnYBzR>bSG^Ql;-1MxTW2f|mcSf8SB^y#abeRW%V)>auGl-Na0uhTIK~)o6gwVE)JbMc@AA0_%q;LlwV&&+ zWjgSw5aw%NCX2mZ(F<|RC*cbh$#|POj&7d~lvfw&T8mP8)~1F&AKVq68rwnMmFREm zBM}i$wwc@KL*lb4)W`?}U$j^b`6D-BJJO^v*)z^KrOAc!TTgn1psOi$y4bN8=ONVj zteNZTe@ROiaWYHdxF{6X6wiy*yRS=U8!9DE*{0gmUg<5@0NX3dKGnxSNybBeJ|_zraY8&&+2p!ZKI>7_~z8WLRUTJF0?Xc!@p|v)C2M{fsCQd z@Tv98qGe0u0m03x3xktAxuuPg2h9aVtl8xr4qQq(6MEZC)2Nj#X~Sg~5@=$(bUi4- zD>Sxt6gm|Mp4@J>@RLyjKq%^UU&S_L-4veGw$vaPr&Sn z6uTu4%c~|;c^hg$PvV?o`41jel0d0xt{2h60M1Q>u&;j zcprU4EIuK8%eFZAA8==QD8c%0yP{m7N4_G&0nM_`Si3vd#_?*0JC#PE_Lg6l1Tp z0=W1Eue||oG^STHr2)Cy;j)jELOQmX|0<%pqRSSMxsOL(qOiA zgYd{L`tnrC{6Kk(Etgi3?7~xaSZ^h<{OQRP+7o{jKtDS@%N^RqeB9#RX3+@aMp;xc z-3X^AO5F6*LyGeBYrqLx72=*K=WbH(YQmI91bf-(O*{JD43>|srl)~LKD(91Eslt6 zEVJz(dZFAH`yI-7b7FV;v#J(;x5Xo$$i=ZULW0KWbxh?rM)Izm{LRO?;vk`|z9G{V z+5M+J7Rmt$bw`uHO%8hV$cTJK1Y^;?(mM0@7hn3f-nf+ZP3xeN;^2-|=echEyBr0m z$t9TYd`D>jb=*R=Ut|;_yD?s2lhV;dUGc4zxJH}0FlxQX@|x+yiJVycOeo~(jWL~* z4Zl&S_%pG!@dRXZcFeY;xmb6t1vZc#}4Eci8h!TySL_eUu+B0 zW*^Jxj7Y6%N^I8%4ZLrnr1IPbO-v})5k*bMlSYu#1L+0#mD`TKD#iB>!w%&EKGHK4 zN7v?j_|5ej2G6o=Kk_I3pir;`u#3vvx(mtiT@PI~Nq_%O3>whzZy40;=HD@>_rxt= z(V*_g!7(LFx+;aU*AuW;t+Mv=$G79`td$ppHvBH@rk`VJR@+@GrWTqij$Mbe@T%gN zC28x|`|@<3inVVHD5l)gS8JEM@>#>i$@cP@he_{PJGQVYC0cE!n*rMrZ{6bRW7puZ z@I!Qa%UAorzUxD@Qykf+%-a3_8wk4BF;5@`(wp|AM*~4uK}EVa-Pm3agjKI8uqKZ+ z%svu!)Gy0boD^{g6Ug(qj;U|+B<(O$555bw_8kgY5ibdWB8`n5`7#yo-ttRSax zr6sZMwk>po|BCnPki31o6vaGeo<^gn2;T@$h|zIkFUjty72KDqu-|db^ln0QW3|p; zq~B|s50JtrI>1+BZY?$xEWS^g-wLffJmS-NguZ|~Rl{t}pHv=^gNusnhF>E2lCE** zW@;!a#Y+b#Fwhgg{}mqpCM6N^bbKyb5W)5N>*n2QH(zv<@&M{P^aNh`Uo_n5+j)|w%vn=hcK?lZin#DwLiqbOc;3&~(4J`Sub!aOUDi#& zzY#}K=>He80{^xPEEGkgkT=K=0=Lp1$$z3}cUO+n{h z#*+d|p`;z2)gy^}kXo5ChPf|MJODO-{^M7eRvZk0(08v{EG4CBt zpgX1mo-Lw*=1*T!4P%wtq3hSf&hI(#K`qYs8!N{otvZ{zH(D=NTq;Yk@rwe@OQbRlD0 zyj=rbC=aW69W^?%%ZmipGSrK*o!&=$00zUwZ}B}hv)w*9sggkT@VL@9G5V88Q9KFY zaPxMCXf_^Azry^_t#sweY{0Bam2@s<>zAu8+Pl&Jki#QZt-Us^mH}0*3OF{%fkEyjKOtbAsB0K7 zlc?MPRm-$Iob&Kd%{R83PV3Ncl+M$Z;|>kOV);>mUhzCPI!zZ(eHLlC6|n~>ztwoV z4Bh_XHv6_s7pa%G;QGOCpdzR5Ihn6yMva%sx3LaxcOf%xi7Juk;; z(fAIFaYjr4Soz`(W1Sx9S?%*M;-cKx23Xtyx7uTK=otFJk{{@78FUDqeBH}wif^d_ z^~fH5>Fhq+3#8}1Ie#QmVKO~2 zS^tB`t^qqBo%s`D?re+1Ad~}4PkN(P->mZW4LpF=zjyo(Df3do@c8i&`eZSucSi_a zklDRsvkx;lU*V~>D-es;zOLY7be)9`=J|D^dih1I)IIv~1wGe>PC)9R7Bb}x#HIfTsXLS8> zi)<|t4(RAk&2VFe7tln1bLj`$mrX3OCL86;an)xeyy=_B`%BD>s<+!NM&6I)DlX=bkqHj?TQzVYj{6>O}SOX*HY&kDRt4`J0B-Sb`D&# z$^LCgdDK$yx+5I5>6FH1!@2HT%l9`}$^Q3Pss6DIk@$3@4$Lcflq-y~-0t9H`%p}_ zPIpRS;R9;|@T*UWhFU^DTT?w?Pn>}u!tOQ4#&)c)!IsB;oNeIVwIh^MkCHD*0Zlh* z%k?tD3Ac|7D>c{jDi%u)3=9*MSN6SLMbVYa;@Soi%S8pg&PR&l=chGX(VcW#eF3`? zvjM0lN0dZU%SvGR5BbesFFSbbu??aZ9TLS;Q4@W1vuf`|X79dO(4V$CrS|^Ro91eL z9tmc-_!)s#*aJI{JFwsS@TMHySg2^K$TC(v`u9#aSsX+xHJc9qNqfLECQo z&6l9rlXsu6#OiI|5@+-Gh(keWgi8N|U$|%w|Ld`5gL)`8l>=pTpl3eN_+Jj}u4|nO z``ym||LyTVk^=uM!TviR{-5melySNpPU4y%f0rz0>{^=-G)&DHDS;mO&%Zh-KS8|~ zpbVq$viiPL>=_p>DQR_6XK$_YaS3ABj%F#|w07*nEv@`%MV|8$D(jzA_KWRbRdi<8 ziVLbLOe*>-G|tq5r~efik(IZko;oA#MFT;av{U|%p)+h{Mvyn#h0m92SSa~Uw}{IS zNR0}AP9PNhBcORl55{zeJ27<8Lk10!&pW{o6=>|6UVX^IX3+3BFPrg4TmkiEY?Vnkc2k@!fucVm803%ha!w@ zKlg2|W-Db8l_z&#SnQ_W0!nqaatkb>M1(8dpdSSeIT#H%Qp`pCdS23{f%1mr>oQ8; zMb@5MdjS-;(|GHhtz!iV-}*Ux-XVW&9BaW==9JpEkjFC7eTGGb&gnC2ESTLpxtP3e z563>QF=ktln5Co{mh?XH;neSQ@u}e>x)dZ)^%H8!MOqKbviIG=yfuBAQ z1DEAefttP*4Pc?%Jj#?CpuaXIFpz=!wpN0S1~c^KENnNYKXqf>$&%7{m!0_;0-OCSd83$wgd`E<+H zXzd~5O9%^H4XsUi#`qc0eA?WvzUp(g$NM*xs$l8XUq1Y?=2FX%Y1Lmo z{Q7>aAKY0kd!(N?Fz<a3pG7w-^|?Vy9p-MSvZ}is{0a?P;J6hVIu&Vyvh|y zrunA9@^jm}FcorLsEy-TN;-g(SHCHOIP{E`A`G~3U#s+_;V@|j-?5XEyO z3c%;-^pY|AtS?4@=W)m(^;L4{I)V!3^nkt@=Tozkh6GEP9eqcH*JX~q$rjd&#o|cM}4My^D-xGA@<7hZ{ADJm&Uh0 zjF%!i@iZzBcL_HoT1)FQ0n*u;?D@fu8owBQ*Zz7M-h=jIzU#>w4rx)tcXz^(e@pJ; zkki%gI_G?@T=54mkZu(`!?=mOim5u`9fE7TxWcg_28@{sBr=&VTsGlrnPgdcm70bm z4jtbx25VX>qd6h#`&B6s(4Ms0soI6;%*dBaUmll>U-O)ts5+I)7~2{8=N>dwldtVR zUHzy7PwPo<@(&O2AH`g9+b5W z+HWfrui05pz-OanW_seKF7r9kGl38Nu{|H_Rt~gy z`78dq-AlU{F>pGhc9HWJ0lT-;cd0!=8K{RaIVv2Oojy#eUMSllRJxiY=^SXuJ-+D; z#x{~H-i(y*q$#5!NEb4jUQYR-a+>buySw^vFF%n}Gj&~f6rUm+vZUAmVZbsSj02YCRgsVC4*cS|gvlGIh;P2q#pQ3w)lu(%nEJ4|Z|T3G zZ{c4}{YH;ra?j#3h*IYZ_&fK@_&y(Oq-#$7)I}S#$|&jZ^mgFJI;63^+kf|uXldQE z=1ux{bN2+{6ahb2CWi>|zjq(@7CNUgZ7)tK1hE z`BLb9aJIXU*SFxyBJ(u^ufI*Xa37?Xi^b&3rw5P8Ywt|lq5Ky%u0gV84Zp~gk`hJ> zvQs2UltKtuk}PB2W~?P-OZ}o4rjn4QaI%ao#L%cA+1G4ivJ7HI*7tdaik9E?zUMvX zyyrUC`wz@D^PQPz?z!*#b3Y8sR*|mx#nP_`+7G={_my88!(b!n1IekCiR781++HLU zctpBQr90^=ra9~G2=H+_*`8lQv+QQHb`;+9vpA+Z4T@tG&!7XHe8M8VZ8ck_f{)B< zO{M^tnsav2Jv`R`7*p$(`lG!#?adXyrQej3E(zyDEs~~u+NZ8NHoBj?&0FdOTI}(= zilS=hC)ha;u+}})^YI|}d7wxNDKW2Vs9^-Zdolw8B+Z6B*3nDhe_lansRjXfT7lq) zsztF6)iVO?tE76kAFHIT@#%JOauJPhhUHTrKLjbX>^#Lx;@D6u7xuD)5^n6Qv!UmH z{)24iPrJX9%4r4aYh6sw^@#!vp64{&vtuOQI4De%PpP@=lFQD+!2R z+vxtvDd(Hm0RV;sjn*pGL3xWN=ILEKD~Q`Fu~m(lDgq1u{J*|=i3eySqsk~p%&d;z z*(dE(seBKV%8v1Lb6l>myJ5lt0`D&eP zTFO)j;aCXxxdWi=pZa@KbAt6B_|(Be{yQ9IdJ?#bG&G-dlgD*W4`sA-baZwcvAu^5 zNbX-nho(*vL9cYQvtQOi2gvi+tW>Hn)(a{(GkrsVsk-!?QS#RJGP$*4W_rh@0dX$m zGb$asK^RArn>0^J{JfIjm=!6FU6SJ|CP3x^oHXI%Fp&r7d4w18M)?t_tQ9#W{?5c# z$%`x{#zJHyT3X6|fk;2aDc5{rYxKfw8-^htOEPc{pTh#6RUwv*;JPu?*Y?PUJ<`PG z@bdR;a8HM)sqU%X;bjbJphh#{_#@(5re;Osg^syqps_wrm6Pc3$-+wo-ni}kNk=ig zDoY}8%wZq=Zcu_Fm#jsrtJ1Xs03l0F_GJRGOFs79wA6D_U(6#aZMHMfH?>DzFq7%h z%;V#Hyq4!HnPL^!7^$HsM$^&_>eZ>ZdKf@*i~GSE0o5z@2ffm%dkR|qdo2CVm6TMW z7|kCbUup9(ysvzLN-{;fZM(5R6*4woyPMJ<{) zmoUs7YpM8y6nBJy{E*~^RD<>@!f;(L3^y0|Jcc#4WNNja!)GZ4-k)fn9jHcLPbQ6_ zN0Si+FA?S?zPChJaf%%mW_6tqf zP6kdThf);gap}ylq3Dw_)rjs3JyzFFlezF1Y41(6}g|F)Mh9m_V0-!Oec%( zpBM*eexU4k_9p>b;Ub?aYYDtpW#7=I&dqcXE>1H}b~A}X?-nWr_C(Vm1w-(nZHNlx zGfY77&Bq$WsXwLwhK&GHqcET2PeZ-fzg8z zXO!v8Y@0PpP7GS>uDDXhx8V ziNAifYkc*XR%Z|F5+!ZMB|wlV=5Fyd=pb)9wIrG2IxXO)w$icWQ(}~<;dc;hCM!m1 z(C5~xL*K|aOkr@#xf(6kb()G=@~7W=-F#VB*(OYQq;uV>^9_McwliD1%nrHP$4bKQ zi07#wQT8PPqrR@HBt5b*n&n-X^meoa;H%}rWwAA<2e|0@J>3;BTEHyA#okZFzN{Hi z*6dJcaRnWZN6{T7m&o@GW2MI1ZyxUR1fzU&ELYX9ll(JfQnKyeh3Q;TY3A6l#fd1r zh}KXK2Rmv<#A4NsH!te8`1};X;i>*@0YP&n!cmne%;I`cQnBJ3R&xzw0;;x;cj!u1 z0z*`96wP&vyAA=E4$Cc;cXfv+-J5Lz(5p8;BG8OwJKAX3SwZZ!CLwoOh|Q`uSAV8O zKCs&vc8$JD?Q;d()~q4b;n5}Cf{V-^NI8kU*lP;Bd{Gsx z+9lge7Z3`DrKSQ4`MbWh+6!hY!yl}lU||LOvw$giphTebYk1E~t0}-@@y7s;p0Fo< zx={S6pT#U1ti}B8LQOi&$spF{t0wlCTF_?wWEOUkT+Ap3s7WS{RgYDj$@dA#g86|U zLS5UkkC(PLb%*jv;0uA{L+(-HM%R=!4!2HM8LpUoiI{q{Bt#g7-Yj5WxAI`9#@kcZhrvA8VWog=)PHO4dN<4>>*j z;tDS3`1Sm4s=?w?YS>)}Kh{MmP4QQfGl!h?OgdS4o+1<#NO@NT91{p99qSi^#fa@^ zJO+_q4f#5N@G4IC=Fb7X8XgGnF92g4^x~a-^jt-7OSRLBxc4`}0fhX0gP`kLDFr$F zj&hC33G@_9Id4?PkxNfq4-3}w)75m})D-A)m=!dF#Lo^~V0PF0pu zB8y`0?RztbHE`8jWIYsmDhPCDPwc@Z`-O+}zOb@I@($Q|#`TmCmwmbvnWFp{*%vmV z@&U0_Ll(J@5m2f&0k$;>W@hcQGH?uGldmM(ccf`W??|`C_3tZK|2<{-dwEuV4U-~U zcJBpoFZ!_t4UmYDodUF+q}9>49l!GMSPbwB@eRW#2D?`Lcx0FyO{Xzpe%pC zO2AWMmJNf&jUu)i)yH@NK>YLPtpy}oFRl_Z7_G8UQe`SQzV#d)P6&n6-NW(RT<|iP zC;$cCU*bz=zX-V>#Xs;7=s6DU8c^xqiEgS1cs+-6R}41zX`btUEj+Jvr4db|vk>Np zMZaxpZBoRdlM?R+#Q%;~QQ3{X;#gCAFV|m8ah-lUMnVh5mY7kW1*BSRbo?(pW14<^>$p_(JlHPoy!G{DX++LOQMb(EB2V^ zitTatc=^ph=TsQK1~K&yxOX+JPHw^N!VKUE>tNO+U5+`R)Xkly8CEu7)jCwVmLe?sJJes_nv2rYvhb=(Q@%7Xx<6TM)^OZxgm8SwJn}7=-Oj^ zw-rd~Mb$_T%SCSp38R}z3O17oh*@N2PCu^-prh_Pp>7$z+(g<`cH7;lW(_iv_BrBU)=!(hQxQPZ1tVUI%;oM&uU=a#xXQ13U1Iix!z;KE3_2eDs)+@5>!27LoYuXd%`B%eRxbfQI z2;jrLU~xa$ljf81V!{Mx=$(Dj{pT$>C65c=V;%OHAooE(k*jD}PBocnnmaW8S+ z>9uv2Ub0Px+uK{depuTk>%CR(u|ELln2NXT219F*@JfbU9Dd9;l#uV$ZSCK_d$b~z zXkusl<%&X8ht=h=JD(d;RdXGNT!T;!t$TZ=lxP(X@hZp53#)EpY6-CxBeWI1QIK0- zCB1Cze1_2IH2`5k$PAUkEPh6qFfD_5!3MRowSnL&*DIrm(}0`&tBjv- zf=-&mYxtdG(l7`J8~Exh|A^hkf^;E(R~pQ?%$TYyMK`-8sNqL=p4{FieSfs5^SVEZ zI|Eiruikp6-biG9kF;9cl6p>kCZ8;1Y zgTkoqaf$NK=J@xKY!?~)7)%?l_!h(-ctB13v+ClKVEl+y7aO6>8rQ&&e8}$C#vfk- z|B9POt8?J|7GGQLq1`kaG5c>pd=aHM{a)K1zv0=Rbj)#eUG0?<6q{+XDvaB(Z2v29Y3 zfFwtvJr;MWvydb#Cu8Pxk=rRJ63n!Aw<{YcSt75N*A{)@f3nry`K5=?KKi!#XO$ho zw{2WBkdBuATktJM1cz?dw|jjW?*yjG-dr3?`@d`_ z+-@3A?5qiiN^$UyIcLW19(>r!s9I_+kBgLbiMi5f@WjLM9nxVf`cl$_G?45J#OgCNHceeg)UpT_Bq}r*N6n&!$Ub! z$tMl3tMY=n!z zBwGBkhD`SymmiO9KB?JlpkU`krQv8QmL%i1`_9nW^6DzMVebETN&oq~Q-7Bm`g_g# zZ?L5GpZ1FW$7XvnFm^i$U9L)Crrwr`P8G!gIQ7(bICYkEl`4!sR^2hX3 UQo~w+TbI#js-IEIK4u>DU$fk@_5c6? literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model.png new file mode 100644 index 0000000000000000000000000000000000000000..26c25e6cda3fa3db1702bed6712138a5c2b19692 GIT binary patch literal 7084 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 z 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 Wo~XJ^!)6Scf>abW72e)55BxtnQJb6q literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_unit__to_node_relationships.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_unit__to_node_relationships.png new file mode 100644 index 0000000000000000000000000000000000000000..dc91ea687cc2f76c8d9efc7ee7c505dcf395941e GIT binary patch literal 19508 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%0A$7D!g1EVLz#_uj(rI4_v-xgxO>PL;^rtoT;d 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 Date: Fri, 22 Sep 2023 11:28:13 +0200 Subject: [PATCH 25/33] add tutorial file with general structure --- docs/src/tutorial/reserves.md | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/src/tutorial/reserves.md diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md new file mode 100644 index 0000000000..02beac7ad6 --- /dev/null +++ b/docs/src/tutorial/reserves.md @@ -0,0 +1,41 @@ +# Reserve definition tutorial + +This tutorial provides a step-by-step guide to setup a simple energy system including reserve requierements on Spine Toolbox. + +## Introduction + +To get the most out of this tutorial, we suggest first completing the Simple System tutorial, which can be found [here](https://spine-tools.github.io/SpineOpt.jl/latest/tutorial/simple_system/). + +## Guide + +### Entering input data + +#### Importing the SpineOpt database template + +TBD + +#### Creating objects + +TBD + +#### Establishing relationships + +TBD + +#### Specifying object parameter values + +TBD + +#### Specifying relationship parameter values + +TBD + +When you're ready, commit all changes to the database. + +### Executing the workflow + +TBD + +### Examining the results + +TBD From e3ac5a449ecfae9eb6d2b0c6d78331aee1d665bb Mon Sep 17 00:00:00 2001 From: datejada Date: Tue, 26 Sep 2023 16:18:17 +0200 Subject: [PATCH 26/33] First changes in the reserve definition steps in the tutorial --- docs/src/tutorial/reserves.md | 37 +++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 02beac7ad6..95e0d43964 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -1,30 +1,51 @@ # Reserve definition tutorial -This tutorial provides a step-by-step guide to setup a simple energy system including reserve requierements on Spine Toolbox. +This tutorial provides a step-by-step guide to include reserve requirements in a simple energy system with Spine Toolbox for SpineOpt. ## Introduction -To get the most out of this tutorial, we suggest first completing the Simple System tutorial, which can be found [here](https://spine-tools.github.io/SpineOpt.jl/latest/tutorial/simple_system/). +Welcome to our tutorial, where we will walk you through the process of adding a new reserve node in SpineOpt using Spine Toolbox. To get the most out of this tutorial, we suggest first completing the Simple System tutorial, which can be found [here](https://spine-tools.github.io/SpineOpt.jl/latest/tutorial/simple_system/). + +### Model assumptions + +- The reserve node has a requirement of 20MW for upwards reserve +- Power plants 'a' and 'b' can both provide reserve to this node + +![image](../figs_reserves/aaa.png) ## Guide ### Entering input data -#### Importing the SpineOpt database template - -TBD +In this tutorial, you will learn how to add a new reserve node to the Simple System. To begin, please launch the Spine Toolbox and select **File** and then **Open Project** or use the keyboard shortcut **Alt + O** to open the desired project. Afterwards, locate the folder that you saved in the Simple System tutorial and click *Ok*. This will prompt the Simple System workflow to appear in the *Design View* section for you to start working on. #### Creating objects -TBD +- Always in the Spine DB editor, locate the *Object tree* (typically at the top-left). Expand the [root] element if not expanded. +- Right click on the [node] class, and select *Add objects* from the context menu. The *Add objects* dialog will pop up. +- Enter the names for the new reseve node as seen in the image below, then press *Ok*. This will create a new object of class *node*, called *upward\_reserve\_node*. + +![image](../figs_reserves/aaa.png) #### Establishing relationships -TBD +- Always in the Spine DB editor, locate the *Relationship tree* (typically at the bottom-left). Expand the *root* element if not expanded. +- Right click on the *unit\_\_to_node* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. +- Select the names of the two units and their **receiving** nodes, as seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into the *upward\_reserve\_node*. + +![image](../figs_reserves/aaa.png) #### Specifying object parameter values -TBD +- Back to *Object tree*, expand the *node* class and select *upward\_reserve\_node*. +- Locate the *Object parameter* table (typically at the top-center). +- In the *Object parameter* table (typically at the top-center), select the following parameter as seen in the image below: + - *demand* parameter and the *Base* alternative, and enter the value *20*. This will establish that there's a demand of '20' at the reverse node. + - *is_reserve_node* parameter and the *Base* alternative, and enter the value *True*. This will establish that it is a reverse node. + - *upward_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. + - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve provision must be greater or equal than the reserve demand. + +![image](../figs_reserves/aaa.png) #### Specifying relationship parameter values From d1ad67d3bc371c56b18e78d8ca7e2ce52b4319dc Mon Sep 17 00:00:00 2001 From: datejada Date: Fri, 29 Sep 2023 18:01:27 +0200 Subject: [PATCH 27/33] Second set of changes to the reserve tutorial --- docs/src/tutorial/reserves.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 95e0d43964..2bc51dd0ea 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -27,6 +27,13 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys ![image](../figs_reserves/aaa.png) +- Right click on the *node* class, and select *Add object group* from the context menu. The *Add object group* dialog will pop up. In the *Group name* field write *upward\_reserve\_group* to refer to this group. Then, add as a members of the group the nodes *electricity\_node* and *upward\_reserve\_node*, as shown in the image below; then press *Ok*. + +!!! note +In SpineOpt, groups of nodes allow the user to create constraints that involve variables from its members. Later in this tutorial, the group named *upward\_reserve\_group* will help to link the flow variables for electricity production and reserve provision. + +![image](../figs_reserves/aaa.png) + #### Establishing relationships - Always in the Spine DB editor, locate the *Relationship tree* (typically at the bottom-left). Expand the *root* element if not expanded. @@ -35,6 +42,12 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys ![image](../figs_reserves/aaa.png) +- Right click on the *report\_\_output* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. + +- Enter *report1* under *report*, and *variable\_om\_costs* under *output*. Repete the same procedure in the second line to add the *res\_proc\_costs* under *output* as seen in the image below; then press *Ok*. This will write the total *vom\_cost* and *procurement reserve cost* values in the objective function to the output database as a part of *report1*. + +![image](../figs_reserves/aaa.png) + #### Specifying object parameter values - Back to *Object tree*, expand the *node* class and select *upward\_reserve\_node*. @@ -49,7 +62,20 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys #### Specifying relationship parameter values -TBD +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_a | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *unit\_capacity* parameter and the *Base* alternative, and enter the value *100* as seen in the image below. This will set the capacity to provide reserve for *power\_plant\_a*. + +!!! note +The value is equal to the unit capacity defined for the electricity node. However, the value can be lower if the unit cannot provide reserves with its total capacity. + +![image](../figs_reserves/aaa.png) + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *unit\_capacity* parameter and the *Base* alternative, and enter the value *200* as seen in the image below. This will set the capacity to provide reserve for *power\_plant\_b*. + +![image](../figs_reserves/aaa.png) When you're ready, commit all changes to the database. From 15fbc91874997a0c9fadaab75d39574c54e570b3 Mon Sep 17 00:00:00 2001 From: datejada Date: Fri, 29 Sep 2023 19:52:45 +0200 Subject: [PATCH 28/33] Trird set of changes to the reserve tutorial --- docs/src/tutorial/reserves.md | 79 ++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 2bc51dd0ea..9c316b98b8 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -30,7 +30,7 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys - Right click on the *node* class, and select *Add object group* from the context menu. The *Add object group* dialog will pop up. In the *Group name* field write *upward\_reserve\_group* to refer to this group. Then, add as a members of the group the nodes *electricity\_node* and *upward\_reserve\_node*, as shown in the image below; then press *Ok*. !!! note -In SpineOpt, groups of nodes allow the user to create constraints that involve variables from its members. Later in this tutorial, the group named *upward\_reserve\_group* will help to link the flow variables for electricity production and reserve provision. +In SpineOpt, groups of nodes allow the user to create constraints that involve variables from its members. Later in this tutorial, the group named *upward\_reserve\_group* will help to link the flow variables for electricity production and reserve procurement. ![image](../figs_reserves/aaa.png) @@ -38,7 +38,7 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - Always in the Spine DB editor, locate the *Relationship tree* (typically at the bottom-left). Expand the *root* element if not expanded. - Right click on the *unit\_\_to_node* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. -- Select the names of the two units and their **receiving** nodes, as seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into the *upward\_reserve\_node*. +- Select the names of the two units and their **receiving** nodes, as seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into both the *upward\_reserve\_node* and the *upward\_reserve\_group*. ![image](../figs_reserves/aaa.png) @@ -56,7 +56,13 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - *demand* parameter and the *Base* alternative, and enter the value *20*. This will establish that there's a demand of '20' at the reverse node. - *is_reserve_node* parameter and the *Base* alternative, and enter the value *True*. This will establish that it is a reverse node. - *upward_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. - - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve provision must be greater or equal than the reserve demand. + - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve procurement must be greater or equal than the reserve demand. + +![image](../figs_reserves/aaa.png) + +- Select *upward\_reserve\_group* in the *Object tree*. + +- In the *Object parameter* table, select the *balance\_type* parameter and the *Base* alternative, and enter the value *balance\_type\_none* as seen in the image below. This will establish that there is no need create an extra balance between the members of the group. ![image](../figs_reserves/aaa.png) @@ -77,12 +83,75 @@ The value is equal to the unit capacity defined for the electricity node. Howeve ![image](../figs_reserves/aaa.png) +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_a | upward\_reserve\_group*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the following parameter as seen in the image below: + - *unit\_capacity* parameter and the *Base* alternative, and enter the value *100*. This will set the total capacity for *power\_plant\_a* in the group. + - *ramp\_up\_limit* parameter and the *Base* alternative, and enter the value *1*. This will set the ramping up capacity to 100% of the unit capacity for *power\_plant\_a*. + +!!! note +The *ramp\_up\_limit* parameter triggers the [Splitting unit flows into ramps]@(ref) constraint, which links the unit's flow and reserve variables. + +![image](../figs_reserves/aaa.png) + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_group*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the following parameter as seen in the image below: + - *unit\_capacity* parameter and the *Base* alternative, and enter the value *200*. This will set the total capacity for *power\_plant\_b* in the group. + - *ramp\_up\_limit* parameter and the *Base* alternative, and enter the value *1*. This will set the ramping up capacity to 100% of the unit capacity for *power\_plant\_b*. + When you're ready, commit all changes to the database. ### Executing the workflow -TBD +- Go back to Spine Toolbox's main window, and hit the **Execute project** button ![image](../figs_simple_system/play-circle.png) from the tool bar. You should see 'Executing All Directed Acyclic Graphs' printed in the *Event log* (at the bottom left by default). + +- Select the 'Run SpineOpt' Tool. You should see the output from SpineOpt in the *Julia Console* after clicking the *object activity control*. ### Examining the results -TBD +- Select the output data store and open the Spine DB editor. You can already inspect the fields in the displayed tables or use a pivot table. + +- For the pivot table, press **Alt + F** for the shortcut to the hamburger menu, and select **Pivot -> Index**. + +- Select *report\_\_unit\_\_node\_\_direction\_\_stochastic\_scenario* under **Relationship tree**, and the first cell under **alternative** in the *Frozen table*. + +- Under alternative in the Frozen table, you can choose results from different runs. Pick the run you want to view. If the workflow has been run several times, the most recent run will usually be found at the bottom. + +- The *Pivot table* will be populated with results from the SpineOpt run. It will look something like the image below. + +![image](../figs_reserves/aaa.png) + +As anticipated, the *power\_plant\_b* is supplying the necessary reserve due to its surplus capacity, while *power\_plant\_a* is operating at full capacity. Additionally, in this model, we have not allocated a cost for reserve procurement. One way to double-check it is by selecting *report\_\_model* under **Relationship tree** and look at the costs the *Pivot table*, see image below. + +![image](../figs_reserves/aaa.png) + +So, is it possible to assign costs to this reserve procurement in SpineOpt? Yes, it is indeed possible. + +#### Specifying a reserve procurement cost value + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_a | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *reserve\_procurement\_cost* parameter and the *Base* alternative, and enter the value *5* as seen in the image below. This will set the cost of providing reserve for *power\_plant\_a*. + +![image](../figs_reserves/aaa.png) + +- In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_node*. + +- In the *Relationship parameter* table (typically at the bottom-center), select the *reserve\_procurement\_cost* parameter and the *Base* alternative, and enter the value *35* as seen in the image below. This will set the cost of providing reserve for *power\_plant\_b*. + +![image](../figs_reserves/aaa.png) + +**Don't forget to commit the new changes to the database!** + +#### Executing the worflow and examining the results again + +- Go back to Spine Toolbox's main window, and hit again the **Execute project** button as before. + +- Select the output data store and open the Spine DB editor. You can inspect results as before, which should look like the image below. + +![image](../figs_reserves/aaa.png) + +Since the cost of reserve procurement is way cheaper in *power\_plant\_a* than in *power\_plant\_b*, then the optimal solution is to reduce the production of electricity in *power\_plant\_a* to provide reserve with this unit rather than *power\_plant\_b* as before. By looking at the total costs, we can see that the reserve procurement costs are no longer zero. + +![image](../figs_reserves/aaa.png) From 2ae6eb5b6ab79125545dba70ac30f4421a821b84 Mon Sep 17 00:00:00 2001 From: datejada Date: Mon, 2 Oct 2023 09:33:00 +0200 Subject: [PATCH 29/33] Add png files and links to them in the tutorial --- ...s_tutorial_power_plant_a_ramp_up_limit.png | Bin 0 -> 9333 bytes ...ial_power_plant_a_res_procurement_cost.png | Bin 0 -> 9688 bytes ...utorial_power_plant_a_reserve_capacity.png | Bin 0 -> 7127 bytes ...s_tutorial_power_plant_b_ramp_up_limit.png | Bin 0 -> 9446 bytes ...ial_power_plant_b_res_procurement_cost.png | Bin 0 -> 9781 bytes ...utorial_power_plant_b_reserve_capacity.png | Bin 0 -> 7230 bytes ..._tutorial_report__output_relationships.png | Bin 0 -> 13277 bytes .../reserves_tutorial_reserve_group.png | Bin 0 -> 10669 bytes ...rves_tutorial_reserve_group_parameters.png | Bin 0 -> 5754 bytes .../reserves_tutorial_reserve_node.png | Bin 0 -> 8701 bytes ...erves_tutorial_reserve_node_parameters.png | Bin 0 -> 10698 bytes .../reserves_tutorial_results_pivot_table.png | Bin 0 -> 27520 bytes ...orial_results_pivot_table_reserve_cost.png | Bin 0 -> 27930 bytes ...eserves_tutorial_results_report__model.png | Bin 0 -> 7084 bytes ...ial_results_report__model_reserve_cost.png | Bin 0 -> 7620 bytes .../reserves_tutorial_schematic.png | Bin 0 -> 27664 bytes ...s_tutorial_unit__to_node_relationships.png | Bin 0 -> 19508 bytes docs/src/tutorial/reserves.md | 34 +++++++++--------- 18 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_res_procurement_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_report__output_relationships.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group_parameters.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node_parameters.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model_reserve_cost.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_schematic.png create mode 100644 docs/src/tutorial/figs_reserves/reserves_tutorial_unit__to_node_relationships.png diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png new file mode 100644 index 0000000000000000000000000000000000000000..2990dd5727585107dea592476711d4e212df0409 GIT binary patch literal 9333 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 Fe*gzHDEHbzI~;M$95bK?VTUF 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png new file mode 100644 index 0000000000000000000000000000000000000000..fb4c731b39f00c806dffde08378fc59d91e47224 GIT binary patch literal 7127 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 Yy+8~PPY1kW?z^$*>)g`DLhe8PUwB}1o&W#< literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png new file mode 100644 index 0000000000000000000000000000000000000000..1955d05672edb1a661a8a42bed2f25b9163452a3 GIT binary patch literal 9446 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png new file mode 100644 index 0000000000000000000000000000000000000000..a821af444911163bb6725e4468f212208f57b453 GIT binary patch literal 9781 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png new file mode 100644 index 0000000000000000000000000000000000000000..be405fcd102f57669b417b7dd6eb9d7eb9ec9cf5 GIT binary patch literal 7230 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_report__output_relationships.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_report__output_relationships.png new file mode 100644 index 0000000000000000000000000000000000000000..0343307405281427df1a56d614f3320bbf5786a8 GIT binary patch literal 13277 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_group.png new file mode 100644 index 0000000000000000000000000000000000000000..83cf7d03fb3e6175f0fd32a810ac37c24d39b8a8 GIT binary patch literal 10669 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⪼3ipkuWJP0pa;KcAZEk&hG$*b!?kv)$? zos`|0se49^ zZ-9}lvYES6Cqb80_N@r-vhU(+c_OO*WOMm~x+n~a{ThR`PnSAr>c{t7@xe(^{iw}l zM$Dy?_(;@iNWv@XL&YY0c-%?}WGu|b-(2bH3DS^u=IhifuvAt9FY0ONUpDs*pE}wh z>N~?F0&-vueF{OW~|L zl9wOPzG~ppY(Hx6hdMzl>~+%6iFm^R_)N-=?R5~0UWS?73}P9M>)rn46ca{VxMyl( zDci%a+4<^mp9sZGMPFE)jrQ7)#Qu;bmYr|8f}s4&dHum}7nnhL+vvok>D{{;N^Y9V zvpjqk2VAUql53dZGh~zVr+IcAU%zJA50hEAU?rbF;@1?x39g$P$bw0&m6yoa1_x*v zhcTAUzc>GL=XhqT*q!TYBYx39TFsQ{hcZfJ(A8}gXd!Z&)jt|CJ`b=|6$CxT=K9Fp zDVPh&ejan*omj>?goyCLkd zkF5R-7`*;he;eih5KktII7KE;K4Yk`!`ADX$zO46FnH(lf807hvF*q_N*Rs(xeGFq z)gZ!JerhIVk@aaNu6zBdF+ha&1~PYr?Hc;H74N}ZbM3&KVd#VlWv*%CFq8an>C82% zT1LqjY|*1T6q5HmHt+>dc&AJ6R2o6?TTGRDYOXq%Rp2#}-5A=-bl<#JIQ81r8uQET zQ;Kw)CJI~HN7Uhkp*XUe0oB?BfEuX-J~!TR#oL=&j|aJejC}#@M{-9aue1 z*Mt0+u!&szny^0OmH}_OtH6nKqgmiINbuQ*U$vjTBPhBT?Uwz;vr3+x>xfCu?c}C$ zA5o*Hcz1%!H-R*CVC#rQz?mlPs?O28Qop41#2tMrRx2Xh2rY(vfq~Y^)wR;{ktOnj z!JwhC=W6s~bK<*S@maANfFRvtbY@-WKD;SQk{?RkBMPNmVcK=Zd#(o-BQQb__VpI% zFhid>WaD+z)I2G@UKI>4)2y023^#aaZaqA52M$#u?7OACXnsYfdDYmL5n+rtw1>DK z20YX~swSkX`hB*`BRZEge2&k`z~&deYUlYtT1firx4y8?DxTU~6o$UD#B&vTpVovi z*W*C5p+?86?a8AB_nv!P3~2w>aeT*g9o~jS@nuaAS@hBDmUBQcqJSh;13ApEo$y`& zba2a_8XknU&G;*OtH7GHh=RS;kd`C%Y9R+)a)Dsbd+yp=q zrcd90=(0xo00Hk{B8gCnR;jI$rW^fw5Yp?o3p&CN>iiYD-~Ja^Aj`;l_gY}d`tpb8 za6(dz`kA%lmhSa_3yeZ_>2v2DxSU%F#D`xi8ULUG{N@me^v6E9M;*5pE4iZxsSlu1 z)a7>anASKO+LTw%Z2Q{CCOL^hZ5O}*Y^@Psn`W8Kpj-inkd8qlcKqW@!kq?kR)3he zPDePHlVutCMfs~GF9qtyTjFfJW4pf|u{ybMTbr!kK5CKae@IO1_y2ehT|(XO{x2Us z-Y-tV=xmiyPAe&ivSrN@2luQi0CqA3JB;XYgJHtAYdN0Aod@R0Y^EH s-EF<-b?a`1p$$%(<(1%@)VIy0*KBoK8l(7*U2bp~8<^{t>N-UI2PMBeHUIzs literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node_parameters.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_reserve_node_parameters.png new file mode 100644 index 0000000000000000000000000000000000000000..e37a307f3969f421e0db207600df0c340f469933 GIT binary patch literal 10698 zcmb`Nc_38n|MwL_%Gg3-h6*hr$=V=YQm6Za_hD)l{+f3WluD= z$vUEJgTY`hma)$m!!xS;zQ29%=lTAAzvp@Wm^o+8T-Q0*bGBPySem_500u8mjxI~lrLnNwfS?-eTG7eHE^?#$Z!Qmk26mC;R<>kOv8`$gR2m6iJuh-*S9M-?cIHlN*&cR08rj9#o?kzTUB-bzJ~^Bg z+qdVjuNy!3`wq5BjT^Xg1nV#)z7@{3Q)h@B%f3@}ei22s-`)`Y{_kna@&pci$ksCG zN9jU^{V1-TYNsvN_h8v~cEs|69*;cQ+1c0gQJ4DTQj}pS_|I!Xqfq2>sC{@&PL8vE z4YO$`M6yOZSQ6G&z>B3Cl5z5R1r!BIB0#j;$r)L4vfps|Gv4nV3lDH zC)u^Qh3=iBe>RE~QG7mT2(f9q`T?FEDy&GsbUHD*l1BI6sMh(IzW4AP0S=%m=)7&+ z>ReSMB7Ns@nnX2mBkqHKTCpyef=usfBA!(4ZI=x?(1Ky_PKyd~-YSI0;GZ($T~c^S z$nW<^v+U)_7j(9*DBpucfyBi%G@skn7fa1FT)ltbRB@1;s#|bp!9K1a5miw;iNyd%S#s@Z5W>!a2e{=Io7buM{duJKqlc-TyEK7Q z-R#Ps{JhwWy-?xbzUaOSyINfN817|kaSM8W_Hjn^hT~R}lkO01^OfJU-8VEpxFz$; z#qC$8uV*(HuN~)>`PQq6&C2LcJtg9}Ga@L>e%s=}fC^Ip#L?iI%A9|`Ld+XPM~x*^ z)w1%K$Rwwkmz?Kexbd}eDR@_37gv=W#vNa@b}ErPdEomqL$aPj8eNTNtT4O2*VgE8 z7~fUqq6s*ye{?2{TZpfDg}E6x?T~RWo{u@cFhzlPir0m$E@Z;8MiwCl5YP0oSE7wj zxMXost3|Ook)-@8r~+V2ZNop_3X=YQTQ|zBu=*EwKMdhG3~0TUgpk4V&rImzIUebx z#UQI`5xws#sE0$#ja1bp;m>h3HOQDT10GS=qL7eUp#!O$W_QIIR3^9dSbk&K*unI$ zA`woEOacw8S=%iE!gC!El%X;n8R7Y+6qW z-nR3poS$5yG*xDe&;_)I6*V&332CKJVS#~0G+MSb{pg!MFnv&Q}T zs;EWJYP3S)jM@ih^mS*LI?}Lp01tX|Xy58Sh6R!$y{wue7Aw43=U}SX#%)y~Lzh$jpd> zNgEU9nv*(O?FR5um>I2 z6R1cN0@a|gx%XX-MYO1x=siT!Z`)lMrOSObh0cr2uy73}!z*~ffT^+N)WfODK)`Br zd{y1pZ@lqjn}nSuHID0sqxV01qiF(sgRcCxb3{j+$jh=e|Eump7*t_9b+jOmM&55V@oVZN)Fl; za%btBmc?g+C7A*7p1|YCh3A+WnW2vO$nJe$#gg#lH(Uu2R z(xxhxm1F)OpB=mR?HXt!fN3*jAbNa~SD$#YHkc7yOhrA7{%$(+FNxy8vq#pP4oDMx|NxxqO;XxNJrS1 z&Ei&i2*RsU(YaBhTf0NsS}YMCmNi8*w)_3A9(78ru<|tI^;iR0A@SxgC&|Qp+#7{U zN$&E^vX3zyGp;h#bq#K=v^=?V(Mn@jJVXli0&Gze;$194xZ`KGiQ=4-IJ-IVB z+cx{7l;kG_;#$sxzbmw*b~;mI+U1PpyYZUIaNA3Hmq7x-A)!OosNIewmv?1vlw3V# z*#i~mQD26Ls^OCtpYX;y@JtH*rZ~?DtfH-KGQ`luvE})ssMZw9^%`oBQ6YV$;mkVL zzN79|(~VQJDqGqQL89Qbs^3!&LtWd99JSX!`+qS!4w85vFMiPemaKgjZQbfUOdfX@ z7s(G%&fG*OWj@h<>laUUc1gjUMV|l~!F;QpPS~lnC$A~}j)TAQnx>N~5DF3o+h1XM zFAiWyneFY2uy$Lea6~L~RYIoFlo8Ag|XQp_JYUY z?+dy3!OTbX-^oKmVA<#Q{LfIs%bgMXY3!WBU(5?T4&S1Y0G5x}7DBcOT!IpSzu1Qw zJAgOh&S={I@9;YK%Qee*GJ0#nGi`FWi)J@-f&sH$;lIGm6GfhYTF*Y!+E&^08e;#D z>iDmK9n(jVb13INY>}zT9A*c8tqR})viJ}5`USXsvhaJG;u*aZ>LxWHdozdy+kMans{O?J^-g-uK@PJs+!+^HI$#fLa^XI`c%F&?9(A}Fx2$Rt z3NKnKo>mdO92j(bFVJx-D=#G6-tL>P3lVQRp0{IMk!?k-GbAmHdfoZO5PrQx0QjM_}LI}&sLW*T^ zBi>PSn`aU(zvg%}))*_I6sD<&bV?p*+|nbEDefoMy;3ykZZ za>7h~JYw;Fn=NjzNdK2el zra4`*wOAp7?N%bxS}fDC$qo;Zr&K~W~z~d{U3~Ot+mPAc=?Y4PsEx}UPaRN z6L9hJ8wp6htHdf#HJTj}Fxvsa{V1dUMmBPMOq}`3{bG6rw4N4ydDb@bL6JF8 zzUE%Em`-KfYm*CF3&&z#hWWiUQNU}d6&7*=tj)BE%V{m8haso3HEe`b%Vl*1xHFh> zwPG64$|NC9fRMt;ZOM%0;OyWFROiw7nP(#!UE-3SA9ym7!1>HDh0fsocOrYH{dx+F z&y?y44amhTwO+Zc+gBZ&np~5^Y~ZXDeKNWr5y)qryb%|L2P#U<6HaUESY_#<-5W;t=~sSf8v{`(ksJ`bMby1l$y7~;3$w= zQMqb7rsP5q7J85j6t^_=;mw!|spCl{N~a!%E4f)BK9-xq#c10_L^6wI(y| zmJGMJP(HfLsiZgd9JX1mXyWc5yX7Fx4?d?CVATh>fb7nw!x!Dh zsJr(KjO6iy%^9&ld1-8ahRzRmHm{J-@Z{4eBZ22<(8ngtX=p!5Il)PXp5?Nn5)-Eu?~9V#Oxwr?@146tcAl?%)FcA--l~&m zf-hD3*CyHM zk3}D~TuMHt^VCX})vD6_efZ8wDM_i&N5fk{Z%lGU5 zm4c0E4h+kz`M1IzLSU7x{dkHm99hFxaBB#g7uje?{LPM1{!-_OWX)&aLyYp#C7(lH zNmBtQI&f~rL^L5X#C^Nb;NXtRN`J0(dP3!WdhJMH>d5FtXwW@)E;}}UA1ddXwgL6w z&9idw;)vkdbUz*bPpXCUYZoVJ!@`{Sh2D@^HI3BSh0&m?&F+0DITl*7Sh_7XoDyN+51MDGoV?#Tg7pM2fCDuzb{32lov$nI?&BA{f`Tv&4B(KDpXcM6EsH-+-HPB<5N!- zi76JKuiIc%Suk!=51|F{uMLKtP<%(^#4c-ZF69jmSfZL}gpAB&cu@=o1~&8G0E`d| zFiUI?^rU5^bS@l}pKb~@=Q^^C1*s0o#jG32A%Jlk%c+$}Rm>8m^b0bw9#tBTj<}6D zq=NQ=g70p^PSirIdN|`g%`AEHl9VSo%u?RV+y%l-r!-893YX3^S_WPxT?u*c!2}OP z#4xG!RUP-*0AQgei1!wbe0c*F;(;Y?z6y?y*2!{^UTdsCy*p2xjk&#kZy{;?#K{7y z+V?12ZP7Ko@U~5Smt5J(#bec@N-c_H^5}{AV99(usr0fWg7opI3$8;1Q_UNc8uXJoavrwSD=CO)+A>;N z;?tIcF};&ZU!p)NTNmU91+1y3w^O0JQ zez0*x-ljiXc0GAb02?1>_SPIlz6A9tnUjT&IZhAQPwgHe58QKn>gCG3;`rjX#Lk^& z3%z*xVoj;Ybt7X7xY0Kv!?v;o_D&l-MdWcuscoxa8Obvb6B2 zxY8*A9!ZME zJFdMWN8ax>J-a@;k?mTJaM3vSAi9a{8`#zr47hWRN~1+9iD=x6uztdPTY*wx4U=}% zh@*xXRSVL-VJi*KUh4CrA! z!5^LO$*qr*6b#iqc7>U3q9VYz(&;w@I>l?&@EuT*pr3$pd?1!8Uc2Id%frpyz-skK zMu6}gNV>TF=9i`L#e*=EVH?&Ikw}v>w$gBXOv)FV&mV`q4nmYW`VZ?;1fn&ru1tf(2 zujNv6@1>{d+a(K+hT4B=NRbH(QST1yBc`wZ6H;`~>3?8qhiQBMK{QpYIf+QEwnLN2 z6zaWil5HuLh?TisE_xZ|+bq=}KU0LEvUvO6@{6QywJM8^{qz1#hq~8C{l{cCd$6A-W8F_|`$^ekE?YN6;ZH4l zz8VRDKhWic@3L5dB7>vM zaW4=jMhM&7?eD5ftp?PBbIVl|o-1vYkzHl&JdR*VA_TgNeEe0O-HlO_r=0fs+HE$R zDUD)=mEn7PZ_E#=@&eVi=@R!RuHw|L3##XoG>5Y{^`4#@zF%L_`7Jviz&jt`#AsCA z+oPt-q_^AXq#Dw319xj19I*q<`WGT~Vp8<0)PQHVG=3)*$x~1?M_+nb*y6#m5l2!X zZ6>MhTY!B4fg{yjS!CZ^{~B&@hY5iN^Uby|p0lpPI&wEM-y;by`)EwyMacyOp8K2Y zHK+0-PE3$p;GN=^3v`WDbs%%_tVQ7c!Y99t9OPNN?!8ng07+_V@hw#QA9Ktk)^qqx zhi6*87PDt2$|s}>H;l*;uhcwSVs>aEu~Op#u?xRz#=88J=cb3mTk&5oHvDN!+WBiF zLp2)DQbi!SL^-8JQfzO+m<&mP5hKlYa^H@#e0DX>0Y4$|;>i6uMW09WFi$sqN$5efEuV9g#DVd~cdB>w7=K(t zHgD~tg`eqOFUf?fFX?wv{rR-eZ;YAL$G;Ue@kZ>lz0Z)^hHC}A)|jfCyKWq_aqQBQ z;4>k;B?lv2NE#6`Iwr62$GG=01*;aCEqxRtqr}+tpB~>~TO#?cv#{l8N{2Po@d-+9 z)+mWw_4+zh9{ES(@PM&)mtZikbyi;yia?r2rxw~joh^KRhVXp)YW0rV@@Ch1rC&X$ z$ZQJ>8;p2Egu{h9Q;XKR4@)YLMxE!B1{6{GUzC?9!?mTU&nDcDQIIt7Ra>C4L}(bJ zr`UiBw}ah^P=b)#1PY_{{RYtfhtc3Zwq zrq74DOy_IVycFENm}!FW4A##Wo3+jvhS7?Yb_8Rvu0?uOH|vLGtQ`xhi~{<|iOV!3^*1*3Ak z_m)%yoyj_LK@R@PzbG)4sG9V5=dAa4)%sQDElOh{NNY_FeEqM6BS;XOtxE;}T9^gN zuQWAqLGLJ?u33HCm+QT(2q-wqkDd5D*usx?*n)-SY^7k3m)zF7`NUoJ+YC!7xF2fm z)3e?-zbzES6NMK4IQM4s9UsfLlL-82{lN}-IqoJxbA|vMh5NZPKE`R(s2O0F8LJ?M zNrx;Whz8W$KKpp&a=3oMH7WQ*>~AAjgf@^>FyQHkz@$#ghAVC2rme*qbM`{V45rL3 ze7QRS9-xuaYe7!5*$xc8Q&47e&TpYr!_I%*=Jydtrk12Jw~0vRFn@rCL@_i`JyEIo zM%}d^P>Zy9TFHuo0aZicytV)|97uAjsHo~U8DRLrv@6yId({)DGV4Jtd>Ba3N!se_ znY0GnuBGHTq0g?@p$9vzKbZFhA;A9>(Lvi^NUV~QAv8~ zqB=#!b50>I=9X7geh(^dM`y4syd8ywIPyw={+ZxYRWk_8`Ldd!Di9vEg#HBx@o+r zZNQ_8$bwQ)>yq(nG5sH_W1ba%Z=l35uGk4 zsHZH*Em9lf(%on%9=M}>mh>^8YL@ER!}LQ|+SGl72xfFi+s#{m6doMOM%q@ZN(2h& zoa%BkMD|}UU>=@2q;;fro@sqsMWD6!Y7dhd@Vp8v+wST0!40v;DTLfdd}M&t#{(w~ z$Dh@93~+XVcLF|3f8Eig7N*J3QdSx5gIi;k{|!OY7^zB2;@6H-*m^2P`G$STr%MDF zRsZnZ*tJ-m8#=d6NGW0A@!Q}rocjjK{Y(_1i$1K`9jYP`@+s(+O64!ylwg zlorXs^tzwq5r=TT?WfO5Q^fC<@qa>0ZZb_0LrSmR^t718>txT&*)h(^{@P-CX#*VxrXKOSE& za(Y+^WUA03S_KqzQ3aeGE=XO*mXd3lib54DiRONA34%4YpdfMd=!2Wu?}rMo&U~$O zMOa!>l&{wyq0h{DmA3D1;-2Kh5D=vBHoo(Uezc3)=47=+OFk|GXK?g&#gWGzB4CC5 zAC< zSNT?H`C$#JVE5e!s?(Ju;hb6eMhI;yT61!fN_c2JQDa47?`U1`KF1hQ{&i2*yB1UaGqGk2 z%>j@+JVxRfsOZPy0PNd`bjnuI&$RhJVb0hhgmV!OpTMWZ3j1OVivg>K*WO#!gcr}F@$BCwl-#^v1QtF1wg5JtvSxP! z&$}u9!wMebFHEqc>-lTRLf(513=>w=BH$VSS>1l4m@{J@TvpCSN`M>Z&9>OB6MOS1pvn>X&o zvfp<6$Bd8l&VTtA|2^g8oV$yYz+bg?W>#lq;GgmxNOS-HGL3l6shtKtQwxFnq41sL zs7@{Zoy1GFDIhm+XX^vt_?|pf#fADMQL*D-_%=XO@%{!xQ+R2o;AI2T3;B8usQ(2- Ce2D}A literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table.png new file mode 100644 index 0000000000000000000000000000000000000000..6adde62a57bd46bb4527a68892f280b92d1877b1 GIT binary patch literal 27520 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 F`!})Ccai`A literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png new file mode 100644 index 0000000000000000000000000000000000000000..ed17d4580e30f05aecd8a1cbbeb13df779b95e96 GIT binary patch literal 27930 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 UQo~w+TbI#js-IEIK4u>DU$fk@_5c6? literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_results_report__model.png new file mode 100644 index 0000000000000000000000000000000000000000..26c25e6cda3fa3db1702bed6712138a5c2b19692 GIT binary patch literal 7084 zcmds6c{rPCyVq%TQ>BY)DQXl|wFI$7Qd>(2ZPTi)lvrbpXlvI}w6#^Wq_L!G8Zxz1 zDbgVZl~7BlRBWXLq1FhASWnE%*VE~DzUy4)`p$L!IDaHh-Z#&CZ_j-{zu*154=!4s z7u+khmyeH6(9G2MG9TYhK;G}CyLa-wpQj5r@rG@v%jXUGirbG*@-B9G7(fm9_)1d* z)|~ly*Lwm?ZBcxDM`X7?+srPXoafy<7-V7-1oL+fy6qh3#&?4} zVa5hN(KtC9&Rn{x3YZm}Q7jr;S;7nvH?xL>i^#-vG$lK!C1tMmnQu##t3~U6o-0A7 zpEAX~Zbaid+ijC6IM>-ZvKBK$$DgQtc^I0cp;*>yyRwL7OpS(^6=L)DJf?5C-vJ1! zQ`sw!C!H9ru?Irrk5Ly(TTC*o^L+mSnxt;rtL+*!0@|!NS59CS(c0DEGCYF|u3evB zN_(UsTX)u2jvk7W3vH0;S5^g9KidjkatS39b7@wvO)Gz1PwCp~iq}_HP;7q2mFyAOP*V^ zVz&aBS8xNt8>R299Kh|A=9v*M{KMGc^5=xmbgiwd;WAp{u7PY~M`nKGD zZII11^-Zc&?dHbnTGx74m(8%6jr}Qu$g}3`b}hw76pS@jyLsy+WMdir3{DGVXy^+8_*+EwJDQVyaNjk1m<{DTHUfQ+oz9o#|#d%P*2SegK zsQluOej+F8HN`R}1Y2EPv+6>Q<_ytLpZhV5^T&<) z;@?+$GV4Rl%VDR(=bWJbt9kO0fJeqmLY)`NE5cw_aFdJ&-?FGu81fR&`}ZubE`(PK zH89V_wD@L#mxWfQN@}Te&M7TxZOK_Hxk9BUCm_#d!x)(&5H(<*(Sq3Cl85CLlB04~ zdXXu61&ZG0M#kdrDm4jtHV<;$8_CowP0*ZMYmy>I?7WTE_rkW@Ka%QrT*GR6n1aVY z$^^|U>z_VT-W|6hg4 zC~E=z8@eXF)|>=sZ0+hb3?wqnNu?q0*e*N6$Sd<~jVwv0xRD|PDkt$kMj!EL##sMS z=?|)GHfmQQLV20J#P(JI0;K?&G$0T=Y`tz6r@q5p=*BiKQkM7&o(rr7Il8;5v{X*P ze+bfLUMGM%js7!Uz*LuOS#!4XmmeO0DJeOa3Aay+Re zcqZ5{_<2IuBPR*!l1>U8IzU%5L-n^%H-ma4>{pYdZXoTMz1D#73GYXX;l9_~Zep~< zBM+}EFD+C#sE{X;A;fA6dZ5-E%iHfMO1aiAlVVGLQpx|KYNYC+h<{FAWk&`@0FYt7 z?mnd|@pk+@IU(6wr-Y+WYGI;SxQxc^B{X*>59QSxdiyGsqoY~gi#q5ylQ~M7!91f# z&IprwweE_=_^DZSg65)lb|&T!twIbxk0XJ#(4|WQ=A#Uw)LX@}pQy_tCk2ufjfYtd zPtv2&6>TPd$_3t{xt>S(s>yub$mdHZGSEDzhO>3ydvsMdU z29g||QzKOr>11sy67n#O%z4(DkVOaNw3aP75R}DMbeC5xY0&Jsv!J=j8ZR5%3z5HP ze8rKyad3cqY6y}XZGaXzmdKhvz4AED?ITr^Y})p~-QhAJ^5fJ6#s_di&)27%ke5UF zV**$0g1cRwfE>~iQ4swzpB@|M~!dTmj<{lWNI2W+D? zNk@9YxE$(zMA3=!Ah_^Q0^wqJ$c%hj=MK2UV9rPH?nsBt5J_3&KtwVpE!o!P*+Xj^ zCIBcBn3gY5dp!DV=Y8c`)4h;p_V9!C;sDEQJeG8>t0qUD>JVB3BEL=E^v@y%2G+)0H<^h$lf zVaKQCroU0ta?Yv6q4B|Fp$7p@p}AIMa725*MIs=d^=14tRuq7%k5CdauFGgjNi7tD zkbt;p70ul;=8?^-+3g8~)TXcitXt+pm=4jTFaLO%+W9GT*KuekO# z+raPlD2(JDnCA~A+#(9WeRN=@kz$*pV#O*DRb0HWww9#%K>9xQpT$^ekY>1Qp7pE6$c%&S(p)4-%onIM zormPYG0%FEu7%xP-G@B4aC)g{Vc`0Xbi8M*$ls8qDAuLnZq`7!Cs`$x2LQ$k9l9DK zLa{MtdHk(7!(Xc5$CXB7`X_$H$#J{Jl}|>ka8{`3kB}KX9d(pB>`*P?SvmID3CQf7 ziK6B+bST-)hO4hN_xq=XnV26_d^Zdwe!Y=;hM(hIO+bHvLV-?dkS}@RxYKZ z>D4PD{;rYXUzGB1>m>g5+P}m^YKbcFH9vQoQm@`n;c_Y-8OyS+rdrf7;^06J;Oo4^jsXdLa0|z~{dKru|cVC$YUM&cR?m?wt3Wfqqg= ze(4KcXT%MGh3$6H_&Tb_7NNLV|0e|RfW_dwa5Ugk_;CkrvD-Xr-kc#Ne+W+(68BP%VU}Rp$&gOb0bMNjS)VsZy; zry4ZTPfj>nJ5n}!8iI@b^){UXXM5OdU{0PlYT8k#fqRCeJe1f9FF>FUy1xWTWf1YU zZ38jr?O~E>><-!)h<{5dZ?mTKYPdTY1xmtr@cS)hFg4(?v-atY3#Q;I2DYn$+ea(& zF(0ho(Iu?!3gP19LIPAsGJyTWxd1;^HD}NU%Ej_=sbBl~Agi?2(sWY#0NK^WI))CR zFm`S~+QtR>(KIETXon|B=kzEC{}E=)WBeYWFs5+QnB*g_QFuhbxNm2JEhr$Pho%N( z^%#L>?n;UC%L4{|d=?y)GgF=~*cf5!f?C&?DPHy<_B`s>0H-c}GP&clj)z^C*|&Hp zs{yBsZeHCG-qgk6{J_y4;Oo`+(tQaUK&C_92`#NYrqZ|Q<9TyqE`dj}>y+VPz05}e zGiw(!`RPVFN+U5%(&ViF;YdtFSUsW}>;amS()#_!J5>8_z(7 zZ(!bqe3x=CFGN;-4A3+5d3<~cb>*A^_>TO8_+On7>C1NZFN#VqtPdjlwrG) z(F`1oXl=qmy1~-gQOjdr$7U=-rIa@UeP(6Ctx0iUxo=sB!4pi`M%A%kEq29MufhV$ zZ!W6>+jtG#rR={dt&VyFfx-W+F1Y3R-fREUVlflt0Ytlf^E0s-ZNmafQ2Fy6ygDX? z!RQv`qOqNKx0=^QTQ6gOgx>>oV2ulOQ2*nPohNGuKbiVxPx!jx;&-%}UtdIEZ$Hx6 zH+M_uADaV@O8wbX*7q6i;g$27+eF(fOkTWl=9CXP_HFF9t%Ap@C;sS41-u1hzoYma zu+rzRB}BWAT=-9NkF3@g%HP64GjU3uTQ;5eG!o>`NJ`N>mUTY2n`YZ(CBY)F&oh z0^$HxG_nqyt@xVJFst=^+_???YE~eWTnr>+o{ z^8EbK;8w?k+Y&IAX7&9f`pQ0WvyEvjSWh|e#yu|j;n}0{AxY<`v*V#k!NlN1K+fse z&SV|YQgSKwd=VNqr7!wISoIwxJlwXg-^ zXZ65r_1B0AOYFWo-L(FM0_mq=@3Hy&Ek=rM$?8eN$gG6(5kkvhw<$3lbHVE^Vhw|I zrX-5tI|sN8)!k%)5L1Ei(@PHfc*a-Z_t=o-*><37k2E>H_1!i!!Hhwc9p4)$;jr+k zSW?hhpZgGzj6rv6SCm{I$v06u-KXAL+7XrObXP~py%x~h*PTchKd!ywWes*b=k45d zjZ~hKQ%^j+z2+!D#x+uoAeQ8N{F+bePNgfds|Qn|_YzRm_|~4k58ED?g|;HzktI=q?-Ywqf4Z1b%clnV_KA z_2eY-V-xgLT8I4VTF8a)XD6)dpBz%i1Ob_DQe8ET^hcTMKC_dIp3y?_D5am+1HT+T z)Rv^@kiU3fqzLIzPl)vn9Qk?l(s&y&5_cMRuqCb7o7kRv(S*OHEa$iPEhMRtzV%|d zN^5-Y+!|8udjCiCb|B+-z^R$_U`o~TM>o47au$^O?LTa^piW;LWMzh3PlVSsVg;jb z7KvNAOFlvFdKhMiza$Asb{(oht@kX{hy`%6mh#`*FmTv)+wg9U-yhblW@6l!#tX%m zzL}(P%}W?Q@7g8)nk>`a(Kh(oRm&Cg$H6t&4?kZ-XCC&>Eo*z*I(*^2NBiwz3^V?w zPfK49=ZGnsi)>$C<|;KhbU=R(c7IdM)r~)n|M1jjO}hB=+y!TFYa}B@eR3=FB8AS* zJ&{yn<{)*18P_~1Z0m|m2R}P*+Nf`!FVUZ$7x#6$j8&kASY94ug5SL}zJ<5GADMjq+ zag{QQYCdN>C*ONA? z zHLR)ix-XWoDlhywFQF(AfIeE}{*p5Zn3a}dX?HJ{9jTpXGaOHi*$WgdbKr>a#!n0N z{`)(>fa8tL`yCF(Q9=xHfbHGP2O}d&&1Y6kSIiGaelGMwH9^4<`}2z#y{NRuNpCOS z8wITZ;@ZZGZAsV^vzl`x-@OIVI^jax<_}=k`zLekO2J^N-&Xv-NB2pzX z!Yp%xh5S;KBa*_%6XeeciC#0Wrh}=qas4GL;RE80443VN%eP$-=hou(THb_;)gH?s zxtbK#hi)E3#sxwg+JD$rpnM20l* z%M-G$V(9BQI&*#15KuXWdg+vRV7%WtSKW-kFl%)tbg_3v??Xj47 z*apQ*s%uneVY1FMAv*Dk4KJzs!1gG>;4bzcZPj+msp?xrZGrv_dg`jltiV*2Jib!l z6Hcy(;Fz1!v<^l*@Q}csBC$PzQ(%QZ)XIN9&wm7I@0dz!qQ7IM_NGPErqCr%O!ca!3iJ(A02)$(l0U1ItSm+>v6v5DY ziAV`(Xd(nDK?o%D7D7l!;DuY}&YN%U``-KRd-vD-k#n-wUVE>#_NsfGSaVY&zQbaN zxwyFajIUq4!^QOjkn{fq??KKpR;V?S^V$c$V|0ZJ(<3p*8SHm8FfribDoZ%Rayq~n zA9{4%7S6>bB)9k5XM9I?l>_|I_nM8bg_nzOfRoRCE+e1&_dVecynO9{;^i!n)Hc3q zU>Rt?l%bEj)b&%0*Dt&tCq%k-pYdLFI`p~gg!8kQzM(6>JT~e3+{YVh+{w#p|NTSD zF@B)z>;eAA0NyoRWKzsgk(-WfyqcFUZeMlukbxe0UsVnrdNsZ=w>+=+Q`o!uWqi|M zO>narbBQ?mlU;uO{KnkGLP|}8JBK^23vX3`B~6=RS9ni9G4~UT$BTP4K0d}7S-w;T za$v{aSs8(VD?z$7QJf3E@XoB00F(kws6@$CXv~rnD-56&2n0 zSFqs)C#bz@Z{}j^c+Z?Mb+Nr~ll8D7WW6{DpzW#%gFcB&NfGW%JzJ)kJF-WzQuLCD z=zaS(iN#FyURU;)!|}+~{w$VbMaax^mt7Dskf_rg8;LgH(2;6dkH;^DWL}h!StQae z&>$5NQ4U|cGjri!aCqg$M%|i>JnTv?mUVsJF2lQQm?Qf=R;Id&&&~#^_-wEJQLl(R zh*_3E7*EAI>)Z1OqZ&#n`QqG>d-A}*3@|uN$Q4?wM_MC3Z6kJSkg+Py17&jfJ~=+p zs!$1+?ipZrXjWz2ZF&&j8_2(Rc<+X!u!}|bC?L;>hz?@@mWey~piCJQx_<(XkH=H< zJ9IwQC>mmy-y_|gGfXJ_cRCL4og~dILHg49xf+Qc)xZvCeHkiy#a)FYE($n1ATBsq z9fO|aJGyr?Cc0ytm5CsL*|p^W%gwF+MAFhqI6_$^%MzR??J8kC4ITin+V)w^+4Y?CEv4;f*2L(<5*}Y+9bT|~+?+1|R(zCwefHrhIFGHjv!$S{ zHV-q|BE9W;w8vI~iyRW~^kN&_u|`hw62)>M_Y|Z`=n@s3Oq*ai;P;q%BIK6{25&J5 zyF7nYc&_PCC+jD0A)(z~11xD~&acjG6h6e1 zN-ti@J*EFz)}4}ua%k%erD%JBRswM$X$a;zR@JMS;gTrE{er-Fp>Dqa;bV2S=4@lBMqaKZR_{#pkqxY3HLt%n01q1cz z)Dm?E)>KjhiC=S*2eEb59;^0~#pBn>FzdxjH)2_r<*NLf=e9of$0JGN6I)=qmu?CI z!Pc*@0itS%!9@%f1=|-oEu&AO-L+6V$@}X!|90Y=7o7r@clLN!Dt3cjU9WlBy#5m5 zzB5~a7-Ef-?7C2Imh8Au1ss?-TWpo(pOBjeldG^hSE!#9uw$Xj00frNfZhF490nV- zJax`x^khifoiqC8#_uz{w3pUgq9|S?)kAR9||^bMhZz{{VI|P&@e)CR~w5b`Izt^UYdG zEvm4Cd#hBA-&1XME!%CzfyG`XfIY%Af~5f^>YhJfHP$caCY8@=QLmr-GN%e78BLi=R?IL+Z^ zXQgvLLZxf_?#Teb=V*9nZ44wI)OGwFq`JNP*_DZ!3iq^kGw0q?9r5LyL)ZId|f?yw_GXM<2Pmg zmrDDi=Kl$Ddpz>iYxTMV6(go5YTYN7&Tb05y&C>H@n`Lcd!g9{X!M7_c%;C~oMbfm z^^n3Fu?^-zNgB@VHqd%lYW?i7O`$u_q|Foe_@yI}G)J8$WA3Ml-XH9Wu;n0m!r!Y~ zmM8;D_cQj%*=kSth9Yl8LtBbT`R8itti<10i-_7puzpD_<`}0QSl+PQacIrr#pt~v zzCi`#(TfJ*myP$_QCjBtXLxLn4Iy0OT}}`oz@4|HhK6{2qx=aa(nMX zI|{3fI>H(LfqxKieULp-8Q|JIm@yuHE(%Q6b0L?4$)_dU?cbv;EI;GFwmZJ(( zN?V|^@e6;l!_OP)Cq11 z**lkT7)|Yk-SN4_cXbORUa3a{il3_-e_p5|-W{c_J~t(QlJus|oNebYj!n|t{5EKp zTap?ezEZ3m4nSqdNS=K$IC1A|r*Fw}{#u@xwvKu3DnE<@d3jh$ohZUQEz2JBKJUZa zR?Z9=_J_>E*&hQ#MAL_}qOLI_B4}yr20}TM;&!&@q%7N0F@YAxc?5$af9?^QqrG6c7GB)v>*d z{8-RXL=^O8%R{pHI%QpDgAJz>MAH{KXw2y7t0VH%X<}#FwidTKZQN))SfrfU0ToNZ zoSHi$(~b+1KHP7!zqLBMl<%6a*vFIe&9&X`1zOhTl$(>%+c;DJX(XyFM`82bc;KTz zfzHXm^z7>iVKhHJ*g$T>3e(^MJYa%GksWU?P!pS#Lbg=ha)%WgKZ@Vc>Ipi^I4*9e zLhfAs7V?ybq538vK(k<~GeFpgHsJkaddC-XaN!N1Ha?%~F<(S)|458ku5S%fA&gFz zgapEbDnb>Ie^C5sS0LDMN>oUbe5>VDujM^eklRJronYEhII{1Vjf>n1@#G?~lJYSNk1MPtFo->@;*%$1DpAGIk&i4_ZaKB1*&>A|%pB zYd-6YQ3N|8y^+VOt02(?9s7w;UC6M&zSxtQ`tfu6jRzxiX9;I^%tJgFfcVqb@2N%4 zliokpLI{l}yC!@(F*vl6Qo?AaZ^4&D`J&2t2Q-{e2d{2UZUS{&#f&<#D7TLpVJez3 zAN8c#HlGCJaGlWWLU^t4UwzWtt6rLa>a49Mezl1<6irEsYcA<;#-eYNP=|YO(sYZ_ zWz36n1>lZ%R%N8gTKm&}u=?IBr}+;}F|Um~o~vEc1G50&;h`Sw&~vp5aXQKurw~&# zdQKc=2_5PMZ)*oYK4~NxP1+c#0`p%;lSS4w19=7DX)_5mbhoSx9almgxnN{5tQsBk zBuu~=dS?3>5U9(hnFT>{bKR+uh*w@w{c8ZAXySniRMwj@^3O22>9m)iw6r62$Abs@ z5mLxVy3Fgk*wyY&jzKvgzinHss!Xu@y zbB+}NiAe^(AI4E|^7GBzeIq9gbB0r&MACiwD|>4;GXQdIIgx|!3TL=A>KcPv!5n6!P)4Z3`7 z_4SCVs6a&gWlj#_Px7K0{=qPhfyo+L1?WRNmUV|)vevbAADB*N&0lkNL_LJEK&nkc zDqPdJL*JVuMFoR$%B0I!QmNM89U1;+e+*VmP*hH&NJ?3!9ttF=+lcNW-zM{nCGk*3 zx&L5X1@@8~@kc#=T<5+~zE^3Aq#XU9r`cv#Xs(UaO_3B}V%^UR3G>1N7q0(3&mvTT z&Z?+OhyHS%*f7`R7!B?!@+jAs0I~DKkJCIapi7}~VxkL1Cu5!oI&p4bn_`v&WA3R6 zpH6@ezS=9oMN$s`^nVBOTn2SVu@XjmFsa%VV$?O@!lb1${mF7_kxI~0 zogZYVTuxA_yuMPK@}476=*M!M0_P5aJ07yoxD=M5-jg>rxLwJ5Yy}$vB4$%1Nor~G%qGQywt%jYn(ekS!#J~(f||R zy66NGOIb~?d_~R#0xK52QV(HTs~CirHVKhpDd+9ItnN8X9Gg!DS?@IVVn!H#lXN1emVXQ$9{c<*ukMY`@8HV7 zx_1vT=gfXHzGXS&EsWd0>>Fp@|KhLC&|(sAw$9q?2tke?PRqt4MdBehe~{U0Cg@u7 zuf*d4$7L)Of?G^8Qptz6TZmT<|2<5!BaHIEoV$}?#nQ*$fjQCR-vkt$+${gLq?k53 z>3*FUJ+7YAKqWJ0R%u*g_RFcChjY)^z+Za%uj`Kq25~ogV0!KDD$_kpHg#~{XJ`zK z9!7CRv2BlV$dEmjD`f*hPMy6Aj`84TWRD8&NIYGQp@Qf}*?b$p}no6+lr11CWBB`EKLJ>A?aX6xD6?*TQukIAdZS&jR7!^~}BZ0BebiGo3tBgeU z&yBsZXUFuK8)2T~(a}K{wJG&W_nCQG;EgG%lyU2hCgCZ&xb)}Y z{2L1eZg`k>4PcE_1+fywZ_9a0XDYkv3QKD3$bf(--}RCzCwqfV=tGPTga$GW?DkQi zfk@9IRXKT^x60N)a>ouyhFCpG_)x0A+SJcph1p_MJ)AaF}3k8W)X3Tz$E@ zBY}OdG(unpC1u@##GpWlAGoP}&!HI|^KjDyKAAZB`ps6Bhjg&E zF?vk1gZplFsi7VUN)X66n0MF-3jUDigO*wY5=8*ouIlXfWLs;(mF@^K`Op`D1f^l) z#H9mL5ze}ANc;{w<#hiKVFaA3drdEKxoX!u)iS(|Uf4bEXl4|_ewDtwkkHv15VHXw ziO`!nx|Q_Ib~9(mQ(E(7_j^bZG7w|w3a4;sGw-F4a-6;yre*NQ5=^HKu5PXjy7&-N zHD+;>Hak4Kr64W}I~O5)2ZZ)0Zua(l;|p^m_(jk`nWncCZbuETWqylJ0lk&V!Kx#q z6utevY-WW)AacH;uq%mOa#VkcD5N&fVr(A)HrO03g5YGbxX#|sJ4U}<{#Ce zpdo270U&zpD0+sDJ=}?PFZ7-WUbZg8ebbQh}O(!Uo(s_09At$ivMj}ON6lK$z=E7u|vNI=^ z7ece_P|%rAe-$dWE%+)5~#J*4RBC21S7&mA3HI=n3#=*ccuWZnc)W)Udj&r&6nm|oM()a z0xBZ)hIB_&dizH|UsZfUCtSW@ox`|4mPV#k;ZZfz(h{RSf^6AR9gXyjKFiXA&^vuY zn>)~DW=PBCmzQz+k}?Bf31@Rm`5DXVdLGYnA5BnC$YyAC@u^7fZwWN;F#}m6DsI6S zu?-jt?AFK=JUR88Rj_1(X8qJD3X+=D+ogm1=$_=BJkd9x)?tehRS=?v4KgMj^7Zv4 z;i)-TP9RMo&A$=1OW3MS4coLLykWN*e52e_b^o= zW5QkPLd<@J>hIkZy14lP+!w-$l>DRx-65@8xtNv`01yFBSIkR|1H_ns%dbG?c6azN(`MaFc=$^l#m(^;pwaDS<%kmyY&12+Jg^k}Vbg9FBcf{~6o zb0uV*@muU}?{7QC9r5{;nQ>oq)gj|vzrI>9&@5mKyMr<3gHfx>d&?dzTq@67w1d2O zn;ec#;oZzOq}+UjvR6ktMW5&SoZp}DI~)#&nYnjfb7$s#bKb!;lxV4$sUZ*ut@6YB+7JkNH~5V_ zMFm<+?`*DtKV&Z2N_QdoZC7T&KPR3js4GAqg%LFSk0`8(#o^Ia;csU- z#?MfXzvUg$qPtvA7W&ppOYZ`Lj{baofCSB9TwPHGb^fEnfkljTZ$4oKg( zWRQcNd7*f5i@wZrbEB2J9BqKI@sNRP(s#?wNVb` zC!UmEfyh5uh@^qch~q^dF)xo9{vUck06Tk3z=B|g;Ooy;LIV6$q4ij=g4>z0P+yH9 zL%|>+TFAkpAQOmu-Obq9+`C}*!@sltk9x34qwD6Koc*zjj*5_gmr1K;(<=-Gp%Dnfbds8u=>DLoV;)jyVBI-)P;M=`w7T_Mov` zs%iKiEfE>Iv(Xz`IfKhvGgoS$nLA3pkWBm|(-zh5kyu`;_Dn)qxtLaHS(r%7so|o9 zJhTdeL*xa0mcOlBlX8#09pObtGeR~5)ALVc*xj^Yfk65TzCj^qM%^gib-$pd;NoCt zd*^ny*gYWqk)q=+lJx!D4JaY5bKxv=?C~C?qiE}$m+~aPqUQ>3vC$w(#&##Hv?~o}ZsyFSs4J8)_=`QvVh6!X?R1Bnb~ z)gyx>Jxg(Q`Wn7cG++}xv=U!-g}smaXZHQ-SHbJolOH7)|9WL&#^u?2p^;C(OY=OW z<2|b+Alm+F?0R*PGbrEp5r&T|)>=-}@Ia#Sql5EW?8v1PkP@pPb%;DyvR?}OPoV*I zwz^(pD;o_J!Ll)M>i=>PBZJs%RQ-_k!Gmw}y{wJW^4QpUZ}&i*8(_j0|!f2>=G9;cbguwKIH^82V>c z6YTHtg5xuj45mX@rB0P3rSo^I$l+bPs(k<3?v?tvB>GJD58@-ReQxf3Cjx9w#dYw# z*R|@7>GX@WiNEpRp+kXF!p#7(zD(Z-9s3~rxJw@4?bGkeev}QoNh{y0_9O<|*=fyt z%(??sfa)ea9}WjFFLEx@^-DjcfaoTXkVvP#E@xc1iBnHagk_MS4HgPcLmC+QYj6(< z;65Ts5=r-QjEA*wzI@WTO1XLv0)dkj$IS_UUaTQpxAR6IEs1zDC$wLBj$iuoF=G_i zL$rbJY^$V=>9&St_^=UUx4Sc*tkgUD}zlTM`)TVs|ECAc^;K;%704R`6Q zb9Lah<~JxI9jthffLiU>0`mcP!M6&0p*mc$zaUs&W%j8av?n^6M|C?Yq z6Bw?RmD&@67A+l301dLF28?r@TZe2Zdo(%3njOI`-=uqWUXf~SGFnqW{jAJ-2SIC% zixMIan3DnVwV|_C4G5U7AwF9sCpm3WSdG@V5j z;1K*Ewn^xIED@>I{O5RV~=pB_X%qc;Hyw zs+Q!QU}%CHFnhfz^fao0p0}kX#QbSveqC*vb{@5(pf+c=bR18%hsup<*|6hjRAQCl$37u8VSTwqj$&_{2Ad0*ikg|3 z^&&Q8^KW2HaV@zf#R7WCX+>=_$%x**L>Ab&VXdU{9insML>v-(C_aR$^n~C1kH7QP6h`O7TW0Hs-hp zHwN(Wpi9E>Qp}XT3lS7UhVVarT`{PZ;%?W2&M~DZ^#nLE7PZu)nqO!oGy4!EdD|{H8vYxA^Z&)C*`>s|fDMPIn zZ#OQz7-OUF5Fh;9zVgKeA&vz)$I`M3A9GWhUTNOaM&&ckT2#7YO$3c`Wh)+x{+syP4-H{6ec6JTV_cP^0T{Jy|liQky9tFL|yOzIZcJq65CSy^^ zl()V7`Zu*V)WsAy&Zx)t^Ob zIUD!!uCB)Rj}el)c-LqMI141%pHr(_jV&CXe{%TfT!^nt^E%7uW!{FgUUSEm&B36I z5abBM#Eeh2^qztpV8>;Y0au`4CbTIriy zAHWm{Fj=+G54_$RmDBTj$y7~DfRUYT#7%uWxSN`w*?_aZaYwEyjT$L<$roN3)sZuF z5JEC%5D9l_(f9?^%ktO?^D`x3+_!a}B+)~^bXK${CQHnw>pE^+J{TOmyOt`IZK21X zEq@Z2KM-%4W6=v|e!R$wt8eMQdy(&pveR;syCaQO^E1OfJ8YlyOgJ*hm=P7mug&c_o<3^Ua|w4DD}ja?RGz8#^^q>_?F0xX&U5ykX$G~#jsXGQMQ)i z0LjkS6k9krjXr6TWxuib+9inHOz_Lrkj~z7=`BS;nsYwrk9vs13lW&uWs4|x1rOb< zTwC2JcP+#K<=d(QBTLx>sAZd^P@>Pw9ZNsoPvy@nzAOx1mKO{&^++-ta%wU-?O+wc z-?9*;l+ds@tSL8g?b7I>m?E=GrizPp06GyXM5G*KDXu?jXgJOC#FLkd>PK=g#Or75 z;7?7TYkI&WZ#m8NJ-CFXgC_e97v&$^a(~sSCsEUmb}b7f<<~6a7qU*Fdxr*Z4eXG| zi8!%WGalTL4i@oJ2I`0GV=wj>$!&3Zc|6hvjI>qU8u6Y_Vd4*Vs&-nAW;>WSw^SUU zoVf{968RnMpi=zrTwoB41P726W?l{O!^92)AriN0n)sFq?&Wf1hV5Oh0f#su)|wH` zuIr>hEsuK8-`{;+zHa-o$AYH6P;t9w_-$i*dfsMblzDlZTC%?%M*1YhdI+?&HPBWS z+C6&o;db4D`)-Yo2kr`9gsL_94P=+cAfPF~ZbS{YXpcNZzib&_of;#z4=LO0`G$(G z8wx$zZu+#7O17&G)HQnGJ>In%xG+-?!(tLho!5Q7ZR>sPhZc=~TT;UAt)iuZK2hC@ zP-lk-g%y#A6?701Jam^Pl}kj#X|mt_YpprO zaIWr74#e|QTRT!=1D2uXzA17dk}=x{1My64>r6*`y;u1om2A;ssFcy}#7lDLE{k|G zlmEB`mro^IeUOx?tWbL6*ad4ulf;vZS-n6TDLyByPM!Vw-z?HvQ`ea}A_$cUbh=Gh zo6mACeuOU_CjQ$j4o%$^*fA?0x9!zI*VAp+u)~8N8WbHBzXbH@TmU?~K9NsGN$N)j z+I~nDA(|@92o0&56=vQRH=oKoahbzgk_1RnH=ss)+D;oryYy>fF#k5Oe6(k$e|iG3 zql4|}t};0a@lrmy8X!bF84A4ul{d>;D>V#IKYANKt17!Bb87Mmg82s%Tue7WT4(yH zHZY%pLyyO@K;=iW*2H))V*i>Vp)8#c&&;;LbPj)kqpI6j6U!DSsdZUF6E?x__E9~} zL^qA0{ts&-zh!LD6frg&LAw2Kskq7AmN+SQoCg$E0*#47F4bG#Ux@X0pOhcLq+Xzf zotPW4XP8vN)>Yne9809@}YbO*?2uvM=}AAH(@7{Zt~^c=P!=Q_AS$+1Zhpv14*_e$7Yec0t zG)3O*WeEbzTeM-~reh?4o30d*;@K7$h~lTVQKW)wmgSW5_k&snXi@tJkxjx>gjX;3 zA-%XgZ;Fp+g<73e=@z8J@|dWTMMFE_n%49)?OO(OA4F6$5d(^`)7C?-d9aMz+<%88 zs%r7pd#qXXNr4*G4*8t#$1w8RO2DjHBfJ9_Z#(^SsI z#fu*~=k2!}4M)PstE@D+Af9wJ?`}|XUvm=>r%BM+W;97NIufM3GqyK;DpL+Wvxl@z|%Lsp;vPkkD$%g;##A3Fg=Tz=7W%u=42Jf>ce3* z-GEf>X_w*{lvk}MHG=se^1tL!SuT=1h)>DJBhk86bw{@?{q`1#o;yn`J0|agbB*d$ z<;uydgJfbMlTlSDu(O$M^XYW&1`bn+ZhNj~4+fL;^G0uGsck)G32^VzIW5nYmH3Vt z<~moSp<|f)6XOfWTbNP<3%D{NFY^)VX0(z z`J}*u{BC<<#t*6#J8hI-Bc8W4 zO3D=4yO^114>2mtyckeJJ@PPtlAFfOPh6GPHaQg;3BH)(KeN?5F5yLrEJ(=dYobJG zV4QPTG*u$KYA`<&6=H3gM!8~aCS#9b{UHwU$)hkX(h2mudLpT8g4)5qb*oX?q3+Su zM@0S_N`E;SmxfYjiQyZIVvtsntjs7KD_Y58!u%ahs=85dB>AnS-Ymrx zGyKw&t7kBX?u5BE{`qaVUwU zJHiK5y{K090}NC3p_j0b(73vZ&zyAlgJaKZMk)I%F4%iev~hoPFll<%oDky4HMh4X z@ABhYvK`wN7VF4d>L54#lmZRQc=0i0qyi4J*c!3R(3JVbC%s+oe!uLVb9BpcHMW1h zFai}-y)2+xs5kv|0Mqr6PSn4r-XhELJssM7;S?=LJ3;*#GhN5fN0j8=)8gkTd*4-D za`hv&cy4k-fQHnsB1}D@-bEFUoRj4}z-L0r1pUiQ73M4P2e7^MOo8`^Q zVYRx$4GQmAqokL(V4&Gj<2w1c8Qji9ldr#IjUt;wRViT5mmfG*{cJf$+Ys!OiIUkg z5H7OO(WEJr9NlI8>vp~z*J%>vk(cZ1yiAhdE9zCp$z<;q;BYihJC&n$xBS}|_}S-% z@b`3W92msU;d#CML})tf+;5No5z&GBiINBF1{d0(6LN=6#;=W%?s)>w*e|s^bttu| z+AzSZIPDhD72+r9CkJQD4<9qw&*~`N`GC5laZ6|Ud640DuYYU=7h);$-o??SPi^tg z6H^)Cp4tIsMStn20Npyv$a&r`(ENwJW{=7mo{x`*w6@Tgf5?7St!DE4(Znwsw{SZC z;DmfbnAzNOE?~b%kyHGTa&vi0wKFxsi+eu0*9h$3uM}(+50O%qCad?rrv{*;R_LudGm+WtmKe)?YYvhGUr!c9nTD-dnC1TBnTKU(dXUko-{C zEQs|D3`%fZF+Xewbr|aVpqIqu`H+F&93AMa(_}(9L;rVnOECMS$|B)t>xkqFwa6aK zhTY8_uPsn)oxZrQc;78~T^N_%)64hLb@eA#G#jzw-Z^zvQUA`D^~Gs|0W~^P@{~Ih zDvK@exEfWk`280r6MnY)m8~f9DWha|ttIN3C!ff6f6z#}j>B_c79Zj{vdHfjg+bdu zRDx0Bvb5AL`41`hS=~sv($&4tC*M^ZuNynqAR{F4q2|uYX(z;+XIjNsiWkeg48?%& z*$>un-SCDWp-i+HjXCB-if{an(;2`ipU}qYbU$~!if^GZlWFf@nPo~`U94_e#@WzM ztnTRG)9f$LE{#5DbYmi*Fcq7ryQ> z!UU~TFSdzBje3|@^2tR{Cov`{C2>I&GmX7oD}$Jd&wAM2{H*C;VOaxVUAQcN0dw~} z?P`-?na-1s7kKMzgxxm#k!xJCSJ`PAakQ_5k_7${9n0qbOO$rB9b{N>bYMw&C#OR5 z%xMOjc&K)-qV_J>m99a|IO(et6$lR6EnqkyNCz!`@TW_ASnO}Uq6(i%ro9d9J;i~~ z!35Dxz5_HhOsn|O0krt3wSjD0Ic7XJmAL3p)sF>->>>p>Is61T8exIeU=KYzLmne4 z1~Hl^vV`1BZ+vFgC4<`H4Khp#`v+$bRecK&&!A7~UVtgoZa00_a$T-!ZjssfSqL%; z8HWd>_iheo{-VUb)0-8A2LvZvi?v}q-m7JO?(PPpk|jyH0o1Eky-e;RdKu`R-Z|yK$*sUm`Nru=R#4CPF(GP&*6IE z;%52PKWj#F?UjYK9bO62V$xRr$P~>*&8@z)8ec|%Zae+KCOz!NVJ#_$WH5pkRo&yi zedsp;8|@vb8JqrnvA^esle2QM`OA4&^B-`@uL}X$Q_54m%nT1vEm_y_+i6BVTEHbsQp8|VwCDlOhgQYp{gga>rR%~}+0`0EKeZaki*wmi69$9GaCo;TjFvh1ci zH*ELo{MIyWezTy@i>V#OJ4M4#Kf^Qhtpocj(>nfVRTWDQKO9u^Z>`LJFA2MdD>1E~ z))#EIYn?;zwkEi#Dtb*NxQ$qIRfONe- zHzhbT*M_kYJ`NeyKm-q`dUX|aLDEw-j zR`$fkbHn~^zM!=F@9Fx*2!?^i_PKd1J+U;$4l9cdIV?|cvunX4a_$YXL=0$-E$TIi zN~;GS81eRw`Rb<#u3o`e{8`|pMRV(ty`_4Y79JD~{VI^=G4zO2pr&Ax|EbhEDuk~IJ$$MyD)wpU}bB)==-%84M?Zn}dU``n}b&W7i-zM+0IsI-)ZVO+0q_SQm z%6q+eMaO^2%Z91*?E&2`%Bv>1QSL_9LhpS2L0?!+;tVSk6X!}P+l-n#Lsgx6TSzf zGt8i%>{-hET>kv|aWIXe9`PzI`QD!=8%KJt%M1B!HtoKyDN|EL2+`8Lt=ds~d8pHL zRs9M)eDJi9&R(ryQ3iD+^z&F3rrGtmY+X&i%{|INhTHl-?lxb%1b?du|*?LvXukrqr-GaY1UIk-RwLL@PR2{2!ofjiuKd`@@f*Hm;>yCy&Jf{{Vxuz!U^7S-HpWOnny~i0Ea=1g< z7<<1L;ZS+2KU%<$w>_-+3yIT!{C(g8<{**thxpMQO4UExTXl}els%JTpmlIk1A~@# zhbDyE{cD-3_g6di>rViMO~rm}s40a-KhT>M`v|!aZp6z_IAU+D3hOiu1I+c zh!6H#hTl#rAG!$b^7F}tMETr5&Wo&_KaGtIg)WGdiN1Nis72O)n zyXm3kUN%o9e#p7uKv=RrhfTf{^FoIChRzyP>+XqLh@dKkxerqf;b*SiOts8yP*yqg^N$>^e( zf55ZlWtK%06#4l+?6}Q8zIi8vi^auuzt>Gz!Sf*2Qd%3tVkUu~E}j1Bq=0iCCPf6g=gbcgEPM;!%G zj3qYE`7bm3*lSvYDPr>2tTl~)Bxc7X0eRYVwu9YNGbi1ave1%*6-{dVJ7BDQV9tdH z%iDVlKn~K|6zFwdN^UAENF2}qvQ%Xx%U**8JxcJz1kS;lVS2O2Ya!G#5FG@u&$N+Bb0%)Pbb@P)*iYEyKnqL zPL6orLkyfF)lvbR1#l__d!+>6FSVJ{>+1Zu^6d5Vbz)*GY5#Y8w@MeAdjz8zVtHE^ z3Y!w%(FokS?lG*GC2-1n9YSaNtV2VkF3bMmC7^30as%g9A`Xr-q~=Fn#TAbgbEU1 zYi=W0w;OvqBxL079HG_tb39?Ui;7#wO(O>_*(g}u!nagmnM>ypP15|w%F^Wr+f|6~ z)}kXzv5)7|0=1;H2r=ZNdgH#|jzn8i8w$E4Nh}<8AyGW>^+}nB5yPiR^%a(7gBr37 zEku{L)3G+xZnAx86zJui+;_C^?VISGBdVNo)&q?+2T0*vdwSh(grhxwuNJ-j$27ug zHYX$)nnsysaSXzt&xS0v2v8dq$LhsUL3nCE0a?`;uFD z4tn2&$E@VFet3UW%W`=N(@|$cT<}VUI&w)_^L;m!@IgZFD|`tJRWlnC#8*_5p5=-Z z-tdVh&6So`6Mi}M03q$^Dr&s_T99md)4cqUcb0hF77hs_caJ|mU%>N*^}8EOq@*-V zHMh>>mA@f=v*^E0fyS!9GJX|xpWx9P24r+{&>tJ~D<4Gs5(Acr-rkVS2K^ZH zlKDZlNjR`Sq&daTQ8lsALww<1g!1CRErMg#%qgctR`MKY3nkBQ`90avi_G%C@#?)v zL-{rePYRg;u%5&us19m(=(s- zF;3ihc~+yPW-A3aLi<_~s>@HTnscP3m03fax(Kp3?qa>~bM+1;g_5_VrK^~z;H zZI5g{Mm#?pI~U)bT_Nc8t}UXzP>E9BoF1)~v(t3~Bk5*}L4Rb}98itut$$jcM5-^) zeKj19t8ly*(;f2E?`ZGdTD8Sr`AZ0N+wPW-$)obCP|+G)6K))H(RVo8<;*pBi>KlW zv2-5wf2F+&%V1;-+i7(S-RW;%n32=ji%Jl)Z!tfzZSknJTzG3{%m72oF>5L8gaRYT ztLCiLZmVNB{i7}VFwRynviKRew%OEp4fl!(nxa!p4zGbs@$q@r6TBh9xTR-HL1@q7QFSP%XR+i`>p4p-`tzNij z94E03bF>Sv)$R?Y#y802Pt@(g$CUW8c9YG0oj^#;a;jMxm1Ilfg&g->%%r1S8oFz*6%$MwGVWx8fS_%>;BC>eP6XmuQ zWMthhZ1D$M`tM&?lnh$9K;EJ6%h#ui$){w$?!@&w{SO$});UOZMX+?27B(J; z@2?4=gIwP&(Ri#$*0l0Nkl+DD9f>qc9&*LpMCCIi9?{gn%B-sN`p>!Kwj_#wA7Yc4 z1&ysX``g9R%14-aI|Y86^DY4=9gAOI$lWPmEqGEkq^&u6BU`O*_UgIYM?**!3Eysz z)<~EUjisXtk$lrS9=v?~#c#Xwjc=hif=&FoQ_89L>$W8{s|{?T09A+(C>3B?d#f}v zt9`>DBW3f4QUZH*M8&1<&maSbIn9ub1V-;fJZIRo8XKKOT)WP)p9iqxTq68yP~Jlm zE#PB+oB|-}Fi?{wtNSrc;jmANJ)jm}q!tmzG$FfC7l!==cS7uPNc~R1O(!Go`nZ}I ze^R3m&DPCAUnUf)vMA9{xCibRdB{S1W8o-w^D_laY`cYG6MmI{&PgqBu-i!iO{zf8 zOFtPeX}0(`-f-A|JW00Nv?!@F7Ia2S>e+Ok#k&+9ccrRP#C}qVqh3{F%>>5iF(y)5 zDju`}H@ZY&<9}_`@zhkBtnu!Fw#O(GQB+XHSONMoagv-iFKvrS$o{qo(w_;JWV508 zFKL>}2kKo-)}RuyE8f!-9r^%_v+e~Qg(J+ts0Jhjw?;O@3#qmcxP6Zf|P> zBRRuQx#YPPlFrFj6F5GKfprcLD$sx3UU_j+JF_ih2~^nrZ6|rQENEjAA12XlcaWj{ z%SY076xdLdKvrnX3-J(8iHRvxp!`WVwB?f516%?$X)6qau$NAv8>#56ZOy@8QPNIO!RMkxP`3_roqg-|Fn~*aw&uc*vrw2o{Nmi%DL#HLv1s0#&_r zgG?l?@eDnm)*craQV50^5jYavjEoF!5o^{$L6AGtb7ajcVR>{~HY=5A&nxIxc$?7# z=0C+MuWGvhQ%D*Rx1m_Sh+vNWMAer|vNO}jI?U%Jb+aT(H3v?2*u~hyBrqEkYh1uA z>iz41mI`)J&4A))6=m97!_0?-%^b*#pc`wpZq&dz!0i%(`Ex4OFFqaJxk}8xp0I(F zpa;AFc%4brovY(ICz189=e5_;;)%;A@FLWzwCRSKYJ{~AD*2-CVn%v?}V}IT;Z+p~jOMCT6>!%_F(-v5V>lxC2yoX=4mCS+c*x zUd_IfgYjIWLx&RXWRTp7l1m)z+}$(0q7RWtd>C^5H^-@oRvlm-O`uddG1HM^@)uwk zoi4TkEs};hl=*yGQxeRg=E>wSQOtw7!T0U`2Ox?Hs0Zzs`rGsC!O&-jchGjI?MMx< zkwn|F=w1vgm5>F$5;AqZe*JpZ`4s4w&3ajXtfI`diIs5&%QeD+J8W>P2)5;REJ9m+c;~ zp(XLI$|stO+4WO1Ni}iXf=3qxI@F5_dd-llHEXt5i)zG)EQMS1ldu0Wu+tY5Zq~!n z9;merhMYOq?{<#1xk)!bNXIfw#SCK)?(LbUFYk6Ls+NR!$9k^RZiU58l^oa1dL3+( zBC^N;t1!SyrQp`y&lv!%b$$37@ zvLPY8$iY@p@)o4>O3Ktk&$}l|gS}Kc&482xWkZ(T-HrRx{>(1hV~x_p+xAm~TR5y| z+c$QBrZx*IMSE3Xv|Acq3Wge`nsUk=%mR0wGo*UqF)&Co%ASgHyT8BomcD{^zBL<> z)3Qqoaz;z>2(veDu6HM0@$=~~x+=UN$G{s;s^WD|uy_}$22x?!Uy6oyzpdpP$(fix zm??a2+w9cr*6hgVSZc_^-Bu`sb9b{aD$l1?ZO-Lyk}V(bTgf!^$}e@k@}V5A1*%bJ zcEotb<*$BpeSby28|gZq*Q&EQs2QH-M{?T$UMs8t9lYdW1gM>Dd|K!GRDMZpZExA} zftW)Kh2;R9dhQod6-)FLZ#g@xv7qnCi+E-*^OY25^3*-VyysN6EkJmrU&+I zId`WY^G#8hZEv2TjenUgCJo`WIJawAI?HnO;ZNLb{A%N7>0yvU@%EIIL7$zR>Ie28 zxJn6n+g3-5@*G03peMA zy`(>YXc9J0i8iuTTeovHBe+QQ&*JI&BQq78RnPRAx%wt`8gJsgdoKc6KZ+UEq(y|R z4%`^iHgEqFlrNgI=wgHu8;i9O+?ahiUzQa+`(snF*`*pGDQREwbZc`Cg&cXA`^ zyV+Ek#CnGtvK5a+R2@ElHasT8DllD`Qfi!Gd2|bQgvOlwfx8%MQ`!bRk1u9<+^N>6 zWU0x>K8_(iVA!x2Hxi^qc``SIH^M!B)OTs3?l&6`2n};5zBtkB>MN1|On`p6Q7CY# z_-9Vh#(ISs7L;laSk^kXN;-ON;6*?wlkR(=ydDq$g7*QzU*fM{y1p=NGyeXaf1lm)2_y^;g<``@nr5f+qRiUp2}+helbnnLc+AsRH zBM0qUXTroA<8F&f^G!z}$LGzr%2J0OQ?~gd25_lQw_fu4twxLNcP%R6gp7GnW1e;h zZMFG$HMvgm5j|8{vj^7iWVwBkew-z!wf45eZAARG%TW_QjIy}o-5~pMV6CM4RkCBW zXTT7zHA=79flHpAbPF!=eF~3H;Ek|hQr>2*& zmO~-=biB>V;qbNlxVuZ^jMI9j+oFRYmHH${H&IMJ_Ajq*$6h65v$(=GmZ@?+zfZcp zrDlK1*(|p8Ny?(VVr2uh$x^fHZ}{(rLpi-K1-m!40&*5WP z4wxyhZEl+?ik1nN3^G{Zw(z^a9sO`gQ-s)O8MZTa4#)1U zmwvQ(A>vlbpuM=|;o@kh#FmLA10(J;S%E$@nA_-$ouWSNcQb|sjyuj{%M+wP0t?sPt+!cY2XoGf(MMu*)b9^aKQdOzE-5>ig@GT-8`aAoD$af z$w*xj8xp!3*ou16(@Pm3WNKCaSb7Dw{Q9J1)K9F>XR*b;ltZfw4XIYXJ~D0f%%VR5 zCodO!7MBxOfh1avjgnC`_{2f*>o3HJfi$6pI3t1i#OfvJv?`vaCttKT-{5LIf^9W& zz@4lh{?!&2H8&`#ASSP;ZwD~G^`>bW8Vf4-QGJUiM)(gI^Wq;4KZHZlW1LX#1ku^) zA4<|+_lJCM#~ZzgS6!U29kFKf{z67vD~lAYaO|LO&O!vS*5r{}U{BE*7N|uWtVAG5 z+WVZBX@*|c^fXR1HIzULtV9)GX!prHu->gNClgwE%x);_fT;Ab%UzxKQH~BT((#W+ zbp`eu)_3j=^SV<35 z(ZI)`-3*rRY@pugt#e@T7`iRHT}p~qidy!XOyp4_G93y!ArG@oA_km#$1Km@L2v$K zRv&$HH5FgtowC7X*Yly1uI?2ZaCxi?^iSY9j4-5Bk8s`5;R@L;1TsRVC-iWFeWXi^ zvNI9XE~j^-2^~PU#6lO#y1UCBmZ-7gmTQT@vAk0y{NTL;^8)<~q0_N*-piuVDZ9Ge z?cw2#zQ*GfTPw<#xZmn!hLH3~H&pE!cxxx6p&2dYhmw6hEV>>(~}Ut7fb9~hjv z7@YPZ_3FBvxgC-HU}oTnMzy1&$&jCS@gE?^N-o(>(laUKLU~=Dx~5Zh#&0L^R*uIC zo^do^7rHYv9s2Wke6uM^*2((EP>D~aPYoy>enI7}h|YcdS@MJT(z}Duab5el?HtI% zt2sirwYJ@9R;$N3c`d2io=X3O8Y{xvrc8=|v(pC96+yc_Y5xi-TZR56y>5`?ArxW+ zBH6Kzu%~omp~_IqS+{*Sqy)TTgMKr+fPuo_zYny9HJMS$(*RdZ2#5x%qo_=Z+vBJM z7(k>O(Z@>;&j{8Ah2?X7N)%}Dycfmy?1$fLPN^xwii%r!Uu z6X4ur1A)nZtdhW>YX~cPe`Ath<&q2ZWZ$zAL6}jUb z$+FBNr+X(ERISd2S=1(r1aCQwv?&Uy@ye`r^ypKB%0c_p`}Qf+0Smwdd(Zq9q>;3m z3@LvIyR`ueUVAW$oC5@C(o?A{>0_cLd%$CX^tN9P(NAo>;Sj4Jp)g&7MQ)(8c9Rk1 z4^X@8o|p<7%qQnyIVKrTNBa<*^vI~xlj4UntO+hKvPfFIh_=p4FuxM(6MBnCf<(W4 z@I#q%^rUyG*F{Ayb5TyEh8I%bIyGmqAO@-nBd7zO0%Q!L962Or;Z!qRZfD&Si(u{Q zl%%Jt)*;NHaG31eog4@*qpjLO2juUvAv0_UW_zudPTDYmxyzs@wXNJi2P6Ui_2^I( zQR5X^E$KPz=A`Gv+J17Sn9N=An)$?^Mr>9MNJXoq+0Qk`(8UBv)0^}E`@%y*MQDGABug2llYDgkV;}t_E1DZP=D}5!S!n5@l~4v^XBZ19V~xt{)({pJ z^vyzf9gxf(TE5#AKSq*z^`lxe-Bg9GpEcihzSnx8(eehT{clODs^a7&4vbxq_0_DSO_)itBy0ki0wUMhdR zhy;&Fvf!^HQvpjDmSpN+euGq{qeBnjwNyqX5J_JdAG+qE`8*KRoj5yYabI^k@JKWR zo_^@*cw%nzI#sdXFCk%(T()@ud9A)`mJU|8303M~9)t8I{~guhKOI4hD$d6Je%``P zhdV&QFw7+^i{a9#O_(kTv;rs9ZZn_CRde_R947tgn(ypqBzRr>Tw>{lu|0ybU8dKV zCRoFCc{rV2_r+j=U#wvns7t&hZKc@_9MP6%t^*wtV)wp{Sf-lvWSAm)9RK(;Bq96G z{6zEmI0?=fIE=6Un#^X9+=m8u&iLnw#HZDHOh^6gHKm{465K}YLAhv!5vpt&Sy0k* z>^u5zsb>i(E|6J*5#K0kLrSH>*z1z`; zhel@2{+C7C|G+Hje&L@xlbr;6&>FCm#qwAib_Psd1gb_sM0gx=Cn2w_OV08AYuu&~ z@@b1PZ}45y!QqTi-4`K@h`@rQ^324_ z>HweF4!qg8Y#=ulA^EXmEwVWzZh8~%dZ%@o@_5pxn8Y;d;Hw51Tx=LJ9r*~N5H^Y!;HoLCFpJ+j@ z->fdXV*EZR=qshSbzdtxN}#M(zKFZqfyte9{xQNU$*@@H5bB1-m(*#-`8_~Akm#$v z90{(1u0kzk$jZ9$$VE^t(!%O)0Al_1o+ii$SxJ$ky{QIJV$Xgf>QtTChi_Q5 zUfG{%D>QF6oN*aYhbh>ZcST))ARYyJO>^}xVp-#QZV-!4{yh|`x32VeiO}rQkR9rr|l`J6isu6IkCDg*35a>HiOOh$73z) zPVK&nSH|{Hg%s--Y~&26HU~5Q*~G7BZ+zQu^KM=%SC6$hTHdhHPY|^m^hFFb9x2_$ ze4jrtdVR@}3&E`TWcjgt8R7r6_g!I8CGENk5Ks`DQ5#W26h^_8AV~%g8k8WpL7FH@ zVk1GKlDYv!B_oo9M4@RwQbQwAM+wp(86>OZEE#OVsm09v`&{g+bDn*-uljka*Q)xe zR;~K#`|5q))uv0ob6TK*`2_A^!M0M_!vku69YR=YdBPU;pb@_k`li0RJ(g{a>Qevy z#Rqi19r?2~=G(4F>UKrwz1)rbPaCu&Qud=bMm{DVM!M2BPDB;?{Uem(&;h4vgIP=> zZe;%cni7n?b2UX->YGeD()-$@l)70wOki(GFSunbwTY}qdt>Hw-VWeLRXH^V_50&# zPY2aLp&7UA`#wc4HiH8t8c*jf#~MES<}=Bo9~xSbgp^3tYv8~){CjAnM48) zs~a#LJL}z3v&RY+4^{>%tr0s+6sps;0wf(vy7EQv?`g`l_FsHiwq5@SN#m`BDFT-I zrdLtUgYAFGQk!@7)N$XLN7-~E2hG6gn|;pc##`OAoFAh_OZ&ni`+Lh2>%0eVU&Vmw zk9l#J;>9uWF-bGg)n++0Bb(#x&Z@0}7#kdt+t{S7oiE#=GR1uX#1wb40xIU>GCsp41)2ByUfKuth{KQzRS7EEnXKV*>OCVutQ8J7eC#>ZoHn>gkea4PeUiqWGIUh$7^ z)!FQJsokDO_op(oXmLJ5K!pR^XJ!P% zN{LTiQ4`D)Acr)eD$PcWMOtqRHShH}+NA9*bW{cQ8($|}@VKBr2f8pwTMLjnhzT{& z1($mDKS5wv($%NQwmB-jPA`O!W(=fuH~96W4r+mP37`#FM9NH97K*H-E{pXchWjxC zV;z~(w{##eTVy{V;a^j zRth!Yf8DJuq6Mk&Z-cy9m1aGr*I(X_KeV{$)}9CG&5Y+lnIU(?pn;o`}`E|G6@<+?V6wT&5jaZFVDN zr1;X#_8!t&$s;6`RF=gL7^P8q^0M^I=^@uz;ProCcXTTWWNIan+hvCw z_CN8qensdv3%O}G$tIP)kS%J&6;m4!7KZ+{tuiaY8GAPlnw9%-bs$#l+Yb;~!5`Qv zE!9O<;>U}Q2R6(B?_?Xut&t+qxoIlXU--wXv zD~yI=S|Bla%8Y7Mu+9K)_kuPpk}BI5^(aX`yW5PHGwwiXPBr zn-LO6=fh!}Q>^LT`321G4{4Y0K_y-DwwsdeSoMA+;M&?;L2cv>>XUi>OgDC`Jj$^F zd>#=*r~@`U9vF^xnoA(7>h+XT&(KTwG-m^lZPtMA7fG9?&sv%rK|*E9 z=e3hhywI5@FhOk*rQi%sUg|KwG=9Trzkf4ZJ7l@0J7KXR6k!%Wdsj<53x7cEB7JZe zv|_vP6OuI3$r=0AH&`PVBc+Ui?BJ2tV(B>yh>b6+YP{OoZg{-k85w~vLxol^fu(5A zNwm~uT<7Jch+CJ6>+5Xwdk^IuWiP72ofngCq20@6n4{zJi1J#vZD#$N)I@Fj?vv8p zthg-BIr$@!-HozbgW&G(*@=n)B+#DB3)ggZbyB8`S}B`cLV0_%>`?1WwoHjThmX%&61KY zOKEBUaC`H3z0bG}5dKSO3rc^cGxpXUwFR&y`v$4S{&&^nuu2aal^(BuD?GwD!z(+Z zZuqpU*^MkV6~R#(%l#;DIsn;Pcrpd$jBUWjdi}x_g&@A!0N9T+oQUs{mDQ5D5Jr90 z0E6j_dD8RN^y%eNI2{8%9A)kJSdG(Q`(CgbD&%vmL5@DsOGnqj2~nPc%e`B!pSxTM z@DSzt1weD*vlgz)_*9g7YB$I$EZ8w0k3h+Bxr{ke0Baw&YUms^6Z)-<{EG0`Fw$PK z_Kr~HEg7)zvX|{`mH<{hK)eqR^5P*ZVaqdlGGa}zZE+3VP&v{nyOwA(u~c3AhORL0fgF6BN5BWyCvG~4vaU^(*1P)njJWpt z&!kq43v6c3n60aPIyvl7nM`i^gh`UBX^&|Jz$8`sP?`Wt9>A{~6B5rl=gCRU4Wem& zvr#rRFCPAuqMMUeITcpH@H4W8ukQGn7I*Lc{V!^VV{ks6n^61Q8!X*`NqZLX23Jal z|5&3gJ-8xR_tp4hhpfkl0^P;di1+W!-+hqONYoU4aW`k^)G*mA0z3{K_i`P-ZVj6` zu$BT+-KlF|aBTWTH((&o*+-YXT{@FFX2PoWbs_$eEaB^qV`fL0mOf@GA#Bcw7p9dG z5c5M$qA)-@5oYU5cugmQylMmR1LE}O5_JHM#{Y7K4fG_wLY;i>Q@&|V7L}+zyS_tn zN6X|k5{mnpM04C!=U9$9Z|G9I$mQUq8yZk{?%NDI(406OdrkJqT@v-)eb%w@6ttjs zkxFZxXP7?as%xU2L}_XEDSJsQ?L|(HJpx21JG@*Z6%zumbZtcb&q+oAXKANlB8`OR z9NHj;B71A2k%X3Loc6rtDX1-PUWr~VwealwZ+^R0Kvb`#y?&;U(B8vB;QvflZi1yv zm-HAR01YV~-nuOd_yWiN$JgdS3gD_5%%e<#?&Q2ZivY4t6Q34H!Uwn)f`5%nxjC=v zMgQ(``>I-qs!Y5XO?uwEB0Xe%PEtg|vQ-OZ+j{pAHN|UgPN?~OS+5m=ul~D5qwl_k z)O4Ct>vH|FKn>koqjp@(OYhf(v~qX*Lz#e%gR3gbprEp|k1|2M+U(v!oROBHj<`J+ zi3!p$5kkuKYUjLEvw!ay9EaU%3tmK1_|?$4n;QAhi@W_HOlS{aVB9%UcN|vS*)XuL z2loI0Qe#ruG{gvz@V8;3*j6v+>r(|hW$l2SevTq+{N-uOx@g6Ab;{c_UR_IEVvMqL z7rjJhF&&cSC}aBfCq2Rm5JovsNnh|WRi~uz)`jXV%4A#iP`X4k-eS)lDp9 zl$-Y6YYXzCoa#@x+w=qx;}ia0{8n^Lq$o*EGV9{2N|}MX=%!o@ zQ1S{8bC7|g9&I@`rmXo|YL;7K^J`Y+S6qKJ`fZRt+yrd)sXSxTUJ<7%z2JS?EQ&V8 zIl5bEt*6&aEYfJp&WW2IA>)Ll)lIDu)b&S}VQ6O}(|m8-yKe%^3l<-fKo=R5WLjrF zsSfc;R&wWH#eEW;Aa%lsF-JuDT#rWvt!`}LNjbc`5jed7npsbL#IO`GK(8+7K0*-j z&;Y%+&Og$@^lE%u`D90DZ*BpW+ zf@U~l->Oj5{Z@hcHMSWSx^iR(E|9K@%0JU2yN;Ps@u?X*U)LmAzD-%O;Xn(1a0BN@ zfEOCbgvL~;LIVZ~5>pHK(D+_Wcxk5h88#mw-a*-q$jgi{#Hh^-tDH>_=_yaA)qPpW zEO!I9jy1U>-S*GI8>C!$vT)sv1I zNf0LE3m%bf?|^|yU+P*NxP47%ug~)u{drx+S z5^D^T793~?;`!`jXwSJCeHvn;9xw|)aDtFWv9vL%Qp>=clE2%s&Sbik1X<^N@j|4l z!fgR`$N(Wa>WZ9U9$2dhCyfzs)=*oC$Oo!Zn!5+8`vg~~V!ck+EPXv%rI*Y!XiSg&YI}J)bfed2v3*)434v>tf&CfKUS1dP5ANml0 z#1n&;eVbtBaU;<8a%8W#|A& z_aRI&+Z;*;CzHJ(z*TmXl>2=^^eoh&M&!>u7A4VnauGiFO#--Uz~T*WMJ-r_>*obz zme>k2OaeK=E7{8*%n79_SL93;)JT-66TTPq!lc`N%=OyrmQw5~^dX;Ke_%h2aX&ii zasAK3IvG2;WmbBN&cR?`onZ~O3%ll`-b0R~=K}5*+X?}aJ?AZN&f{@N3YPY`4nT~6 z5YWaY-UN`a4Ph+l&YB%y{1Yo!)A<$>L*=y#&14eVY~8t(VK;FY}oqU;v>}#veX5G9Y?k;Rd@HZ z<>X+}_K_&S&DyMhnk9T1@1u1)FJ<@3*AYs=Q$i_*{@l&t;=ESZCIW&SaJav*Nv2?* zz`N&BHfYDD-Qai#QtIitR5KSQ!I*v~9{qdWyr5;pAX3lQ1fV|3Hi;X)-zdfaC0@U2 zI@=+#ztcY0^o@QR<5K_P=;;6%OJP3Z%x_)u7t`RqO*&Vg;^PHkJ`eziyw(jQ4~>(Z zb{SFE54A&f7i<9>8zv=9?smdpeKNgV-GC_DlgtoJ3(=caafLt)k5SX{7 z%xvEQ06ipj6eQi&Qajd5zLwU)dSl@>-vdsp|5tynI`DM|9b44^+dUfZhE%f;A~*Lx zay6{~e@%ZW1zz1N;=7pTkUX-))@N9=fD;2zyf( zGrVr?OrzSSB7Hx>z}*y70zgZzS1|m0_t^_ZHgPO0&v6wnhN=BoTNJ0&vu6?s8~F>Q z&3Y5P!m-~T`vUs=C6NOd_p~P?rQw)5>KdmwwLxx5v$6XM60g&ZH$4ZgQrsPl7u-LV zJBB!s>u)A^$R0)Y{{*!73X599$=B`0)NYxIw1IZbYSI_)UB}gF=H5j<;vl6)7b;9fpc;qxV2o?eFi9v zHq=GS1_^fkxZ7)lVV|PJ?Xd&#(5>pUd(S8f&sav|X#SlQSc-e)dLMo&UV$8DZcz~b z@%?&v;8eVTw6nRNN<*o3riuL0Ao$+SHYQ6*#QH^h_-_ABIIPQOAtQ9!2+V;AHJ;v^{ zOK_ZIypgc|F8{rh+ue`f2yKsT%szLpFiqmEskw7YacJm*wrtkC7WKvn%<9DEk+|uK zOBHp^V&Q4@T5S9LWY1EFp@q z$$B(h=;;Vm(h;pU+g)s1o>4Qt0BIJI2$S- z9CtpRWG$r^9oQgZ&^X*aQnR17Y3szf5{T^|YSs}Bb=C^mkWg8Cr;w9h$V0-R0;Yf4 zt&aB&4*N3x1EFE4@bQ5C=;BbLH}LhO-`~BSaXEExR3$-3H*QiaQ@v@^&(AMr))h?; zc4CUD*RUt~Kf&2DHvP9@XTHhhjIGAK@d5xzpeR$4STf!Y^fErr9uhxl1Q=G^UzZ;a z-sfy}#t_}CKl@b^uVrPvpr;sFR{a|DNQ{V+PIjWWPe|tXkUg+QCfsybLsy=lGQFIS zK{6O_YHNF!_wd-O7LpOrigh7=BQbruJFP5zEDjq#D^Yt@&;JQ5oYA%|gvY|7kfLd; zSwGLga-W_+OeT(Q$F|+*xGHI)@+q@{%=gkfio3h4gw|gC$ZqLWORRwTQv8a-tP_8} zbt2oF4y7|yk9*v)(}ld~Ka69?o{Ee-j#z5{=KU(i`K+J%UsTOS2^q6(_NSq1UE^w~ zZmL%6G=0MxRX}a3>e=bg2(kNd zKZ_35z1)!|gf6vzL)qsyn9=>tEGTW7vp1>G&tav5Rj>~nj_ zHh%KJWbuqpIo{zb{+_~tHrl5yV==S_ZM|Q!_q+E|z9cWY z8%bdEV6}=h&$s~SO7_c+6?AADSk*5f_}FqH)L`Cj3a`q7<=j?`i2AVJ7M(2i-q7ie zVl(1=@WHaLHabgD=DLZW@)nZr;@LboQH2zPuGwZ_hmOwPQ`IonrItx;qe;o5nfgd zv>t5O6Ui9x9D+HUOY_aj&Xpg0l;m8#in7DY^?VP-axhSt;f(%UjMo>b-~&08qb>4? zR6Y3}!gz{DW@eE058wlV=B``8dGf1wO(3TVk~U-ppwMg>2E1pk$Es=0c+tYIS>=)i z!}~=kRP0vl^1|)Jw}Kd7Bl?EihzCMl>LhfvevByZ|BxE@?}!151ACv$PU- z{B)#DGVFawtVQb6!r#f6l}E-HM~2Wj`5Lk5dh)_~mWdvN2!Y=5`t6`ZAVQjqE6bql z4wjdnl=(%j_fn$`p}g+>XOn=IC7v#43X$imHqAEf)R6%=CL7ps!L*8;(ajs8dwt}j zyhrsz>bPIs<<7G1-H^3>;)RQcI}C91`8UT_)i{d^x|vIK1ZZPetiApJ_QR5Sr7>5U z!3nbW@6bS|`iZDRZ_6iyN$EQB1n7PU(WXoAb<<^suwJTVZPAD&h{+%1jYoMv>)?1C zQdNp2ipekM?Tv;)Gk}K)#Y7@uzKz+JTk@khrR=XE0P3x+KITlR*n6KH)XjIpFe68hDc^c?egZXm- z2r$jM`j9PKsGQJ;dOHpJHHgUvLpP~uy@g7i28fPhx{mu~b!@L|Gav)r}z&Tq1vPM?}r1Umd6u<)-SWG2PfSQ}}ic|hs?padHCQ10ol)yawJ!) zKPi*&{@_j(NXC-XfATEorobBbzdp07 zLC_};BP)~N^(G~g?7TdK0ez`iTAH5*`mJB%B?c7QTpk4aAW@It`gD6u$miC+kB57W z*EQBSr9CvQ^QmdBYIlmz+{#gAUt4)KZ#H!@n~9WW91@q_u^;9hhL ztXS{@4YiUWy9vG(At&VK@RsDnj%0X!DI zyk^f=1wbDW;O1s{4~u~AJv37Gkrhf0sq?B3%o>@9)_Q!H%7CDe;=^($YL;-5Qz0{! z_wR}R;~!Ce&_x+AC8`!^Elq1e1#=cB{+{New}xV#J3{`N1K+`DSu?LSI@EjyYr{PM zK@EVh&^udjwtNKr2%lk*`x-5`nhU&SiO8E243Memqwpy`iw@4RjX?ha$@N2utp8aL}baJ8Cevcgl{M9xT!w+qs z_b$5e7+6{S!YMian=HZ6*b3#XO=0+ZrUcu`ht|4sg!6R=Ta#`$>a3K{lGJ&f%tAyQ z$NRLYhWU#R{xC_@qh7j~(}3c?Z(a2nCCmM75Pn{+=Qh>~Egb>!Rz`nz z$IcFVFG|@{!VA=LF^PRcoTl}o`rq+2q_1W#|CtdAHQBvtW|i!N(bESqMm7&7rSCaO z6mZ$^*6Oj{p1cXv)?fY@Emfy>A5p6u$+4;TXBVP6Rbgx}Su+(OMw%10<$EVhP2H<4 zsedKs&Whdmc>5QZ#6R=*cLBSN9<|vnA5S`K!y1u$LjD1>n6s=mF9=kB@al@0ZFCQ} z{x!s7I#7t%{3f>XiOH)wn-A<_B{zBExCYNGtz_#@(@}yCEYmOi=j|wDatRX8%LZS0 z`u80%n&lZyI_U%C)SKNUnf~)i=?#i8x#5^yrT^dFM6gUqDFBW2|NZ$N9)kO=2PfQK Wo~XJ^!)6Scf>abW72e)55BxtnQJb6q literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/figs_reserves/reserves_tutorial_unit__to_node_relationships.png b/docs/src/tutorial/figs_reserves/reserves_tutorial_unit__to_node_relationships.png new file mode 100644 index 0000000000000000000000000000000000000000..dc91ea687cc2f76c8d9efc7ee7c505dcf395941e GIT binary patch literal 19508 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%0A$7D!g1EVLz#_uj(rI4_v-xgxO>PL;^rtoT;d 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 Date: Mon, 9 Oct 2023 15:40:14 +0200 Subject: [PATCH 30/33] minor changes (spelling and figure locations) --- docs/src/tutorial/reserves.md | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index ab31c0b13b..515e08cf01 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -11,7 +11,7 @@ Welcome to our tutorial, where we will walk you through the process of adding a - The reserve node has a requirement of 20MW for upwards reserve - Power plants 'a' and 'b' can both provide reserve to this node -![image](../figs_reserves/reserves_tutorial_schematic.png) +![image](figs_reserves/reserves_tutorial_schematic.png) ## Guide @@ -23,16 +23,16 @@ In this tutorial, you will learn how to add a new reserve node to the Simple Sys - Always in the Spine DB editor, locate the *Object tree* (typically at the top-left). Expand the [root] element if not expanded. - Right click on the [node] class, and select *Add objects* from the context menu. The *Add objects* dialog will pop up. -- Enter the names for the new reseve node as seen in the image below, then press *Ok*. This will create a new object of class *node*, called *upward\_reserve\_node*. +- Enter the names for the new reserve node as seen in the image below, then press *Ok*. This will create a new object of class *node*, called *upward\_reserve\_node*. -![image](../figs_reserves/reserves_tutorial_reserve_node.png) +![image](figs_reserves/reserves_tutorial_reserve_node.png) - Right click on the *node* class, and select *Add object group* from the context menu. The *Add object group* dialog will pop up. In the *Group name* field write *upward\_reserve\_group* to refer to this group. Then, add as a members of the group the nodes *electricity\_node* and *upward\_reserve\_node*, as shown in the image below; then press *Ok*. !!! note In SpineOpt, groups of nodes allow the user to create constraints that involve variables from its members. Later in this tutorial, the group named *upward\_reserve\_group* will help to link the flow variables for electricity production and reserve procurement. -![image](../figs_reserves/reserves_tutorial_reserve_group.png) +![image](figs_reserves/reserves_tutorial_reserve_group.png) #### Establishing relationships @@ -40,13 +40,13 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - Right click on the *unit\_\_to_node* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. - Select the names of the two units and their **receiving** nodes, as seen in the image below; then press *Ok*. This will establish that both *power\_plant\_a* and *power\_plant\_b* release energy into both the *upward\_reserve\_node* and the *upward\_reserve\_group*. -![image](../figs_reserves/reserves_tutorial_unit__to_node_relationships.png) +![image](figs_reserves/reserves_tutorial_unit__to_node_relationships.png) - Right click on the *report\_\_output* class, and select *Add relationships* from the context menu. The *Add relationships* dialog will pop up. -- Enter *report1* under *report*, and *variable\_om\_costs* under *output*. Repete the same procedure in the second line to add the *res\_proc\_costs* under *output* as seen in the image below; then press *Ok*. This will write the total *vom\_cost* and *procurement reserve cost* values in the objective function to the output database as a part of *report1*. +- Enter *report1* under *report*, and *variable\_om\_costs* under *output*. Repeat the same procedure in the second line to add the *res\_proc\_costs* under *output* as seen in the image below; then press *Ok*. This will write the total *vom\_cost* and *procurement reserve cost* values in the objective function to the output database as a part of *report1*. -![image](../figs_reserves/reserves_tutorial_report__output_relationships.png) +![image](figs_reserves/reserves_tutorial_report__output_relationships.png) #### Specifying object parameter values @@ -58,13 +58,13 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - *upward_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve procurement must be greater or equal than the reserve demand. -![image](../figs_reserves/reserves_tutorial_reserve_node_parameters.png) +![image](figs_reserves/reserves_tutorial_reserve_node_parameters.png) - Select *upward\_reserve\_group* in the *Object tree*. -- In the *Object parameter* table, select the *balance\_type* parameter and the *Base* alternative, and enter the value *balance\_type\_none* as seen in the image below. This will establish that there is no need create an extra balance between the members of the group. +- In the *Object parameter* table, select the *balance\_type* parameter and the *Base* alternative, and enter the value *balance\_type\_none* as seen in the image below. This will establish that there is no need to create an extra balance between the members of the group. -![image](../figs_reserves/reserves_tutorial_reserve_group_parameters.png) +![image](figs_reserves/reserves_tutorial_reserve_group_parameters.png) #### Specifying relationship parameter values @@ -75,13 +75,13 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v !!! note The value is equal to the unit capacity defined for the electricity node. However, the value can be lower if the unit cannot provide reserves with its total capacity. -![image](../figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png) +![image](figs_reserves/reserves_tutorial_power_plant_a_reserve_capacity.png) - In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_node*. - In the *Relationship parameter* table (typically at the bottom-center), select the *unit\_capacity* parameter and the *Base* alternative, and enter the value *200* as seen in the image below. This will set the capacity to provide reserve for *power\_plant\_b*. -![image](../figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png) +![image](figs_reserves/reserves_tutorial_power_plant_b_reserve_capacity.png) - In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_a | upward\_reserve\_group*. @@ -92,7 +92,7 @@ The value is equal to the unit capacity defined for the electricity node. Howeve !!! note The *ramp\_up\_limit* parameter triggers the [Splitting unit flows into ramps]@(ref) constraint, which links the unit's flow and reserve variables. -![image](../figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png) +![image](figs_reserves/reserves_tutorial_power_plant_a_ramp_up_limit.png) - In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_group*. @@ -100,13 +100,13 @@ The *ramp\_up\_limit* parameter triggers the [Splitting unit flows into ramps]@( - *unit\_capacity* parameter and the *Base* alternative, and enter the value *200*. This will set the total capacity for *power\_plant\_b* in the group. - *ramp\_up\_limit* parameter and the *Base* alternative, and enter the value *1*. This will set the ramping up capacity to 100% of the unit capacity for *power\_plant\_b*. -![image](../figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png) +![image](figs_reserves/reserves_tutorial_power_plant_b_ramp_up_limit.png) -When you're ready, commit all changes to the database. +When you're ready, save/commit all changes to the database. ### Executing the workflow -- Go back to Spine Toolbox's main window, and hit the **Execute project** button ![image](../figs_simple_system/play-circle.png) from the tool bar. You should see 'Executing All Directed Acyclic Graphs' printed in the *Event log* (at the bottom left by default). +- Go back to Spine Toolbox's main window, and hit the **Execute project** button ![image](figs_simple_system/play-circle.png) from the tool bar. You should see 'Executing All Directed Acyclic Graphs' printed in the *Event log* (at the bottom left by default). - Select the 'Run SpineOpt' Tool. You should see the output from SpineOpt in the *Julia Console* after clicking the *object activity control*. @@ -122,11 +122,11 @@ When you're ready, commit all changes to the database. - The *Pivot table* will be populated with results from the SpineOpt run. It will look something like the image below. -![image](../figs_reserves/reserves_tutorial_results_pivot_table.png) +![image](figs_reserves/reserves_tutorial_results_pivot_table.png) As anticipated, the *power\_plant\_b* is supplying the necessary reserve due to its surplus capacity, while *power\_plant\_a* is operating at full capacity. Additionally, in this model, we have not allocated a cost for reserve procurement. One way to double-check it is by selecting *report\_\_model* under **Relationship tree** and look at the costs the *Pivot table*, see image below. -![image](../figs_reserves/reserves_tutorial_results_report__model.png) +![image](figs_reserves/reserves_tutorial_results_report__model.png) So, is it possible to assign costs to this reserve procurement in SpineOpt? Yes, it is indeed possible. @@ -136,13 +136,13 @@ So, is it possible to assign costs to this reserve procurement in SpineOpt? Yes, - In the *Relationship parameter* table (typically at the bottom-center), select the *reserve\_procurement\_cost* parameter and the *Base* alternative, and enter the value *5* as seen in the image below. This will set the cost of providing reserve for *power\_plant\_a*. -![image](../figs_reserves/reserves_tutorial_power_plant_a_res_procurement_cost.png) +![image](figs_reserves/reserves_tutorial_power_plant_a_res_procurement_cost.png) - In *Relationship tree*, expand the *unit\_\_to\_node* class and select *power\_plant\_b | upward\_reserve\_node*. - In the *Relationship parameter* table (typically at the bottom-center), select the *reserve\_procurement\_cost* parameter and the *Base* alternative, and enter the value *35* as seen in the image below. This will set the cost of providing reserve for *power\_plant\_b*. -![image](../figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png) +![image](figs_reserves/reserves_tutorial_power_plant_b_res_procurement_cost.png) **Don't forget to commit the new changes to the database!** @@ -152,8 +152,8 @@ So, is it possible to assign costs to this reserve procurement in SpineOpt? Yes, - Select the output data store and open the Spine DB editor. You can inspect results as before, which should look like the image below. -![image](../figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png) +![image](figs_reserves/reserves_tutorial_results_pivot_table_reserve_cost.png) Since the cost of reserve procurement is way cheaper in *power\_plant\_a* than in *power\_plant\_b*, then the optimal solution is to reduce the production of electricity in *power\_plant\_a* to provide reserve with this unit rather than *power\_plant\_b* as before. By looking at the total costs, we can see that the reserve procurement costs are no longer zero. -![image](../figs_reserves/reserves_tutorial_results_report__model_reserve_cost.png) +![image](figs_reserves/reserves_tutorial_results_report__model_reserve_cost.png) From c58b541ff1994f12acee95836d3256fbe3843b4f Mon Sep 17 00:00:00 2001 From: datejada Date: Tue, 10 Oct 2023 12:48:26 +0200 Subject: [PATCH 31/33] Improve the instructions to open the Desing View --- docs/src/tutorial/reserves.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 515e08cf01..a839e93962 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -17,7 +17,12 @@ Welcome to our tutorial, where we will walk you through the process of adding a ### Entering input data -In this tutorial, you will learn how to add a new reserve node to the Simple System. To begin, please launch the Spine Toolbox and select **File** and then **Open Project** or use the keyboard shortcut **Alt + O** to open the desired project. Afterwards, locate the folder that you saved in the Simple System tutorial and click *Ok*. This will prompt the Simple System workflow to appear in the *Design View* section for you to start working on. +- Launch the Spine Toolbox and select **File** and then **Open Project** or use the keyboard shortcut **Alt + O** to open the desired project. +- Locate the folder that you saved in the Simple System tutorial and click *Ok*. This will prompt the Simple System workflow to appear in the *Design View* section for you to start working on. +- Select the 'input' Data Store item in the *Design View*. +- Go to *Data Store Properties* and hit **Open editor**. This will open the database in the *Spine DB editor*. + +In this tutorial, you will learn how to add a new reserve node to the Simple System. #### Creating objects @@ -54,9 +59,9 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - Locate the *Object parameter* table (typically at the top-center). - In the *Object parameter* table (typically at the top-center), select the following parameter as seen in the image below: - *demand* parameter and the *Base* alternative, and enter the value *20*. This will establish that there's a demand of '20' at the reverse node. - - *is_reserve_node* parameter and the *Base* alternative, and enter the value *True*. This will establish that it is a reverse node. - - *upward_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. - - *nodal_balance_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve procurement must be greater or equal than the reserve demand. + - *is\_reserve\_node* parameter and the *Base* alternative, and enter the value *True*. This will establish that it is a reverse node. + - *upward\_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. + - *nodal\_balance\_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve procurement must be greater or equal than the reserve demand. ![image](figs_reserves/reserves_tutorial_reserve_node_parameters.png) From 07bf8dfb1974bd7e07e7608b7eb8b4c187d68c5c Mon Sep 17 00:00:00 2001 From: Diego Alejandro Tejada Arango <12887482+datejada@users.noreply.github.com> Date: Mon, 16 Oct 2023 09:44:07 +0200 Subject: [PATCH 32/33] Update reserves.md Clarify how to include the upward reserve value in the SpineToolbox interface --- docs/src/tutorial/reserves.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index a839e93962..1ca6c8e677 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -60,7 +60,7 @@ In SpineOpt, groups of nodes allow the user to create constraints that involve v - In the *Object parameter* table (typically at the top-center), select the following parameter as seen in the image below: - *demand* parameter and the *Base* alternative, and enter the value *20*. This will establish that there's a demand of '20' at the reverse node. - *is\_reserve\_node* parameter and the *Base* alternative, and enter the value *True*. This will establish that it is a reverse node. - - *upward\_reserve* parameter and the *Base* alternative, and enter the value *True*. This will establish the direction of the reserve is upwards. + - *upward\_reserve* parameter and the *Base* alternative, then right-click on the value cell and then, in the context menu, select 'Edit...' and select the option *True*. This will establish the direction of the reserve is upwards. - *nodal\_balance\_sense* parameter and the *Base* alternative, and enter the value $\geq$. This will establish that the total reserve procurement must be greater or equal than the reserve demand. ![image](figs_reserves/reserves_tutorial_reserve_node_parameters.png) From 239f3589f9a95bab39c66deab807beef9570b3c9 Mon Sep 17 00:00:00 2001 From: Diego Alejandro Tejada Arango <12887482+datejada@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:56:54 +0200 Subject: [PATCH 33/33] Extend the introduction Add to the introduction a short explanation of what the reserves are and why are important --- docs/src/tutorial/reserves.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/tutorial/reserves.md b/docs/src/tutorial/reserves.md index 1ca6c8e677..876a4110d8 100644 --- a/docs/src/tutorial/reserves.md +++ b/docs/src/tutorial/reserves.md @@ -6,6 +6,8 @@ This tutorial provides a step-by-step guide to include reserve requirements in a Welcome to our tutorial, where we will walk you through the process of adding a new reserve node in SpineOpt using Spine Toolbox. To get the most out of this tutorial, we suggest first completing the Simple System tutorial, which can be found [here](https://spine-tools.github.io/SpineOpt.jl/latest/tutorial/simple_system/). +Reserves refer to the capacity or energy that is kept as a backup to ensure the power system's reliability. This reserve capacity can be brought online automatically or manually in the event of unforeseen system disruptions such as generation failure, transmission line failure, or a sudden increase in demand. Operating reserves are essential to ensure that there is always enough generation capacity available to meet demand, even in the face of unforeseen system disruptions. + ### Model assumptions - The reserve node has a requirement of 20MW for upwards reserve