mirror of
https://github.com/ANL-CEEESA/RELOG.git
synced 2025-12-05 23:38:52 -06:00
Allow product disposal at collection centers
This commit is contained in:
@@ -4,73 +4,132 @@
|
||||
},
|
||||
"products": {
|
||||
"P1": {
|
||||
"transportation cost ($/km/tonne)": [0.015, 0.015],
|
||||
"transportation energy (J/km/tonne)": [0.12, 0.11],
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.015,
|
||||
0.015
|
||||
],
|
||||
"transportation energy (J/km/tonne)": [
|
||||
0.12,
|
||||
0.11
|
||||
],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [0.052, 0.050],
|
||||
"CH4": [0.003, 0.002]
|
||||
"CO2": [
|
||||
0.052,
|
||||
0.050
|
||||
],
|
||||
"CH4": [
|
||||
0.003,
|
||||
0.002
|
||||
]
|
||||
},
|
||||
"initial amounts": {
|
||||
"C1": {
|
||||
"latitude (deg)": 7.0,
|
||||
"longitude (deg)": 7.0,
|
||||
"amount (tonne)": [934.56, 934.56]
|
||||
"amount (tonne)": [
|
||||
934.56,
|
||||
934.56
|
||||
]
|
||||
},
|
||||
"C2": {
|
||||
"latitude (deg)": 7.0,
|
||||
"longitude (deg)": 19.0,
|
||||
"amount (tonne)": [198.95, 198.95]
|
||||
"amount (tonne)": [
|
||||
198.95,
|
||||
198.95
|
||||
]
|
||||
},
|
||||
"C3": {
|
||||
"latitude (deg)": 84.0,
|
||||
"longitude (deg)": 76.0,
|
||||
"amount (tonne)": [212.97, 212.97]
|
||||
"amount (tonne)": [
|
||||
212.97,
|
||||
212.97
|
||||
]
|
||||
},
|
||||
"C4": {
|
||||
"latitude (deg)": 21.0,
|
||||
"longitude (deg)": 16.0,
|
||||
"amount (tonne)": [352.19, 352.19]
|
||||
"amount (tonne)": [
|
||||
352.19,
|
||||
352.19
|
||||
]
|
||||
},
|
||||
"C5": {
|
||||
"latitude (deg)": 32.0,
|
||||
"longitude (deg)": 92.0,
|
||||
"amount (tonne)": [510.33, 510.33]
|
||||
"amount (tonne)": [
|
||||
510.33,
|
||||
510.33
|
||||
]
|
||||
},
|
||||
"C6": {
|
||||
"latitude (deg)": 14.0,
|
||||
"longitude (deg)": 62.0,
|
||||
"amount (tonne)": [471.66, 471.66]
|
||||
"amount (tonne)": [
|
||||
471.66,
|
||||
471.66
|
||||
]
|
||||
},
|
||||
"C7": {
|
||||
"latitude (deg)": 30.0,
|
||||
"longitude (deg)": 83.0,
|
||||
"amount (tonne)": [785.21, 785.21]
|
||||
"amount (tonne)": [
|
||||
785.21,
|
||||
785.21
|
||||
]
|
||||
},
|
||||
"C8": {
|
||||
"latitude (deg)": 35.0,
|
||||
"longitude (deg)": 40.0,
|
||||
"amount (tonne)": [706.17, 706.17]
|
||||
"amount (tonne)": [
|
||||
706.17,
|
||||
706.17
|
||||
]
|
||||
},
|
||||
"C9": {
|
||||
"latitude (deg)": 74.0,
|
||||
"longitude (deg)": 52.0,
|
||||
"amount (tonne)": [30.08, 30.08]
|
||||
"amount (tonne)": [
|
||||
30.08,
|
||||
30.08
|
||||
]
|
||||
},
|
||||
"C10": {
|
||||
"latitude (deg)": 22.0,
|
||||
"longitude (deg)": 54.0,
|
||||
"amount (tonne)": [536.52, 536.52]
|
||||
}
|
||||
"amount (tonne)": [
|
||||
536.52,
|
||||
536.52
|
||||
]
|
||||
}
|
||||
},
|
||||
"disposal limit (tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-1000,
|
||||
-1000
|
||||
]
|
||||
},
|
||||
"P2": {
|
||||
"transportation cost ($/km/tonne)": [0.02, 0.02]
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.02,
|
||||
0.02
|
||||
]
|
||||
},
|
||||
"P3": {
|
||||
"transportation cost ($/km/tonne)": [0.0125, 0.0125]
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.0125,
|
||||
0.0125
|
||||
]
|
||||
},
|
||||
"P4": {
|
||||
"transportation cost ($/km/tonne)": [0.0175, 0.0175]
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.0175,
|
||||
0.0175
|
||||
]
|
||||
}
|
||||
},
|
||||
"plants": {
|
||||
@@ -80,10 +139,19 @@
|
||||
"P2": 0.2,
|
||||
"P3": 0.5
|
||||
},
|
||||
"energy (GJ/tonne)": [0.12, 0.11],
|
||||
"energy (GJ/tonne)": [
|
||||
0.12,
|
||||
0.11
|
||||
],
|
||||
"emissions (tonne/tonne)": {
|
||||
"CO2": [0.052, 0.050],
|
||||
"CH4": [0.003, 0.002]
|
||||
"CO2": [
|
||||
0.052,
|
||||
0.050
|
||||
],
|
||||
"CH4": [
|
||||
0.003,
|
||||
0.002
|
||||
]
|
||||
},
|
||||
"locations": {
|
||||
"L1": {
|
||||
@@ -91,24 +159,54 @@
|
||||
"longitude (deg)": 0.0,
|
||||
"disposal": {
|
||||
"P2": {
|
||||
"cost ($/tonne)": [-10.0, -10.0],
|
||||
"limit (tonne)": [1.0, 1.0]
|
||||
"cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"limit (tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
},
|
||||
"P3": {
|
||||
"cost ($/tonne)": [-10.0, -10.0],
|
||||
"limit (tonne)": [1.0, 1.0]
|
||||
"cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"limit (tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"capacities (tonne)": {
|
||||
"250.0": {
|
||||
"opening cost ($)": [500.0, 500.0],
|
||||
"fixed operating cost ($)": [30.0, 30.0],
|
||||
"variable operating cost ($/tonne)": [30.0, 30.0]
|
||||
"opening cost ($)": [
|
||||
500.0,
|
||||
500.0
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
30.0,
|
||||
30.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
30.0,
|
||||
30.0
|
||||
]
|
||||
},
|
||||
"1000.0": {
|
||||
"opening cost ($)": [1250.0, 1250.0],
|
||||
"fixed operating cost ($)": [30.0, 30.0],
|
||||
"variable operating cost ($/tonne)": [30.0, 30.0]
|
||||
"opening cost ($)": [
|
||||
1250.0,
|
||||
1250.0
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
30.0,
|
||||
30.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
30.0,
|
||||
30.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -117,14 +215,32 @@
|
||||
"longitude (deg)": 0.5,
|
||||
"capacities (tonne)": {
|
||||
"0.0": {
|
||||
"opening cost ($)": [1000, 1000],
|
||||
"fixed operating cost ($)": [50.0, 50.0],
|
||||
"variable operating cost ($/tonne)": [50.0, 50.0]
|
||||
"opening cost ($)": [
|
||||
1000,
|
||||
1000
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
50.0,
|
||||
50.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
50.0,
|
||||
50.0
|
||||
]
|
||||
},
|
||||
"10000.0": {
|
||||
"opening cost ($)": [10000, 10000],
|
||||
"fixed operating cost ($)": [50.0, 50.0],
|
||||
"variable operating cost ($/tonne)": [50.0, 50.0]
|
||||
"opening cost ($)": [
|
||||
10000,
|
||||
10000
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
50.0,
|
||||
50.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
50.0,
|
||||
50.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,14 +258,26 @@
|
||||
"longitude (deg)": 65.0,
|
||||
"disposal": {
|
||||
"P3": {
|
||||
"cost ($/tonne)": [100.0, 100.0]
|
||||
"cost ($/tonne)": [
|
||||
100.0,
|
||||
100.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"capacities (tonne)": {
|
||||
"1000.0": {
|
||||
"opening cost ($)": [3000, 3000],
|
||||
"fixed operating cost ($)": [50.0, 50.0],
|
||||
"variable operating cost ($/tonne)": [50.0, 50.0]
|
||||
"opening cost ($)": [
|
||||
3000,
|
||||
3000
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
50.0,
|
||||
50.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
50.0,
|
||||
50.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -158,9 +286,18 @@
|
||||
"longitude (deg)": 0.20,
|
||||
"capacities (tonne)": {
|
||||
"10000": {
|
||||
"opening cost ($)": [3000, 3000],
|
||||
"fixed operating cost ($)": [50.0, 50.0],
|
||||
"variable operating cost ($/tonne)": [50.0, 50.0]
|
||||
"opening cost ($)": [
|
||||
3000,
|
||||
3000
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
50.0,
|
||||
50.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
50.0,
|
||||
50.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,9 +311,18 @@
|
||||
"longitude (deg)": 100.0,
|
||||
"capacities (tonne)": {
|
||||
"15000": {
|
||||
"opening cost ($)": [0.0, 0.0],
|
||||
"fixed operating cost ($)": [0.0, 0.0],
|
||||
"variable operating cost ($/tonne)": [-15.0, -15.0]
|
||||
"opening cost ($)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
-15.0,
|
||||
-15.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,9 +336,18 @@
|
||||
"longitude (deg)": 50.0,
|
||||
"capacities (tonne)": {
|
||||
"10000": {
|
||||
"opening cost ($)": [0.0, 0.0],
|
||||
"fixed operating cost ($)": [0.0, 0.0],
|
||||
"variable operating cost ($/tonne)": [-15.0, -15.0]
|
||||
"opening cost ($)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"fixed operating cost ($)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
-15.0,
|
||||
-15.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ The **products** section describes all products and subproducts in the simulatio
|
||||
|`transportation energy (J/km/tonne)` | The energy required to transport this product. Must be a time series. Optional.
|
||||
|`transportation emissions (tonne/km/tonne)` | A dictionary mapping the name of each greenhouse gas, produced to transport one tonne of this product along one kilometer, to the amount of gas produced (in tonnes). Must be a time series. Optional.
|
||||
|`initial amounts` | A dictionary mapping the name of each location to its description (see below). If this product is not initially available, this key may be omitted. Must be a time series.
|
||||
| `disposal limit (tonne)` | Total amount of product that can be disposed of across all collection centers. If omitted, all product must be processed. This parameter has no effect on product disposal at plants.
|
||||
| `disposal cost ($/tonne)` | Cost of disposing one tonne of this product at a collection center. If omitted, defaults to zero. This parameter has no effect on product disposal costs at plants.
|
||||
|
||||
Each product may have some amount available at the beginning of each time period. In this case, the key `initial amounts` maps to a dictionary with the following keys:
|
||||
|
||||
@@ -73,7 +75,9 @@ Each product may have some amount available at the beginning of each time period
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [0.052, 0.050],
|
||||
"CH4": [0.003, 0.002]
|
||||
}
|
||||
},
|
||||
"disposal cost ($/tonne)": [-10.0, -12.0],
|
||||
"disposal limit (tonne)": [1.0, 1.0],
|
||||
},
|
||||
"P2": {
|
||||
"transportation cost ($/km/tonne)": [0.022, 0.020]
|
||||
|
||||
@@ -147,6 +147,7 @@ Report showing primary product amounts, locations and marginal costs. Generated
|
||||
| `longitude (deg)` | Longitude of the collection center.
|
||||
| `year` | What year this row corresponds to. This reports includes one row for each year.
|
||||
| `amount (tonne)` | Amount of product available at this collection center.
|
||||
| `amount disposed (tonne)` | Amount of product disposed of at this collection center.
|
||||
| `marginal cost ($/tonne)` | Cost to process one additional tonne of this product coming from this collection center.
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ function build_graph(instance::Instance)::Graph
|
||||
collection_shipping_nodes = ShippingNode[]
|
||||
|
||||
name_to_process_node_map = Dict{Tuple{AbstractString,AbstractString},ProcessNode}()
|
||||
collection_center_to_node = Dict()
|
||||
|
||||
process_nodes_by_input_product =
|
||||
Dict(product => ProcessNode[] for product in instance.products)
|
||||
@@ -27,6 +28,7 @@ function build_graph(instance::Instance)::Graph
|
||||
for center in instance.collection_centers
|
||||
node = ShippingNode(next_index, center, center.product, [], [])
|
||||
next_index += 1
|
||||
collection_center_to_node[center] = node
|
||||
push!(collection_shipping_nodes, node)
|
||||
end
|
||||
|
||||
@@ -83,6 +85,7 @@ function build_graph(instance::Instance)::Graph
|
||||
collection_shipping_nodes,
|
||||
arcs,
|
||||
name_to_process_node_map,
|
||||
collection_center_to_node,
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ mutable struct Graph
|
||||
collection_shipping_nodes::Vector{ShippingNode}
|
||||
arcs::Vector{Arc}
|
||||
name_to_process_node_map::Dict{Tuple{AbstractString,AbstractString},ProcessNode}
|
||||
collection_center_to_node::Dict{CollectionCenter,ShippingNode}
|
||||
end
|
||||
|
||||
function Base.show(io::IO, instance::Graph)
|
||||
|
||||
@@ -37,6 +37,8 @@ function parse(json)::Instance
|
||||
cost = product_dict["transportation cost (\$/km/tonne)"]
|
||||
energy = zeros(T)
|
||||
emissions = Dict()
|
||||
disposal_limit = zeros(T)
|
||||
disposal_cost = zeros(T)
|
||||
|
||||
if "transportation energy (J/km/tonne)" in keys(product_dict)
|
||||
energy = product_dict["transportation energy (J/km/tonne)"]
|
||||
@@ -46,7 +48,25 @@ function parse(json)::Instance
|
||||
emissions = product_dict["transportation emissions (tonne/km/tonne)"]
|
||||
end
|
||||
|
||||
product = Product(product_name, cost, energy, emissions)
|
||||
if "disposal limit (tonne)" in keys(product_dict)
|
||||
disposal_limit = product_dict["disposal limit (tonne)"]
|
||||
end
|
||||
|
||||
if "disposal cost (\$/tonne)" in keys(product_dict)
|
||||
disposal_cost = product_dict["disposal cost (\$/tonne)"]
|
||||
end
|
||||
|
||||
prod_centers = []
|
||||
|
||||
product = Product(
|
||||
product_name,
|
||||
cost,
|
||||
energy,
|
||||
emissions,
|
||||
disposal_limit,
|
||||
disposal_cost,
|
||||
prod_centers,
|
||||
)
|
||||
push!(products, product)
|
||||
prod_name_to_product[product_name] = product
|
||||
|
||||
@@ -66,6 +86,7 @@ function parse(json)::Instance
|
||||
product,
|
||||
center_dict["amount (tonne)"],
|
||||
)
|
||||
push!(prod_centers, center)
|
||||
push!(collection_centers, center)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,6 +13,9 @@ mutable struct Product
|
||||
transportation_cost::Vector{Float64}
|
||||
transportation_energy::Vector{Float64}
|
||||
transportation_emissions::Dict{String,Vector{Float64}}
|
||||
disposal_limit::Vector{Float64}
|
||||
disposal_cost::Vector{Float64}
|
||||
collection_centers::Vector
|
||||
end
|
||||
|
||||
mutable struct CollectionCenter
|
||||
|
||||
@@ -20,13 +20,17 @@ function create_vars!(model::JuMP.Model)
|
||||
graph, T = model[:graph], model[:instance].time
|
||||
model[:flow] =
|
||||
Dict((a, t) => @variable(model, lower_bound = 0) for a in graph.arcs, t = 1:T)
|
||||
model[:dispose] = Dict(
|
||||
model[:plant_dispose] = Dict(
|
||||
(n, t) => @variable(
|
||||
model,
|
||||
lower_bound = 0,
|
||||
upper_bound = n.location.disposal_limit[n.product][t]
|
||||
) for n in values(graph.plant_shipping_nodes), t = 1:T
|
||||
)
|
||||
model[:collection_dispose] = Dict(
|
||||
(n, t) => @variable(model, lower_bound = 0,) for
|
||||
n in values(graph.collection_shipping_nodes), t = 1:T
|
||||
)
|
||||
model[:store] = Dict(
|
||||
(n, t) =>
|
||||
@variable(model, lower_bound = 0, upper_bound = n.location.storage_limit)
|
||||
@@ -131,14 +135,25 @@ function create_objective_function!(model::JuMP.Model)
|
||||
end
|
||||
end
|
||||
|
||||
# Shipping node costs
|
||||
# Plant shipping node costs
|
||||
for n in values(graph.plant_shipping_nodes), t = 1:T
|
||||
|
||||
# Disposal costs
|
||||
add_to_expression!(
|
||||
obj,
|
||||
n.location.disposal_cost[n.product][t],
|
||||
model[:dispose][n, t],
|
||||
model[:plant_dispose][n, t],
|
||||
)
|
||||
end
|
||||
|
||||
# Collection shipping node costs
|
||||
for n in values(graph.collection_shipping_nodes), t = 1:T
|
||||
|
||||
# Disposal costs
|
||||
add_to_expression!(
|
||||
obj,
|
||||
n.location.product.disposal_cost[t],
|
||||
model[:collection_dispose][n, t],
|
||||
)
|
||||
end
|
||||
|
||||
@@ -154,16 +169,29 @@ function create_shipping_node_constraints!(model::JuMP.Model)
|
||||
for n in graph.collection_shipping_nodes
|
||||
model[:eq_balance][n, t] = @constraint(
|
||||
model,
|
||||
sum(model[:flow][a, t] for a in n.outgoing_arcs) == n.location.amount[t]
|
||||
sum(model[:flow][a, t] for a in n.outgoing_arcs) ==
|
||||
n.location.amount[t] + model[:collection_dispose][n, t]
|
||||
)
|
||||
end
|
||||
for prod in model[:instance].products
|
||||
if isempty(prod.collection_centers)
|
||||
continue
|
||||
end
|
||||
expr = AffExpr()
|
||||
for center in prod.collection_centers
|
||||
n = graph.collection_center_to_node[center]
|
||||
add_to_expression!(expr, model[:collection_dispose][n, t])
|
||||
end
|
||||
@constraint(model, expr <= prod.disposal_limit[t])
|
||||
end
|
||||
|
||||
# Plants
|
||||
for n in graph.plant_shipping_nodes
|
||||
@constraint(
|
||||
model,
|
||||
sum(model[:flow][a, t] for a in n.incoming_arcs) ==
|
||||
sum(model[:flow][a, t] for a in n.outgoing_arcs) + model[:dispose][n, t]
|
||||
sum(model[:flow][a, t] for a in n.outgoing_arcs) +
|
||||
model[:plant_dispose][n, t]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,22 +39,25 @@ function get_solution(model::JuMP.Model; marginal_costs = true)
|
||||
end
|
||||
|
||||
# Products
|
||||
if marginal_costs
|
||||
for n in graph.collection_shipping_nodes
|
||||
location_dict = OrderedDict{Any,Any}(
|
||||
"Marginal cost (\$/tonne)" => [
|
||||
round(abs(JuMP.shadow_price(model[:eq_balance][n, t])), digits = 2) for t = 1:T
|
||||
],
|
||||
"Latitude (deg)" => n.location.latitude,
|
||||
"Longitude (deg)" => n.location.longitude,
|
||||
"Amount (tonne)" => n.location.amount,
|
||||
"Dispose (tonne)" =>
|
||||
[JuMP.value(model[:collection_dispose][n, t]) for t = 1:T],
|
||||
)
|
||||
if marginal_costs
|
||||
location_dict["Marginal cost (\$/tonne)"] = [
|
||||
round(abs(JuMP.shadow_price(model[:eq_balance][n, t])), digits = 2) for
|
||||
t = 1:T
|
||||
]
|
||||
end
|
||||
if n.product.name ∉ keys(output["Products"])
|
||||
output["Products"][n.product.name] = OrderedDict()
|
||||
end
|
||||
output["Products"][n.product.name][n.location.name] = location_dict
|
||||
end
|
||||
end
|
||||
|
||||
# Plants
|
||||
for plant in instance.plants
|
||||
@@ -178,13 +181,14 @@ function get_solution(model::JuMP.Model; marginal_costs = true)
|
||||
plant_dict["Total output"][product_name] = zeros(T)
|
||||
plant_dict["Output"]["Send"][product_name] = product_dict = OrderedDict()
|
||||
|
||||
disposal_amount = [JuMP.value(model[:dispose][shipping_node, t]) for t = 1:T]
|
||||
disposal_amount =
|
||||
[JuMP.value(model[:plant_dispose][shipping_node, t]) for t = 1:T]
|
||||
if sum(disposal_amount) > 1e-5
|
||||
skip_plant = false
|
||||
plant_dict["Output"]["Dispose"][product_name] =
|
||||
disposal_dict = OrderedDict()
|
||||
disposal_dict["Amount (tonne)"] =
|
||||
[JuMP.value(model[:dispose][shipping_node, t]) for t = 1:T]
|
||||
[JuMP.value(model[:plant_dispose][shipping_node, t]) for t = 1:T]
|
||||
disposal_dict["Cost (\$)"] = [
|
||||
disposal_dict["Amount (tonne)"][t] *
|
||||
plant.disposal_cost[shipping_node.product][t] for t = 1:T
|
||||
|
||||
@@ -13,6 +13,7 @@ function products_report(solution; marginal_costs = true)::DataFrame
|
||||
df."longitude (deg)" = Float64[]
|
||||
df."year" = Int[]
|
||||
df."amount (tonne)" = Float64[]
|
||||
df."amount disposed (tonne)" = Float64[]
|
||||
df."marginal cost (\$/tonne)" = Float64[]
|
||||
T = length(solution["Energy"]["Plants (GJ)"])
|
||||
for (prod_name, prod_dict) in solution["Products"]
|
||||
@@ -22,6 +23,7 @@ function products_report(solution; marginal_costs = true)::DataFrame
|
||||
latitude = round(location_dict["Latitude (deg)"], digits = 6)
|
||||
longitude = round(location_dict["Longitude (deg)"], digits = 6)
|
||||
amount = location_dict["Amount (tonne)"][year]
|
||||
amount_disposed = location_dict["Dispose (tonne)"][year]
|
||||
push!(
|
||||
df,
|
||||
[
|
||||
@@ -32,6 +34,7 @@ function products_report(solution; marginal_costs = true)::DataFrame
|
||||
year,
|
||||
amount,
|
||||
marginal_cost,
|
||||
amount_disposed,
|
||||
],
|
||||
)
|
||||
end
|
||||
|
||||
@@ -169,6 +169,12 @@
|
||||
},
|
||||
"initial amounts": {
|
||||
"$ref": "#/definitions/InitialAmount"
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"$ref": "#/definitions/TimeSeries"
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"$ref": "#/definitions/TimeSeries"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -40,7 +40,14 @@ using RELOG
|
||||
@test plant.sizes[2].fixed_operating_cost == [30, 30]
|
||||
@test plant.sizes[2].variable_operating_cost == [30, 30]
|
||||
|
||||
p1 = product_name_to_product["P1"]
|
||||
@test p1.disposal_limit == [1.0, 1.0]
|
||||
@test p1.disposal_cost == [-1000.0, -1000.0]
|
||||
|
||||
p2 = product_name_to_product["P2"]
|
||||
@test p2.disposal_limit == [0.0, 0.0]
|
||||
@test p2.disposal_cost == [0.0, 0.0]
|
||||
|
||||
p3 = product_name_to_product["P3"]
|
||||
@test length(plant.output) == 2
|
||||
@test plant.output[p2] == 0.2
|
||||
|
||||
@@ -18,7 +18,7 @@ using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats
|
||||
)
|
||||
|
||||
@test length(model[:flow]) == 76
|
||||
@test length(model[:dispose]) == 16
|
||||
@test length(model[:plant_dispose]) == 16
|
||||
@test length(model[:open_plant]) == 12
|
||||
@test length(model[:capacity]) == 12
|
||||
@test length(model[:expansion]) == 12
|
||||
@@ -32,7 +32,7 @@ using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 750.0
|
||||
|
||||
v = model[:dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1]
|
||||
v = model[:plant_dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1]
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 1.0
|
||||
end
|
||||
|
||||
@@ -26,6 +26,15 @@ basedir = dirname(@__FILE__)
|
||||
@test "F2" in keys(solution["Plants"])
|
||||
@test "F3" in keys(solution["Plants"])
|
||||
@test "F4" in keys(solution["Plants"])
|
||||
|
||||
@test "Products" in keys(solution)
|
||||
@test "P1" in keys(solution["Products"])
|
||||
@test "C1" in keys(solution["Products"]["P1"])
|
||||
@test "Dispose (tonne)" in keys(solution["Products"]["P1"]["C1"])
|
||||
|
||||
total_disposal =
|
||||
sum([loc["Dispose (tonne)"] for loc in values(solution["Products"]["P1"])])
|
||||
@test total_disposal == [1.0, 1.0]
|
||||
end
|
||||
|
||||
@testset "solve (heuristic)" begin
|
||||
|
||||
Reference in New Issue
Block a user