Skip to content
Snippets Groups Projects
Commit 07be6b5d authored by Victor Dachet's avatar Victor Dachet
Browse files

synthetic_methane_morocco

parent 99be39fe
No related branches found
No related tags found
No related merge requests found
Pipeline #17725 passed
Showing
with 45864 additions and 1 deletion
# Synthetic Methane Morocco
\ No newline at end of file
This directory contains the GBOML models used in the paper
> **Synthetic methane for closing the carbon loop: Comparative study of three
carbon sources for remote carbon-neutral fuel synthetization**
>
> [Michaël Fonder](https://www.uliege.be/cms/c_9054334/fr/repertoire?uid=u225873), Pierre Counotte, [Victor Dachet](https://www.uliege.be/cms/c_9054334/fr/repertoire?uid=u234824), Jehan de Séjournet, and [Damien Ernst](https://www.uliege.be/cms/c_9054334/fr/repertoire?uid=u030242)
In this repository, we use the following denomination for our three carbon sourcing configurations:
* scenario 1 : DAC in Morocco
* scenario 2 : PCCC in Morocco
* scenario 3 : PCCC in Belgium + DAC in Morocco
The sizing of the RREH can be optimized for all the configurations described in the paper by running:
```shell
python run_models.py
```
Most of the data presented in the tables of the paper are derived from the output json file generated for each configuration. Computing the unit cost of each commodity requires some model alterations and cannot be simply derived from these data. To get the commodity cost for our models, we provide the [`commodity_costs.py`](commodity_costs.py) script which can be run to get the table of the commodity costs:
```shell
python commodity_cost.py
```
Output files will be located in a new `commodity_cost_results` directory.
## Dependencies
You need a working installation of GBOML with the python API, and of Gurobi to use the scripts given in this repository. GBOML models can be optimized individually with any working install of GBOML.
## Citation
If you use our work in your research, please consider citing our paper:
```
@article{Fonder2023Synthetic,
title = {Synthetic methane for closing the carbon loop: Comparative study of three carbon sources for remote carbon-neutral fuel synthetization},
author = {Fonder, Micha\"el and Counotte, Pierre and Dachet, Victor and De S\'ejournet, Jehan and Ernst, Damien},
booktitle = {arXiv},
month = {October},
year = {2023}
}
```
import argparse
import gboml_functions as gf
import os
""" Production of a txt file with cost commodity per commodity unit """
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-n1', '--name1', help='Name gboml file scenario 1',
type=str, default=os.path.join('gboml_models','scenario_1.txt'))
parser.add_argument('-n2', '--name2', help='Name gboml file scenario 2',
type=str, default=os.path.join('gboml_models','scenario_2.txt'))
parser.add_argument('-n3', '--name3', help='Name gboml file scenario 3',
type=str, default=os.path.join('gboml_models','scenario_3.txt'))
parser.add_argument('-y', '--years', help='Number of years',
type=int, default=1)
parser.add_argument('-md', '--methane_demand', help='Methane demand in kt / h',
type=float, default=0)
parser.add_argument('-cd', '--co2_demand', help='CO2 demand in kt / h',
type=float, default=0.5)
parser.add_argument('-hd', '--hydrogen_demand', help='Hydrogen demand in kt / h',
type=float, default=1)
parser.add_argument('-wd', '--water_demand', help='Water demand in kt / h',
type=float, default=1)
args = parser.parse_args()
name1 = args.name1
name2 = args.name2
name3 = args.name3
years = args.years
methane_demand = args.methane_demand
co2_demand = args.co2_demand
hydrogen_demand = args.hydrogen_demand
water_demand = args.water_demand
timehorizon = 365*24*years
""" Commodity cost per commodity unit calculation """
""" Values saved in a .txt file """
gf.main(name1,timehorizon,methane_demand,hydrogen_demand,0,0,0,0) # only hydrogen demand
gf.main(name1,timehorizon,methane_demand,0,water_demand,0,0,0) # only water demand
gf.main(name1,timehorizon,methane_demand,0,0,co2_demand,1,0) # only co2 demand in scenario 1
gf.main(name2,timehorizon,methane_demand,0,0,co2_demand,2,0) # only co2 demand in scenario 2
gf.main(name3,timehorizon,methane_demand,0,0,co2_demand,3,1) # only co2 demand in scenario 3 + renewable energy cost
from gboml import GbomlGraph
import gboml.compiler.classes as gcc
import json
import os
def main(file_name, timehorizon, methane_demand, hydrogen_demand, water_demand, co2_demand, scenario, renewable_energy):
""" GBOML graph run """
statut, output_file = gboml_graph_run_and_alteration(file_name, timehorizon, methane_demand, hydrogen_demand, water_demand, co2_demand, scenario)
if statut != 0:
if hydrogen_demand != 0:
commodity = 'hydrogen'
elif water_demand != 0:
commodity = 'water'
elif co2_demand != 0 and scenario == 1:
commodity = 'co2_s1'
elif co2_demand != 0 and scenario == 2:
commodity = 'co2_s2'
elif co2_demand != 0 and scenario == 3:
commodity = 'co2_s3'
else:
exit()
""" Cost calculation """
commodity_price(output_file, commodity, renewable_energy)
else:
exit()
return
def gboml_graph_run(file_name, timehorizon):
""" GBOML graph creation and running """
file_name = os.path.splitext(file_name)[0]
gboml_model = GbomlGraph(timehorizon=timehorizon)
nodes, edges, global_param = gboml_model.import_all_nodes_and_edges(file_name + '.txt')
gboml_model.add_global_parameters(global_param)
gboml_model.add_nodes_in_model(*nodes)
gboml_model.add_hyperedges_in_model(*edges)
gboml_model.build_model()
solution, obj, status, solver_info, constr_info, _ = gboml_model.solve_gurobi()
print("Solved")
gathered_data = gboml_model.turn_solution_to_dictionary(solver_info, status, solution, obj, constr_info)
out_dir = 'model_outputs'
os.makedirs(out_dir, exist_ok=True)
scenario_nbre = os.path.split(file_name)[-1]
out_file = os.path.join(out_dir, scenario_nbre)
with open(out_file + '.json', "w") as fp:
json.dump(gathered_data, fp, indent=4)
print(out_file + '.json saved')
return
def gboml_graph_run_and_alteration(file_name, timehorizon, methane_demand, hydrogen_demand, water_demand, co2_demand, scenario):
# return statut, output_file
# statut = 0 in case of error
file_name = os.path.splitext(file_name)[0]
demand_list = [methane_demand, hydrogen_demand, water_demand, co2_demand]
nb_commodity_different_zero = 0
for i in demand_list:
if i != 0:
nb_commodity_different_zero += 1
if nb_commodity_different_zero > 1:
print("TypeError: There must be only one commodity demand")
return 0, ''
""" GBOML graph creation """
gboml_model = GbomlGraph(timehorizon=timehorizon)
nodes, edges, global_param = gboml_model.import_all_nodes_and_edges(file_name + '.txt')
""" GBOML graph alteration """
for e in edges:
if e.name == 'WATER_BALANCE_HUB':
e.parameters = list(filter(lambda x: x.name != "demand" , e.parameters))
e.parameters.append(gcc.Parameter('demand', gcc.Expression('literal', water_demand)))
if e.name == 'HYDROGEN_BALANCE_HUB':
e.parameters = list(filter(lambda x: x.name != "demand" , e.parameters))
e.parameters.append(gcc.Parameter('demand', gcc.Expression('literal', hydrogen_demand)))
if e.name == 'METHANE_BALANCE_DESTINATION':
e.parameters = list(filter(lambda x: x.name != "demand" , e.parameters))
e.parameters.append(gcc.Parameter('demand', gcc.Expression('literal', methane_demand)))
if e.name == 'CO2_BALANCE_HUB':
e.parameters = list(filter(lambda x: x.name != "demand" , e.parameters))
e.parameters.append(gcc.Parameter('demand', gcc.Expression('literal', co2_demand)))
if scenario == 3 and e.name == 'CO2_PROD_DESTINATION':
conversion_factor_methane = e.parameters[1].expression.evaluate_expression({}) # kt CH4 / kt CO2
e.parameters = list(filter(lambda x: x.name != "demand" , e.parameters))
e.parameters.append(gcc.Parameter('demand', gcc.Expression('literal', co2_demand * conversion_factor_methane)))
""" GBOML graph run with gurobi """
gboml_model.add_global_parameters(global_param)
gboml_model.add_nodes_in_model(*nodes)
gboml_model.add_hyperedges_in_model(*edges)
gboml_model.build_model()
solution, obj, status, solver_info, constr_info, _ = gboml_model.solve_gurobi()
print("Solved")
gathered_data = gboml_model.turn_solution_to_dictionary(solver_info, status, solution, obj, constr_info)
if hydrogen_demand != 0:
commodity_changed = 'hydrogen'
elif water_demand != 0:
commodity_changed = 'water'
elif co2_demand != 0:
commodity_changed = 'co2'
else:
commodity_changed = ''
out_dir = 'commodity_cost_results'
os.makedirs(out_dir, exist_ok=True)
scenario_nbre = os.path.split(file_name)[-1]
out_file = os.path.join(out_dir,scenario_nbre)
with open(out_file + '_' + commodity_changed + '.json', "w") as fp:
json.dump(gathered_data, fp, indent=4)
print(out_file + '_' + commodity_changed + '.json saved')
return 1, out_file + '_' + commodity_changed + '.json'
def save_value_in_file(output_file_name, commodity, cost): # commodity is a string while cost is a float object
with open (output_file_name, 'a') as output_file:
output_file.write('\n')
output_file.write(commodity)
if commodity == 'wind_hub' or commodity =='solar_pv_hub' or commodity == 'wind_be' or commodity == 'solar_pv_be':
output_file.write(' : %lf €/MWh' % cost)
else:
output_file.write(' : %lf €/t' % cost)
print(output_file_name + ' saved')
return
def commodity_price(output_file, commodity, renewable_energy):
out_file_name = os.path.join(os.path.split(output_file)[0], 'commodity_cost.txt')
with open(output_file) as file:
data = json.load(file)
""" Commodity cost calculation """
if commodity == 'hydrogen':
objective = data["solution"]["objective"] # MEur
total_hydrogen_production = sum(data["solution"]["elements"]["ELECTROLYSIS_PLANTS"]["variables"]["hydrogen_out"]["values"]) # kt
commodity_cost = objective * 1000000 / (total_hydrogen_production * 1000) # Eur/t
elif commodity == 'water':
objective = data["solution"]["objective"] # MEur
total_water_production = sum(data["solution"]["elements"]["DESALINATION_PLANTS"]["variables"]["water_out"]["values"]) # kt
commodity_cost = objective * 1000000 / (total_water_production * 1000) # Eur/t
elif commodity == 'co2_s1':
objective = data["solution"]["objective"] # MEur
total_carbon_dioxide1_production = sum(data["solution"]["elements"]["DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION"]["variables"]["co2_out"]["values"]) # kt
commodity_cost = objective * 1000000 / (total_carbon_dioxide1_production * 1000) # Eur/t
elif commodity =='co2_s2':
objective = data["solution"]["objective"] # MEur
total_carbon_dioxide2_production = sum(data["solution"]["elements"]["PIPE_CO2_ON_SHORE_VERY_BIG"]["variables"]["flow_out"]["values"]) # kt
commodity_cost = objective * 1000000 / (total_carbon_dioxide2_production * 1000) # Eur/t
elif commodity == 'co2_s3':
objective = data["solution"]["objective"] # MEur
total_carbon_dioxide3_production = sum(data["solution"]["elements"]["PCCC_BE"]["variables"]["co2_source"]["values"]) # kt
commodity_cost = objective * 1000000 / (total_carbon_dioxide3_production * 1000) # Eur/t
else:
return
save_value_in_file(out_file_name, commodity, commodity_cost)
""" electricity cost calculation """
if renewable_energy != 0:
wind_hub_objective = sum(data["solution"]["elements"]["WIND_PLANTS"]["objectives"]["unnamed"]) # MEur
total_wind_hub_elec_out = sum(data["solution"]["elements"]["WIND_PLANTS"]["variables"]["elec_out"]["values"]) # Gwh
wind_hub_cost = wind_hub_objective * 1000000 / (total_wind_hub_elec_out * 1000) # Eur / MWh
pv_hub_objective = sum(data["solution"]["elements"]["SOLAR_PV_PLANTS"]["objectives"]["unnamed"]) # MEur
total_pv_hub_elec_out = sum(data["solution"]["elements"]["SOLAR_PV_PLANTS"]["variables"]["elec_out"]["values"]) # Gwh
pv_hub_cost = pv_hub_objective * 1000000 / (total_pv_hub_elec_out * 1000) # Eur / MWh
wind_be_objective = sum(data["solution"]["elements"]["WIND_PLANTS_BE"]["objectives"]["unnamed"]) # MEur
total_wind_be_elec_out = sum(data["solution"]["elements"]["WIND_PLANTS_BE"]["variables"]["elec_out"]["values"]) # GWh
wind_be_cost = wind_be_objective * 1000000 / (total_wind_be_elec_out * 1000) # Eur / MWh
pv_be_objective = sum(data["solution"]["elements"]["SOLAR_PV_PLANTS_BE"]["objectives"]["unnamed"]) # MEur
total_pv_be_elec_out = sum(data["solution"]["elements"]["SOLAR_PV_PLANTS_BE"]["variables"]["elec_out"]["values"]) # GWh
pv_be_cost = pv_be_objective * 1000000 / (total_pv_be_elec_out * 1000) # Eur / MWh
save_value_in_file(out_file_name,'wind_hub', wind_hub_cost)
save_value_in_file(out_file_name,'solar_pv_hub', pv_hub_cost)
save_value_in_file(out_file_name,'wind_be', wind_be_cost)
save_value_in_file(out_file_name,'solar_pv_be', pv_be_cost)
return
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
cap_co2 = 0.0;
co2_emission_cost = 0.0;
contingency_10 = 1.1;
contingency_30 = 1.3;
#NODE PCCC_BE
#PARAMETERS
unit_kt_h = 0;
energy_carbon_dioxide = 0;
pre_installed_capacity = 0;
max_capacity = 0.23; // kt - maximum capacity of carbon capture
// data from Berger et al. 2019
capex_existing = 3150.0 * global.contingency_30; // M€/kt/h
fom_existing = 0.0;
vom_existing = 0.0;
lifetime_existing = 20;
// data from Berger et al. 2019
capex = 3150.0 * global.contingency_30; // M€/kt/h
fom = 0.0;
vom = 0.0;
lifetime = 20;
electricity_required_for_CO2 = 0.4125; // MWh/t or GWh/kt
// Other
yearly_capex_existing = capex_existing * global.wacc / (1 - (1 + global.wacc)**(-lifetime_existing));
yearly_capex = capex * global.wacc / (1 - (1 + global.wacc)**(-lifetime));
yearly_existing_cost = (yearly_capex_existing + fom_existing) * global.number_years_horizon * pre_installed_capacity;
max_co2_captured_rate = 0.9;
conversion_factor_methane = 0.364; // kt CH4 / kt CO2
#VARIABLES
external: elec_in[T];
internal: new_capacity;
external: co2_source[T]; //kt/h
external: co2_released[T]; // kt/h
external: co2_captured[T]; // kt/h
#CONSTRAINTS
co2_source[t] == co2_released[t] + co2_captured[t];
co2_captured[t] <= max_co2_captured_rate * co2_source[t];
co2_captured[t] >= 0;
co2_released[t] >= 0;
elec_in[t] >= 0;
new_capacity >= 0;
co2_captured[t] <= new_capacity;
// new_capacity <= max_capacity - pre_installed_capacity; // no hypothesis on maximum capacity of PCCC in belgium
elec_in[t] == electricity_required_for_CO2 * co2_captured[t];
#OBJECTIVES
min: (yearly_capex + fom) * global.number_years_horizon * new_capacity; // M€
min: vom * co2_captured[t]; // M€
min: global.co2_emission_cost * co2_released[t]; // M€
#NODE CO2_STORAGE_BE
#PARAMETERS
full_capex_stock = 1.35 * global.contingency_10;
full_capex_flow = (32.4+16.2) * global.contingency_10;
lifetime_stock = 30.0;
lifetime_flow = 30.0;
annualised_capex_stock = full_capex_stock * global.wacc * (1 + global.wacc)**lifetime_stock / ((1 + global.wacc)**lifetime_stock - 1); // MEur
annualised_capex_flow = full_capex_flow * global.wacc * (1 + global.wacc)**lifetime_flow / ((1 + global.wacc)**lifetime_flow - 1); // MEur
fom_stock = 0.0675;
fom_flow = 1.62 + 0.81; // MEur/(kt/h)-year (carbon dioxide liquefaction + regasification)
vom_stock = 0.0;
vom_flow = 0.0;
conversion_factor_electricity = 0.105;
#VARIABLES
internal: capacity_flow;
internal: capacity_stock;
internal: co2_stored[T];
external: elec_in[T];
external: co2_in[T];
external: co2_out[T];
#CONSTRAINTS
co2_in[t] <= capacity_flow;
co2_out[t] <= capacity_flow;
co2_stored[t] <= capacity_stock;
co2_stored[0] == co2_stored[T-1];
co2_stored[t+1] == co2_stored[t] + co2_in[t] - co2_out[t];
elec_in[t] == conversion_factor_electricity * co2_in[t];
capacity_flow >= 0;
capacity_stock >= 0;
co2_stored[t] >= 0;
co2_in[t] >= 0;
co2_out[t] >= 0;
elec_in[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex_stock + fom_stock) * capacity_stock + global.number_years_horizon * (annualised_capex_flow + fom_flow) * capacity_flow;
min: vom_stock * co2_stored[t] + vom_flow * co2_in[t];
#NODE CCGT_BE
// ASSET data for 2050 for advanced CCGT have been taken as defaults for cost and efficiency parameters
// ens.dk data for 2050 for minimum power and outage
#PARAMETERS
unit_GW = 0;
energy_electricity = 0;
pre_installed_capacity = 0; // GW(e) // DATA From Electricity MAP
max_capacity = 100; // GW(e)
//data from ASSET 2020
capex_existing = 820 * global.contingency_30; // k€/MW(e)
fom_existing = 17; // k€/MW(e)
vom_existing = 1.99 * 1/(10**3); // k€/MWh(e)
lifetime_existing = 25; // years
//data from ASSET 2050
capex = 750 * global.contingency_30; // k€/MW(e)
fom = 15; // k€/MW(e)
vom = 1.73 * 1/(10**3); // k€/MWh(e)
conversion_efficiency = 0.63; // kWh(e)/kWh(ch4_hhv)
self_consumption = 0.0002;
lifetime = 25; // years
// data from ens.dk
min_external_power = 0.4; //
planned_outage = 2/52; // 2 weeks/52
forced_outage = 0.02;
// Others
ramp_rate_up = 1.0; //
ramp_rate_down = 1.0; //
spec_CO2_emission = 0.202; // kt/GWh or t/MWh
nb_year = T/8760;
wacc = 0.07;
//yearly_capex_existing = capex_existing * wacc / (1 - (1 + wacc)**(-lifetime_existing));
yearly_capex = capex * wacc / (1 - (1 + wacc)**(-lifetime));
//yearly_existing_cost = (yearly_capex_existing + fom_existing) * nb_year * pre_installed_capacity;
conversion_factor_methane = 15.42; // GWh/kt
#VARIABLES
internal: new_capacity; // GW(e)
external: methane_in[T]; // kt(ch4)
external: elec_out[T]; // GWh(e)
external: co2_out[T]; // kt(co2)
#CONSTRAINTS
new_capacity >= 0;
pre_installed_capacity + new_capacity <= max_capacity;
min_external_power * (new_capacity + pre_installed_capacity) <= elec_out[t]/(1 - self_consumption);
elec_out[t]/(1 - self_consumption) <= new_capacity + pre_installed_capacity;
elec_out[t]/(1 - self_consumption) == conversion_efficiency * methane_in[t] * conversion_factor_methane;
elec_out[i] - elec_out[i-1] <= ramp_rate_up * (new_capacity + pre_installed_capacity) for i in [1:T-1];
elec_out[i] - elec_out[i-1] >= - ramp_rate_down * (new_capacity + pre_installed_capacity) for i in [1:T-1];
sum(elec_out[i]/(1 - self_consumption) for i in [0:T-1]) <= (1 - forced_outage - planned_outage) * (pre_installed_capacity + new_capacity) * T;
co2_out[t] == spec_CO2_emission * methane_in[t] * conversion_factor_methane;
#OBJECTIVES
min: (yearly_capex + fom) * nb_year * new_capacity ; // M€
min: vom * elec_out[t]; // M€
// min co2_cost: global.co2_emission_cost * co2_out[t];
\ No newline at end of file
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
cap_co2 = 0.0;
co2_emission_cost = 0.0;
contingency_10 = 1.1;
contingency_30 = 1.3;
#NODE DESALINATION_PLANTS
#PARAMETERS
full_capex = 28.08 * global.contingency_30;
lifetime = 20.0;
annualised_capex = full_capex * global.wacc * (1 + global.wacc)**lifetime / ((1 + global.wacc)**lifetime - 1); // MEur
fom = 0.0; // MEur/year
vom = 0.000315;
conversion_factor_electricity = 0.004;
minimum_level = 1.0;
ramp_rate_up = 0.0;
ramp_rate_down = 0.0;
#VARIABLES
internal: capacity; // kt/h - freshwater is the reference flow for sizing
external: elec_in[T];
external: water_out[T];
#CONSTRAINTS
water_out[t] <= capacity;
minimum_level * capacity <= water_out[t];
elec_in[t] == conversion_factor_electricity * water_out[t];
water_out[t] <= water_out[t-1] + ramp_rate_up * capacity;
water_out[t-1] <= water_out[t] + ramp_rate_down * capacity;
capacity >= 0;
elec_in[t] >= 0;
water_out[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * water_out[t];
#NODE WATER_STORAGE
#PARAMETERS
full_capex_stock = 0.065 * global.contingency_10;
full_capex_flow = 1.55923 * global.contingency_10;
lifetime_stock = 30.0;
lifetime_flow = 30.0;
annualised_capex_stock = full_capex_stock * global.wacc * (1 + global.wacc)**lifetime_stock / ((1 + global.wacc)**lifetime_stock - 1); // MEur
annualised_capex_flow = full_capex_flow * global.wacc * (1 + global.wacc)**lifetime_flow / ((1 + global.wacc)**lifetime_flow - 1); // MEur
fom_stock = 0.0013;
fom_flow = 0.0312;
vom_stock = 0.0;
vom_flow = 0.0;
conversion_factor_electricity = 0.00036;
#VARIABLES
internal: capacity_flow;
internal: capacity_stock;
internal: water_stored[T];
external: elec_in[T];
external: water_in[T];
external: water_out[T];
#CONSTRAINTS
water_in[t] <= capacity_flow;
water_out[t] <= capacity_flow;
water_stored[t] <= capacity_stock;
water_stored[0] == water_stored[T-1];
water_stored[t+1] == water_stored[t] + water_in[t] - water_out[t];
elec_in[t] == conversion_factor_electricity * water_in[t];
capacity_flow >= 0;
capacity_stock >= 0;
water_stored[t] >= 0;
water_in[t] >= 0;
water_out[t] >= 0;
elec_in[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex_stock + fom_stock) * capacity_stock + global.number_years_horizon * (annualised_capex_flow + fom_flow) * capacity_flow;
min: vom_stock * water_stored[t] + vom_flow * water_in[t];
#NODE ELECTROLYSIS_PLANTS
#PARAMETERS
full_capex = 800.0 * global.contingency_30;
lifetime = 15.0;
annualised_capex = full_capex * global.wacc * (1 + global.wacc)**lifetime / ((1 + global.wacc)**lifetime - 1); // MEur
fom = 30.0; // MEur/year
vom = 0.0;
conversion_factor_electricity = 53;
conversion_factor_water = 9.0;
minimum_level = 0.05;
#VARIABLES
internal: capacity; // GW - reference flow for sizing is electricity
external: elec_in[T]; // GWh/h
external: water_in[T]; // kt/h
external: hydrogen_out[T]; // kt/h
#CONSTRAINTS
elec_in[t] <= capacity;
minimum_level * capacity <= elec_in[t];
elec_in[t] == conversion_factor_electricity * hydrogen_out[t];
water_in[t] == conversion_factor_water * hydrogen_out[t];
capacity >= 0;
elec_in[t] >= 0;
hydrogen_out[t] >= 0;
water_in[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * elec_in[t];
#NODE HYDROGEN_STORAGE
#PARAMETERS
full_capex_stock = 45.0 * global.contingency_10;
full_capex_flow = 0.0 * global.contingency_10;
lifetime_stock = 30.0;
lifetime_flow = 30.0;
annualised_capex_stock = full_capex_stock * global.wacc * (1 + global.wacc)**lifetime_stock / ((1 + global.wacc)**lifetime_stock - 1); // MEur
annualised_capex_flow = full_capex_flow * global.wacc * (1 + global.wacc)**lifetime_flow / ((1 + global.wacc)**lifetime_flow - 1); // MEur
fom_stock = 2.25;
fom_flow = 0.0;
vom_stock = 0.0;
vom_flow = 0.0;
conversion_factor_electricity = 1.3;
minimum_level = 0.05;
#VARIABLES
internal: capacity_flow;
internal: capacity_stock;
internal: hydrogen_stored[T];
external: elec_in[T];
external: hydrogen_in[T];
external: hydrogen_out[T];
#CONSTRAINTS
hydrogen_in[t] <= capacity_flow;
hydrogen_out[t] <= capacity_flow;
minimum_level * capacity_stock <= hydrogen_stored[t];
hydrogen_stored[t] <= capacity_stock;
hydrogen_stored[0] == hydrogen_stored[T-1];
hydrogen_stored[t+1] == hydrogen_stored[t] + hydrogen_in[t] - hydrogen_out[t];
elec_in[t] == conversion_factor_electricity * hydrogen_in[t];
capacity_flow >= 0;
capacity_stock >= 0;
hydrogen_stored[t] >= 0;
hydrogen_in[t] >= 0;
hydrogen_out[t] >= 0;
elec_in[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex_stock + fom_stock) * capacity_stock + global.number_years_horizon * (annualised_capex_flow + fom_flow) * capacity_flow;
min: vom_stock * hydrogen_stored[t] + vom_flow * hydrogen_in[t];
#NODE METHANATION_PLANTS
#PARAMETERS
HHV_CH4 = 15.441; // GWh / kt
full_capex = 300.0 * global.contingency_30 * HHV_CH4; // to obtain cost in MEur/(kt/h)
lifetime = 20.0;
annualised_capex = full_capex * global.wacc * (1 + global.wacc)**lifetime / ((1 + global.wacc)**lifetime - 1); // MEur
fom = 29.4 * HHV_CH4; // MEur/year
vom = 0.;
conversion_factor_hydrogen = 0.5;
conversion_factor_water = 2.25;
conversion_factor_co2 = 2.75;
conversion_factor_heat = 0.71/5.28; // GW (heat)/ GW (methane)
minimum_level = 1.0;
ramp_rate_up = 0.0;
ramp_rate_down = 0.0;
#VARIABLES
internal: capacity; // kt/h - reference flow for sizing is methane
external: hydrogen_in[T];
external: co2_in[T];
external: methane_out[T];
external: water_out[T];
external: heat_out[T]; // Gwh/h
#CONSTRAINTS
methane_out[t] <= capacity;
minimum_level * capacity <= methane_out[t];
hydrogen_in[t] == conversion_factor_hydrogen * methane_out[t];
co2_in[t] == conversion_factor_co2 * methane_out[t];
water_out[t] == conversion_factor_water * methane_out[t];
heat_out[t] == conversion_factor_heat * HHV_CH4 * methane_out[t];
methane_out[t] <= methane_out[t-1] + ramp_rate_up * capacity;
methane_out[t-1] <= methane_out[t] + ramp_rate_down * capacity;
capacity >= 0;
methane_out[t] >= 0;
hydrogen_in[t] >= 0;
heat_out[t] >= 0;
co2_in[t] >= 0;
water_out[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * methane_out[t];
\ No newline at end of file
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
cap_co2 = 0.0;
co2_emission_cost = 0.0;
contingency_10 = 1.1;
contingency_30 = 1.3;
#NODE DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION // 2030
#PARAMETERS
full_capex = 6000 * global.contingency_30;
lifetime = 20.0;
annualised_capex = full_capex * global.wacc * (1 + global.wacc)**lifetime / ((1 + global.wacc)**lifetime - 1); // MEur
fom = 300; // MEur/kt
vom = 0.0; // MEur/kt
conversion_factor_electricity = 0.15; // Gwh/kt(co2)
conversion_factor_water = 5.0;
heat_consumption = 1.46; // GWh/kt(co2)
LHV_hydrogen = 33.3; // Gwh/kt(h2)
minimum_level = 1.0;
ramp_rate_up = 0.0;
ramp_rate_down = 0.0;
heat_recovery_factor = 0.2; // GWh/kt(co2)
#VARIABLES
internal: capacity; // kt/h - carbon dioxide is the reference flow for sizing
external: elec_in[T];
external: water_in[T];
external: hydrogen_in[T];
external: co2_out[T];
external: heat_in[T]; // GWh from methanation
#CONSTRAINTS
co2_out[t] <= capacity;
minimum_level * capacity <= co2_out[t];
elec_in[t] == conversion_factor_electricity * co2_out[t];
water_in[t] == conversion_factor_water * co2_out[t];
hydrogen_in[t] * LHV_hydrogen + heat_in[t] + heat_recovery_factor * co2_out[t-1] == heat_consumption * co2_out[t];
co2_out[t] <= co2_out[t-1] + ramp_rate_up * capacity;
co2_out[t-1] <= co2_out[t] + ramp_rate_down * capacity;
capacity >= 0;
elec_in[t] >= 0;
water_in[t] >= 0;
hydrogen_in[t] >= 0;
co2_out[t] >= 0;
heat_in[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * co2_out[t];
#NODE DIRECT_AIR_CAPTURE_PLANTS
#PARAMETERS
full_capex = 4801.4 * global.contingency_30;
lifetime = 30.0;
annualised_capex = full_capex * global.wacc * (1 + global.wacc)**lifetime / ((1 + global.wacc)**lifetime - 1); // MEur
fom = 0.0; // MEur/year
vom = 0.0207; // MEur/kt
conversion_factor_electricity = 0.1091;
conversion_factor_water = 5.0;
heat_consumption = 1.46; // GWh/kt(co2)
LHV_hydrogen = 33.3; // Gwh/kt(h2)
minimum_level = 1.0;
ramp_rate_up = 0.0;
ramp_rate_down = 0.0;
max_steam_level = 275/900;
min_hydrogen_level = 600/900;
#VARIABLES
internal: capacity; // kt/h - carbon dioxide is the reference flow for sizing
external: elec_in[T];
//external: hydrogen_in[T];
external: water_in[T];
external: co2_out[T];
//external: heat_in[T]; // GWh from methanation
#CONSTRAINTS
co2_out[t] <= capacity;
minimum_level * capacity <= co2_out[t];
elec_in[t] == conversion_factor_electricity * co2_out[t] + heat_consumption * co2_out[t];
water_in[t] == conversion_factor_water * co2_out[t];
//hydrogen_in[t] * LHV_hydrogen + heat_in[t] == heat_consumption * co2_out[t];
//heat_in[t] <= max_steam_level * heat_consumption * co2_out[t];
//hydrogen_in[t] * LHV_hydrogen >= min_hydrogen_level * heat_consumption * co2_out[t];
co2_out[t] <= co2_out[t-1] + ramp_rate_up * capacity;
co2_out[t-1] <= co2_out[t] + ramp_rate_down * capacity;
capacity >= 0;
elec_in[t] >= 0;
water_in[t] >= 0;
//hydrogen_in[t] >= 0;
co2_out[t] >= 0;
//heat_in[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * co2_out[t];
#NODE POWER_PLANTS
#PARAMETERS
co2_energy_ratio_coal = 0.91; // kt (co2) / GWh
co2_energy_ratio_gas = 0.35; // kt (co2) / GWh
#NODE SAFI_POWER_STATION
#PARAMETERS
annual_yielded_energy = 10000; // GWh
distance_to_hub = 1.6; // km
#VARIABLES
internal: co2_out[T]; // kt (co2)
#CONSTRAINTS
co2_out[t] == POWER_PLANTS.co2_energy_ratio_coal * annual_yielded_energy / (365*24);
co2_out[t] >= 0;
#VARIABLES
internal: co2_out_SAFI[T] <- SAFI_POWER_STATION.co2_out[T];
external: co2_out[T]; // kt (co2)
#CONSTRAINTS
co2_out[t] == co2_out_SAFI[t];
co2_out[t] >= 0.0;
#NODE PCCC
#PARAMETERS
unit_kt_h = 0.0;
energy_co2 = 0.0;
pre_installed_capacity = 0.0;
max_capacity = 5.0; // kt - maximum capacity of carbon capture
//capex_existing = 3150.0 * global.contingency_30; // M€/kt/h
//fom_existing = 0.0;
//vom_existing = 0.0;
//lifetime_existing = 20;
capex = 3150.0 * global.contingency_30; // M€/kt/h
fom = 0.0;
vom = 0.0;
lifetime = 20;
elec_in_required_for_CO2 = 0.4125; // MWh/t or GWh/kt
//yearly_capex_existing = capex_existing * global.wacc / (1 - (1 + global.wacc)**(-lifetime_existing));
yearly_capex = capex * global.wacc / (1 - (1 + global.wacc)**(-lifetime));
//yearly_existing_cost = (yearly_capex_existing + fom_existing) * global.number_years_horizon * pre_installed_capacity;
//ramp_rate_up = 0.0;
//ramp_rate_down = 0.0;
#VARIABLES
internal: new_capacity;
external: elec_in[T];
external: co2_released[T];
external: co2_captured[T];
#CONSTRAINTS
elec_in[t] >= 0;
new_capacity >= 0;
new_capacity <= max_capacity - pre_installed_capacity;
co2_captured[t] >= 0;
co2_released[t] >= 0;
co2_captured[t] <= new_capacity;
elec_in[t] == elec_in_required_for_CO2 * co2_captured[t];
//co2_captured[t] <= co2_captured[t-1] + ramp_rate_up * new_capacity;
//co2_captured[t-1] <= co2_captured[t] + ramp_rate_down * new_capacity;
#OBJECTIVES
min: (yearly_capex + fom) * global.number_years_horizon * new_capacity; // M€
min: vom * co2_captured[t]; // M€
min: global.co2_emission_cost * co2_released[t]; // M€
#NODE CO2_STORAGE
#PARAMETERS
full_capex_stock = 2.3 * global.contingency_10;
full_capex_flow = (55.8+25.1) * global.contingency_10;
lifetime_stock = 30.0;
lifetime_flow = 30.0;
annualised_capex_stock = full_capex_stock * global.wacc * (1 + global.wacc)**lifetime_stock / ((1 + global.wacc)**lifetime_stock - 1); // MEur
annualised_capex_flow = full_capex_flow * global.wacc * (1 + global.wacc)**lifetime_flow / ((1 + global.wacc)**lifetime_flow - 1); // MEur
fom_stock = 0.0675;
fom_flow = 2.79 + 1.25; // MEur/(kt/h)-year (carbon dioxide liquefaction + regasification)
vom_stock = 0.0;
vom_flow = 0.0;
conversion_factor_electricity = 0.014;
#VARIABLES
internal: capacity_flow;
internal: capacity_stock;
internal: co2_stored[T];
external: elec_in[T];
external: co2_in[T];
external: co2_out[T];
#CONSTRAINTS
co2_in[t] <= capacity_flow;
co2_out[t] <= capacity_flow;
co2_stored[t] <= capacity_stock;
co2_stored[0] == co2_stored[T-1];
co2_stored[t+1] == co2_stored[t] + co2_in[t] - co2_out[t];
elec_in[t] == conversion_factor_electricity * co2_in[t];
capacity_flow >= 0;
capacity_stock >= 0;
co2_stored[t] >= 0;
co2_in[t] >= 0;
co2_out[t] >= 0;
elec_in[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex_stock + fom_stock) * capacity_stock + global.number_years_horizon * (annualised_capex_flow + fom_flow) * capacity_flow;
min: vom_stock * co2_stored[t] + vom_flow * co2_in[t];
#NODE PIPE_CO2_ON_SHORE_VERY_BIG // 0.12-0.5 kt/h
// DATA from ENS.DK
#PARAMETERS
length = 1.6; // length of the pipe in km
capex = 2.3 * length * global.contingency_10; // M€/kt/h
fom = 20 * 1/(10**3) * length; // M€/kt/h
vom = 0; // M€/kt
lifetime = 50.0; // years
electricity_required_for_CO2 = 0.00002; //GW/kt/h
efficiency_pipe = 1.0;
yearly_capex = capex * global.wacc / (1 - (1 + global.wacc)**(-lifetime));
#VARIABLES
external: flow_in[T]; // kt/h
external: flow_out[T]; // kt/h
external: elec_in[T]; // GWH(e)
internal: capacity; // kt/h
#CONSTRAINTS
flow_out[t] == efficiency_pipe * flow_in[t];
capacity >= 0;
flow_in[t] >= 0;
flow_in[t] <= capacity;
elec_in[t] == electricity_required_for_CO2 * flow_in[t];
#OBJECTIVES
min: (yearly_capex + fom) * capacity * global.number_years_horizon;
min: vom * flow_in[t];
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
cap_co2 = 0.0;
co2_emission_cost = 0.0;
contingency_10 = 1.1;
contingency_30 = 1.3;
#NODE SOLAR_PV_PLANTS
#PARAMETERS
full_capex = 380.0 * global.contingency_10;
lifetime = 25.0;
annualised_capex = full_capex * global.wacc * (1 + global.wacc)**lifetime / ((1 + global.wacc)**lifetime - 1); // MEur
fom = 7.25; // MEur/year
vom = 0.0;
capacity_factor_PV = import "maroc_pv_capacity_factor_one_year.csv"; // Dimensionless
max_capacity = 500.0; // GW
#VARIABLES
internal: capacity;
external: elec_out[T];
#CONSTRAINTS
elec_out[t] <= capacity_factor_PV[t] * capacity;
capacity <= max_capacity;
capacity >= 0;
elec_out[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * elec_out[t];
#NODE WIND_PLANTS
#PARAMETERS
full_capex = 1040.0 * global.contingency_10;
lifetime = 30.0;
annualised_capex = full_capex * global.wacc * (1 + global.wacc)**lifetime / ((1 + global.wacc)**lifetime - 1); // MEur
fom = 12.6; // MEur/year
vom = 0.00135; // MEur/GWh
capacity_factor_wind = import "maroc_wind_capacity_factor_one_year.csv"; // Dimensionless
max_capacity = 500.0; // GW
#VARIABLES
internal: capacity;
external: elec_out[T];
#CONSTRAINTS
elec_out[t] <= capacity_factor_wind[t] * capacity;
capacity <= max_capacity;
capacity >= 0;
elec_out[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * elec_out[t];
#NODE BATTERY_STORAGE
#PARAMETERS
full_capex_stock = 142.0 * global.contingency_30;
full_capex_flow = 160.0 * global.contingency_30;
lifetime_stock = 10.0;
lifetime_flow = 10.0;
annualised_capex_stock = full_capex_stock * global.wacc * (1 + global.wacc)**lifetime_stock / ((1 + global.wacc)**lifetime_stock - 1); // MEur
annualised_capex_flow = full_capex_flow * global.wacc * (1 + global.wacc)**lifetime_flow / ((1 + global.wacc)**lifetime_flow - 1); // MEur
fom_stock = 0.0;
fom_flow = 0.5;
vom_stock = 0.0018;
vom_flow = 0.0;
charge_discharge_ratio = 1.0;
self_discharge = 0.00004;
efficiency_in = 0.959;
efficiency_out = 0.959;
#VARIABLES
internal: capacity_flow;
internal: capacity_stock;
internal: electricity_stored[T];
external: elec_in[T];
external: elec_out[T];
#CONSTRAINTS
elec_in[t] <= capacity_flow;
elec_out[t] <= charge_discharge_ratio * capacity_flow;
electricity_stored[t] <= capacity_stock;
electricity_stored[0] == electricity_stored[T-1];
electricity_stored[t+1] == (1 - self_discharge) * electricity_stored[t] + efficiency_in * elec_in[t] - elec_out[t] / efficiency_out;
capacity_flow >= 0;
capacity_stock >= 0;
electricity_stored[t] >= 0;
elec_in[t] >= 0;
elec_out[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex_stock + fom_stock) * capacity_stock + global.number_years_horizon * (annualised_capex_flow + fom_flow) * capacity_flow;
min: vom_stock * electricity_stored[t] + vom_flow * elec_in[t];
#NODE HVDC
#PARAMETERS
line_lenght = 650; // km
full_capex_lines = 0.25 * global.contingency_30 * line_lenght;
full_capex_stations = 2 * 115.0 * global.contingency_30;
lifetime_lines = 40.0;
lifetime_stations = 40.0;
annualised_capex_lines = full_capex_lines * global.wacc * (1 + global.wacc)**lifetime_lines / ((1 + global.wacc)**lifetime_lines - 1); // MEur
annualised_capex_stations = full_capex_stations * global.wacc * (1 + global.wacc)**lifetime_stations / ((1 + global.wacc)**lifetime_stations - 1); // MEur
annualised_capex = annualised_capex_lines + annualised_capex_stations; // MEur/GW-year (Lines + Stations)
fom = 2.5 + 4.6; // MEur/year
vom = 0.0;
efficiency_HVDC = 0.985 - 3.5e-5 * line_lenght;
#VARIABLES
internal: capacity;
external: elec_in[T];
external: elec_out[T];
#CONSTRAINTS
elec_in[t] <= capacity;
elec_out[t] == efficiency_HVDC * elec_in[t];
capacity >= 0;
elec_in[t] >= 0;
elec_out[t] >= 0;
#OBJECTIVES
min: global.number_years_horizon * (annualised_capex + fom) * capacity;
min: vom * elec_in[t];
#HYPEREDGE POWER_BALANCE_ELEC_PROD
#CONSTRAINTS
SOLAR_PV_PLANTS.elec_out[t] + WIND_PLANTS.elec_out[t] + BATTERY_STORAGE.elec_out[t] == BATTERY_STORAGE.elec_in[t] + HVDC.elec_in[t];
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
gas_demand = 0.0739299599388333; // kt/h
contingency_10 = 1.1;
contingency_30 = 1.3;
//---- Remote Hub power production ----//
#NODE SOLAR_PV_PLANTS = import SOLAR_PV_PLANTS from "Remote_hub_power_production.gboml";
#NODE WIND_PLANTS = import WIND_PLANTS from "Remote_hub_power_production.gboml";
#NODE BATTERY_STORAGE = import BATTERY_STORAGE from "Remote_hub_power_production.gboml";
#NODE HVDC = import HVDC from "Remote_hub_power_production.gboml";
#HYPEREDGE POWER_BALANCE_ELEC_PROD
#CONSTRAINTS
SOLAR_PV_PLANTS.elec_out[t] + WIND_PLANTS.elec_out[t] + BATTERY_STORAGE.elec_out[t] == BATTERY_STORAGE.elec_in[t] + HVDC.elec_in[t];
//---- Remote hub CH4 production line ----//
#NODE DESALINATION_PLANTS = import DESALINATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE WATER_STORAGE = import WATER_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE ELECTROLYSIS_PLANTS = import ELECTROLYSIS_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE HYDROGEN_STORAGE = import HYDROGEN_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE METHANATION_PLANTS = import METHANATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#HYPEREDGE WATER_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
DESALINATION_PLANTS.water_out[t] + METHANATION_PLANTS.water_out[t] + WATER_STORAGE.water_out[t] == WATER_STORAGE.water_in[t] + ELECTROLYSIS_PLANTS.water_in[t] + demand;
#HYPEREDGE HYDROGEN_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
ELECTROLYSIS_PLANTS.hydrogen_out[t] + HYDROGEN_STORAGE.hydrogen_out[t] == HYDROGEN_STORAGE.hydrogen_in[t] + METHANATION_PLANTS.hydrogen_in[t] + demand;
//---- Commodities transportation ----//
#NODE METHANE_CARRIER = import METHANE_CARRIER from "Commodity_transportation.gboml";
#HYPEREDGE LIQUEFIED_METHANE_BALANCE_HUB
#CONSTRAINTS
METHANE_CARRIER.liquefied_methane_out[t] + METHANE_CARRIER.storage_liquefied_methane_out[t] == METHANE_CARRIER.storage_liquefied_methane_in[t] + METHANE_CARRIER.liquefied_methane_in[t];
#HYPEREDGE POWER_BALANCE_HUB
#CONSTRAINTS
HVDC.elec_out[t] == ELECTROLYSIS_PLANTS.elec_in[t] + HYDROGEN_STORAGE.elec_in[t] + DESALINATION_PLANTS.elec_in[t] + WATER_STORAGE.elec_in[t] + METHANE_CARRIER.elec_in[t];
#HYPEREDGE METHANE_BALANCE_HUB
#CONSTRAINTS
METHANATION_PLANTS.methane_out[t] == METHANE_CARRIER.methane_in[t];
#HYPEREDGE METHANE_BALANCE_DESTINATION
#PARAMETERS
demand = global.gas_demand;
#CONSTRAINTS
METHANE_CARRIER.methane_out[t] == demand;
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
gas_demand = 0.0739299599388333; // kt/h
contingency_10 = 1.1;
contingency_30 = 1.3;
//---- Remote Hub power production ----//
#NODE SOLAR_PV_PLANTS = import SOLAR_PV_PLANTS from "Remote_hub_power_production.gboml";
#NODE WIND_PLANTS = import WIND_PLANTS from "Remote_hub_power_production.gboml";
#NODE BATTERY_STORAGE = import BATTERY_STORAGE from "Remote_hub_power_production.gboml";
#NODE HVDC = import HVDC from "Remote_hub_power_production.gboml";
#HYPEREDGE POWER_BALANCE_ELEC_PROD
#CONSTRAINTS
SOLAR_PV_PLANTS.elec_out[t] + WIND_PLANTS.elec_out[t] + BATTERY_STORAGE.elec_out[t] == BATTERY_STORAGE.elec_in[t] + HVDC.elec_in[t];
//---- Remote hub CO2 management ----//
#NODE DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION = import DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION from "Remote_hub_CO2_management.gboml";
#NODE CO2_STORAGE = import CO2_STORAGE from "Remote_hub_CO2_management.gboml";
#HYPEREDGE CO2_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.co2_out[t] + CO2_STORAGE.co2_out[t] == CO2_STORAGE.co2_in[t] + METHANATION_PLANTS.co2_in[t] + demand;
//---- Remote hub CH4 production line ----//
#NODE DESALINATION_PLANTS = import DESALINATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE WATER_STORAGE = import WATER_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE ELECTROLYSIS_PLANTS = import ELECTROLYSIS_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE HYDROGEN_STORAGE = import HYDROGEN_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE METHANATION_PLANTS = import METHANATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#HYPEREDGE WATER_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
DESALINATION_PLANTS.water_out[t] + METHANATION_PLANTS.water_out[t] + WATER_STORAGE.water_out[t] == WATER_STORAGE.water_in[t] + ELECTROLYSIS_PLANTS.water_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.water_in[t] + demand;
#HYPEREDGE HYDROGEN_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
ELECTROLYSIS_PLANTS.hydrogen_out[t] + HYDROGEN_STORAGE.hydrogen_out[t] == HYDROGEN_STORAGE.hydrogen_in[t] + METHANATION_PLANTS.hydrogen_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.hydrogen_in[t] + demand;
#HYPEREDGE HEAT_BALANCE
#CONSTRAINTS
METHANATION_PLANTS.heat_out[t] >= DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.heat_in[t];
//---- Commodities transportation ----//
#NODE METHANE_CARRIER = import METHANE_CARRIER from "Commodity_transportation.gboml";
#HYPEREDGE LIQUEFIED_METHANE_BALANCE_HUB
#CONSTRAINTS
METHANE_CARRIER.liquefied_methane_out[t] + METHANE_CARRIER.storage_liquefied_methane_out[t] == METHANE_CARRIER.storage_liquefied_methane_in[t] + METHANE_CARRIER.liquefied_methane_in[t];
#HYPEREDGE POWER_BALANCE_HUB
#CONSTRAINTS
HVDC.elec_out[t] == ELECTROLYSIS_PLANTS.elec_in[t] + HYDROGEN_STORAGE.elec_in[t] + DESALINATION_PLANTS.elec_in[t] + WATER_STORAGE.elec_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.elec_in[t] + CO2_STORAGE.elec_in[t] + METHANE_CARRIER.elec_in[t];
#HYPEREDGE METHANE_BALANCE_HUB
#CONSTRAINTS
METHANATION_PLANTS.methane_out[t] == METHANE_CARRIER.methane_in[t];
#HYPEREDGE METHANE_BALANCE_DESTINATION
#PARAMETERS
demand = global.gas_demand;
#CONSTRAINTS
METHANE_CARRIER.methane_out[t] == demand;
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
co2_emission_cost = 0.0;
gas_demand = 0.0739299599388333; // kt/h
contingency_10 = 1.1;
contingency_30 = 1.3;
//---- Remote Hub power production ----//
#NODE SOLAR_PV_PLANTS = import SOLAR_PV_PLANTS from "Remote_hub_power_production.gboml";
#NODE WIND_PLANTS = import WIND_PLANTS from "Remote_hub_power_production.gboml";
#NODE BATTERY_STORAGE = import BATTERY_STORAGE from "Remote_hub_power_production.gboml";
#NODE HVDC = import HVDC from "Remote_hub_power_production.gboml";
#HYPEREDGE POWER_BALANCE_PROD
#CONSTRAINTS
SOLAR_PV_PLANTS.elec_out[t] + WIND_PLANTS.elec_out[t] + BATTERY_STORAGE.elec_out[t] == BATTERY_STORAGE.elec_in[t] + HVDC.elec_in[t];
//---- Remote hub CO2 management ----//
#NODE PCCC = import PCCC from "Remote_hub_CO2_management.gboml";
#NODE CO2_STORAGE = import CO2_STORAGE from "Remote_hub_CO2_management.gboml";
#NODE POWER_PLANTS = import POWER_PLANTS from "Remote_hub_CO2_management.gboml";
#NODE PIPE_CO2_ON_SHORE_VERY_BIG = import PIPE_CO2_ON_SHORE_VERY_BIG from "Remote_hub_CO2_management.gboml";
#HYPEREDGE CO2_CAPTURE
#PARAMETERS
max_co2_captured_rate = 0.9;
#CONSTRAINTS
PCCC.co2_captured[t] <= max_co2_captured_rate * POWER_PLANTS.co2_out[t];
POWER_PLANTS.co2_out[t] == PCCC.co2_captured[t] + PCCC.co2_released[t];
#HYPEREDGE CO2_BALANCE_PIPE
#CONSTRAINTS
PIPE_CO2_ON_SHORE_VERY_BIG.flow_in[t] == PCCC.co2_captured[t];
#HYPEREDGE CO2_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
PIPE_CO2_ON_SHORE_VERY_BIG.flow_out[t] + CO2_STORAGE.co2_out[t] == CO2_STORAGE.co2_in[t] + METHANATION_PLANTS.co2_in[t] + demand;
//---- Remote hub CH4 production line ----//
#NODE DESALINATION_PLANTS = import DESALINATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE WATER_STORAGE = import WATER_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE ELECTROLYSIS_PLANTS = import ELECTROLYSIS_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE HYDROGEN_STORAGE = import HYDROGEN_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE METHANATION_PLANTS = import METHANATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#HYPEREDGE WATER_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
DESALINATION_PLANTS.water_out[t] + METHANATION_PLANTS.water_out[t] + WATER_STORAGE.water_out[t] == WATER_STORAGE.water_in[t] + ELECTROLYSIS_PLANTS.water_in[t] + demand;
#HYPEREDGE HYDROGEN_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
ELECTROLYSIS_PLANTS.hydrogen_out[t] + HYDROGEN_STORAGE.hydrogen_out[t] == HYDROGEN_STORAGE.hydrogen_in[t] + METHANATION_PLANTS.hydrogen_in[t] + demand;
//---- Commodities transportation ----//
#NODE METHANE_CARRIER = import METHANE_CARRIER from "Commodity_transportation.gboml";
#HYPEREDGE LIQUEFIED_METHANE_BALANCE_HUB
#CONSTRAINTS
METHANE_CARRIER.liquefied_methane_out[t] + METHANE_CARRIER.storage_liquefied_methane_out[t] == METHANE_CARRIER.storage_liquefied_methane_in[t] + METHANE_CARRIER.liquefied_methane_in[t];
#HYPEREDGE POWER_BALANCE_HUB
#CONSTRAINTS
HVDC.elec_out[t] == ELECTROLYSIS_PLANTS.elec_in[t] + HYDROGEN_STORAGE.elec_in[t] + DESALINATION_PLANTS.elec_in[t] + WATER_STORAGE.elec_in[t] + PCCC.elec_in[t] + CO2_STORAGE.elec_in[t] + METHANE_CARRIER.elec_in[t] + PIPE_CO2_ON_SHORE_VERY_BIG.elec_in[t];
#HYPEREDGE METHANE_BALANCE_HUB
#CONSTRAINTS
METHANATION_PLANTS.methane_out[t] == METHANE_CARRIER.methane_in[t];
#HYPEREDGE METHANE_BALANCE_DESTINATION
#PARAMETERS
demand = global.gas_demand;
#CONSTRAINTS
METHANE_CARRIER.methane_out[t] == demand;
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
cap_co2 = 0.0;
co2_emission_cost = 0.0;
gas_demand = 0.0739299599388333; // kt/h
contingency_10 = 1.1;
contingency_30 = 1.3;
//---- Remote Hub power production ----//
#NODE SOLAR_PV_PLANTS = import SOLAR_PV_PLANTS from "Remote_hub_power_production.gboml";
#NODE WIND_PLANTS = import WIND_PLANTS from "Remote_hub_power_production.gboml";
#NODE BATTERY_STORAGE = import BATTERY_STORAGE from "Remote_hub_power_production.gboml";
#NODE HVDC = import HVDC from "Remote_hub_power_production.gboml";
#HYPEREDGE POWER_BALANCE_ELEC_PROD
#CONSTRAINTS
SOLAR_PV_PLANTS.elec_out[t] + WIND_PLANTS.elec_out[t] + BATTERY_STORAGE.elec_out[t] == BATTERY_STORAGE.elec_in[t] + HVDC.elec_in[t];
//---- Remote hub CO2 management ----//
#NODE DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION = import DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION from "Remote_hub_CO2_management.gboml";
// #NODE CO2_STORAGE = import CO2_STORAGE from "Remote_hub_CO2_management.gboml";
#HYPEREDGE CO2_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
CO2_CARRIER.co2_out[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.co2_out[t] == METHANATION_PLANTS.co2_in[t] + CO2_CARRIER.HUB_co2_in[t] + demand;
//---- Remote hub CH4 production line ----//
#NODE DESALINATION_PLANTS = import DESALINATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE WATER_STORAGE = import WATER_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE ELECTROLYSIS_PLANTS = import ELECTROLYSIS_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE HYDROGEN_STORAGE = import HYDROGEN_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE METHANATION_PLANTS = import METHANATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#HYPEREDGE POWER_BALANCE_HUB
#CONSTRAINTS
HVDC.elec_out[t] == ELECTROLYSIS_PLANTS.elec_in[t] + HYDROGEN_STORAGE.elec_in[t] + DESALINATION_PLANTS.elec_in[t] + WATER_STORAGE.elec_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.elec_in[t] + METHANE_CARRIER.elec_in[t] + CO2_CARRIER.HUB_elec_in[t];
#HYPEREDGE WATER_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
DESALINATION_PLANTS.water_out[t] + METHANATION_PLANTS.water_out[t] + WATER_STORAGE.water_out[t] == WATER_STORAGE.water_in[t] + ELECTROLYSIS_PLANTS.water_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.water_in[t] + demand;
#HYPEREDGE HYDROGEN_BALANCE_HUB
#PARAMETERS
demand = 0;
#CONSTRAINTS
ELECTROLYSIS_PLANTS.hydrogen_out[t] + HYDROGEN_STORAGE.hydrogen_out[t] == HYDROGEN_STORAGE.hydrogen_in[t] + METHANATION_PLANTS.hydrogen_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.hydrogen_in[t] + demand;
#HYPEREDGE HEAT_BALANCE
#CONSTRAINTS
METHANATION_PLANTS.heat_out[t] >= DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.heat_in[t];
//---- Commodities transportation ----//
#NODE METHANE_CARRIER = import METHANE_CARRIER from "Commodity_transportation.gboml";
#NODE CO2_CARRIER = import CO2_CARRIER from "Commodity_transportation.gboml";
#HYPEREDGE LIQUEFIED_METHANE_BALANCE_HUB
#CONSTRAINTS
METHANE_CARRIER.liquefied_methane_out[t] + METHANE_CARRIER.storage_liquefied_methane_out[t] == METHANE_CARRIER.storage_liquefied_methane_in[t] + METHANE_CARRIER.liquefied_methane_in[t] + CO2_CARRIER.liquefied_methane_in[t];
#HYPEREDGE METHANE_BALANCE_HUB
#CONSTRAINTS
METHANATION_PLANTS.methane_out[t] == METHANE_CARRIER.methane_in[t];
#HYPEREDGE METHANE_BALANCE_DESTINATION
#PARAMETERS
demand = global.gas_demand;
#CONSTRAINTS
METHANE_CARRIER.methane_out[t] == demand;
//---- CO2 capture, Belgium ----//
#NODE PCCC_BE = import PCCC_BE from "Belgium.gboml";
#HYPEREDGE CO2_BALANCE_DESTINATION
#CONSTRAINTS
CO2_CARRIER.BE_co2_in[t] == PCCC_BE.co2_captured[t];
#HYPEREDGE CO2_PROD_DESTINATION
#PARAMETERS
demand = global.gas_demand;
conversion_factor_methane = 0.364; // kt CH4 / kt CO2
#CONSTRAINTS
PCCC_BE.co2_source[t] == demand/conversion_factor_methane;
//---- Hub power generation, Belgium ----//
//#NODE CCGT_BE = import CCGT_BE from "Belgium.gboml";
#NODE SOLAR_PV_PLANTS_BE = import SOLAR_PV_PLANTS from "Remote_hub_power_production.gboml"
with capacity_factor_PV = import "belgium_pv_capacity_factor_one_year.csv";
#NODE WIND_PLANTS_BE = import WIND_PLANTS from "Remote_hub_power_production.gboml"
with capacity_factor_wind = import "belgium_wind_capacity_factor_one_year.csv";
#NODE BATTERY_STORAGE_BE = import BATTERY_STORAGE from "Remote_hub_power_production.gboml";
#NODE HVDC_BE = import HVDC from "Remote_hub_power_production.gboml"
with line_lenght = 50;
#HYPEREDGE POWER_BALANCE_ELEC_PROD_BE
#CONSTRAINTS
SOLAR_PV_PLANTS_BE.elec_out[t] + WIND_PLANTS_BE.elec_out[t] + BATTERY_STORAGE_BE.elec_out[t] == BATTERY_STORAGE_BE.elec_in[t] + HVDC_BE.elec_in[t];
#HYPEREDGE ELEC_BALANCE_DESTINATION
#CONSTRAINTS
HVDC_BE.elec_out[t] == PCCC_BE.elec_in[t] + CO2_CARRIER.BE_elec_in[t];
#TIMEHORIZON
T = 1*8760;
#GLOBAL
wacc = 0.07;
number_years_horizon = T/8760;
cap_co2 = 0.0;
co2_emission_cost = 0.0;
contingency_10 = 1.1;
contingency_30 = 1.3;
gas_demand = 0.0739299599388333;
//---- Remote Hub power production ----//
#NODE SOLAR_PV_PLANTS = import SOLAR_PV_PLANTS from "Remote_hub_power_production.gboml";
#NODE WIND_PLANTS = import WIND_PLANTS from "Remote_hub_power_production.gboml";
#NODE BATTERY_STORAGE = import BATTERY_STORAGE from "Remote_hub_power_production.gboml";
#NODE HVDC = import HVDC from "Remote_hub_power_production.gboml";
#HYPEREDGE POWER_BALANCE_ELEC_PROD
#CONSTRAINTS
SOLAR_PV_PLANTS.elec_out[t] + WIND_PLANTS.elec_out[t] + BATTERY_STORAGE.elec_out[t] == BATTERY_STORAGE.elec_in[t] + HVDC.elec_in[t];
//---- Remote hub CO2 management ----//
#NODE DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION = import DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION from "Remote_hub_CO2_management.gboml";
#NODE CO2_STORAGE = import CO2_STORAGE from "Remote_hub_CO2_management.gboml";
#HYPEREDGE CO2_BALANCE_HUB
#CONSTRAINTS
PIPE_CO2_OFF_SHORE.co2_out[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.co2_out[t] + CO2_STORAGE.co2_out[t] == CO2_STORAGE.co2_in[t] + METHANATION_PLANTS.co2_in[t];
#HYPEREDGE HEAT_BALANCE
#CONSTRAINTS
METHANATION_PLANTS.heat_out[t] >= DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.heat_in[t];
//---- Remote hub CH4 production line ----//
#NODE DESALINATION_PLANTS = import DESALINATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE WATER_STORAGE = import WATER_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE ELECTROLYSIS_PLANTS = import ELECTROLYSIS_PLANTS from "Remote_hub_CH4_production_line.gboml";
#NODE HYDROGEN_STORAGE = import HYDROGEN_STORAGE from "Remote_hub_CH4_production_line.gboml";
#NODE METHANATION_PLANTS = import METHANATION_PLANTS from "Remote_hub_CH4_production_line.gboml";
#HYPEREDGE POWER_BALANCE_HUB
#CONSTRAINTS
HVDC.elec_out[t] == ELECTROLYSIS_PLANTS.elec_in[t] + HYDROGEN_STORAGE.elec_in[t] + DESALINATION_PLANTS.elec_in[t] + WATER_STORAGE.elec_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.elec_in[t] + METHANE_TRANSPORT_STORAGE.HUB_elec_in[t] + PIPE_CO2_OFF_SHORE.elec_in[t];
#HYPEREDGE WATER_BALANCE_HUB
#CONSTRAINTS
DESALINATION_PLANTS.water_out[t] + METHANATION_PLANTS.water_out[t] + WATER_STORAGE.water_out[t] == WATER_STORAGE.water_in[t] + ELECTROLYSIS_PLANTS.water_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.water_in[t];
#HYPEREDGE HYDROGEN_BALANCE_HUB
#CONSTRAINTS
ELECTROLYSIS_PLANTS.hydrogen_out[t] + HYDROGEN_STORAGE.hydrogen_out[t] == HYDROGEN_STORAGE.hydrogen_in[t] + DIRECT_AIR_CAPTURE_PLANTS_BASED_ON_SOLID_ADSORPTION.hydrogen_in[t] + METHANATION_PLANTS.hydrogen_in[t];
//---- Commodities transportation ----//
#NODE METHANE_TRANSPORT_STORAGE = import METHANE_TRANSPORT_STORAGE from "Commodity_transportation.gboml";
#NODE PIPE_CO2_OFF_SHORE = import PIPE_CO2_OFF_SHORE from "Commodity_transportation.gboml";
#HYPEREDGE METHANE_BALANCE_HUB
#CONSTRAINTS
METHANATION_PLANTS.methane_out[t] == METHANE_TRANSPORT_STORAGE.methane_in[t];
#HYPEREDGE METHANE_BALANCE_DESTINATION
#PARAMETERS
demand = global.gas_demand;
#CONSTRAINTS
METHANE_TRANSPORT_STORAGE.PIPE_methane_out[t] + METHANE_TRANSPORT_STORAGE.REG_methane_out[t] == METHANE_TRANSPORT_STORAGE.LIQ_methane_in[t] + demand;
//---- CO2 capture, Belgium ----//
#NODE PCCC_BE = import PCCC_BE from "Belgium.gboml";
#HYPEREDGE CO2_BALANCE_DESTINATION
#CONSTRAINTS
PIPE_CO2_OFF_SHORE.co2_in[t] == PCCC_BE.co2_captured[t];
#HYPEREDGE CO2_PROD_DESTINATION
#PARAMETERS
demand = global.gas_demand;
conversion_factor_methane = 0.364; // kt CH4 / kt CO2
#CONSTRAINTS
PCCC_BE.co2_source[t] == demand/conversion_factor_methane;
//---- Hub power generation, Belgium ----//
//#NODE CCGT_BE = import CCGT_BE from "Belgium.gboml"
#NODE SOLAR_PV_PLANTS_BE = import SOLAR_PV_PLANTS from "Remote_hub_power_production.gboml"
with capacity_factor_PV = import "belgium_pv_capacity_factor_one_year.csv";
#NODE WIND_PLANTS_BE = import WIND_PLANTS from "Remote_hub_power_production.gboml"
with capacity_factor_wind = import "belgium_wind_capacity_factor_one_year.csv";
#NODE BATTERY_STORAGE_BE = import BATTERY_STORAGE from "Remote_hub_power_production.gboml";
#NODE HVDC_BE = import HVDC from "Remote_hub_power_production.gboml"
with line_lenght = 50;
#HYPEREDGE POWER_BALANCE_ELEC_PROD_BE
#CONSTRAINTS
SOLAR_PV_PLANTS_BE.elec_out[t] + WIND_PLANTS_BE.elec_out[t] + BATTERY_STORAGE_BE.elec_out[t] == BATTERY_STORAGE_BE.elec_in[t] + HVDC_BE.elec_in[t];
#HYPEREDGE ELEC_BALANCE_DESTINATION
#CONSTRAINTS
HVDC_BE.elec_out[t] == PCCC_BE.elec_in[t] + METHANE_TRANSPORT_STORAGE.BE_elec_in[t];
This diff is collapsed.
import argparse
import gboml_functions as gf
import os
""" Enable to run gboml files one after the other """
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-if', '--input_files', nargs = '*', help='names gboml files to be run',
type=str, default=[
os.path.join('gboml_models','scenario_1.txt'),
os.path.join('gboml_models','scenario_2.txt'),
os.path.join('gboml_models','scenario_3.txt'),
os.path.join('gboml_models','scenario_3_pipe.txt')])
parser.add_argument('-y', '--years', help='Number of years',
type=int, default=1)
args = parser.parse_args()
files = args.input_files
years = args.years
timehorizon = 365*24*years
for file in files:
gf.gboml_graph_run(file, timehorizon)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment