Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model sedos steel sector #101

Draft
wants to merge 81 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
45c3ff0
Commenting
FelixMau Jul 9, 2024
5730321
Typo and uncomment
SabineHaas Jul 9, 2024
55c3792
Add results processing
SabineHaas Jul 9, 2024
876eed3
Adding color logging
FelixMau Jul 9, 2024
f63c921
Linting and adding .env file
FelixMau Jul 9, 2024
866d83e
Bugfix
FelixMau Jul 18, 2024
a576a53
Merge branch 'feature/handle_nans' into feature/extend_steel_example
FelixMau Jul 23, 2024
b98074d
Extend `parameter_name` mapping
FelixMau Jul 30, 2024
59f71d0
Better warning
FelixMau Jul 30, 2024
547e963
Better loggin in builder
FelixMau Jul 30, 2024
525bde6
Update dependencies
FelixMau Jul 30, 2024
80bf167
pre commit
FelixMau Jul 31, 2024
c4cd98a
Start adapters for GHG facades
SabineHaas Aug 20, 2024
06fa64d
Recalculate amount like capacity
FelixMau Aug 21, 2024
5ece641
Write adapters for GHG facades
SabineHaas Aug 22, 2024
47f554e
Check that needed buses are defined
SabineHaas Aug 22, 2024
816fc42
Rename emission_factors from ef_.. in MimoAdapter
SabineHaas Aug 22, 2024
c990867
Add Modelstruktur.xlsx with GHG Adapters
SabineHaas Aug 22, 2024
b12b415
Merge branch 'feature/extend_steel_example' into feature/add_adapters
SabineHaas Aug 22, 2024
2b0dc5c
Apply black
SabineHaas Aug 22, 2024
9a03cf9
Add debug mode with 5 time steps per period
SabineHaas Aug 26, 2024
7fa288c
apply black
SabineHaas Aug 26, 2024
1a51d3c
Remove check that does not work
SabineHaas Aug 26, 2024
97429b0
Merge pull request #97 from sedos-project/feature/add_adapters
SabineHaas Aug 26, 2024
2775034
Add to .gitignore
SabineHaas Sep 4, 2024
345f2dc
Remove hard coded number
SabineHaas Sep 4, 2024
a1daa73
Bugfix in debug mode
SabineHaas Oct 10, 2024
be539f1
Add 'infite' amount 9999999999999 to commodities that are missing amount
SabineHaas Oct 14, 2024
c065665
Adapt emission factors to naming convention of oemof.tabular
SabineHaas Oct 14, 2024
02fd1ef
Merge branch 'feature/extend_steel_example' into feature/amount-muss-…
SabineHaas Oct 22, 2024
670bf26
Fix use of decomission() for 'amount'
SabineHaas Oct 28, 2024
9fd1053
Merge pull request #96 from sedos-project/feature/amount-muss-als-num…
SabineHaas Oct 29, 2024
b37c533
Convert dict with array to str for type guessing to work
SabineHaas Oct 29, 2024
db1ba4c
import json
SabineHaas Oct 29, 2024
982dbeb
add missing changes due to transfer
SabineHaas Oct 29, 2024
3c323a0
Prevent error in case of empty bus_map
SabineHaas Oct 29, 2024
6106256
Change input parameters in case of no outputs
SabineHaas Oct 29, 2024
425dbb8
Adapt profile in case of amount changing over years
SabineHaas Oct 30, 2024
39a85e2
Install bug fix with data_adapter
SabineHaas Oct 30, 2024
88fb00b
Make function name more generic
SabineHaas Nov 5, 2024
c09022e
Extend max to time series over all time steps of each period
SabineHaas Nov 5, 2024
775a234
Answer FutureWarning of DataFrame concatenation
SabineHaas Nov 5, 2024
bc635be
Remove unnecessary parameter
SabineHaas Nov 5, 2024
ffe8ad3
Correct logging info for better understanding
SabineHaas Nov 5, 2024
6ca11c2
Initialize EmissionConstraintAdapter
SabineHaas Nov 7, 2024
7611602
Remove line, max time series is added in build_datapackage
SabineHaas Nov 11, 2024
96a18c7
Convert availablity_constant to full_load_time_max
SabineHaas Nov 11, 2024
bea8f1d
Add author and fix typo
SabineHaas Nov 11, 2024
92bf37b
Remove empty default_pre_mapping_calculations from mimo adapter to ma…
SabineHaas Nov 11, 2024
e487795
Adding expandable parameter to investment processes
SabineHaas Nov 14, 2024
bf3aa4f
Add bug fix for biogas treatment
SabineHaas Nov 14, 2024
a0f7819
Add parameter primary in mimo adapter and drop 'primary' from foreign…
SabineHaas Nov 14, 2024
58b27f7
Update oemof industry installation branch
SabineHaas Nov 14, 2024
3f3c11d
Bugfix add lifetime to x2x_other_biogas_treatment
SabineHaas Nov 14, 2024
237ec6f
Install main branch of data_adapter
SabineHaas Nov 15, 2024
bc0dae6
Update pyproject.toml
SabineHaas Nov 18, 2024
5b0d97e
Adapt oemof-tabular installation
SabineHaas Nov 18, 2024
28999d7
Correct error
SabineHaas Nov 18, 2024
5664f50
Merge branch 'feature/extend_steel_example' into feature/EmissionCons…
SabineHaas Dec 2, 2024
6a09abf
Fill EmissionConstraintAdapter and add constraint to dp
SabineHaas Dec 2, 2024
7515780
replace quotes with # to make a json.loads easier later
SabineHaas Dec 2, 2024
2752e9a
Get process units
SabineHaas Dec 3, 2024
1a47bed
Merge pull request #99 from sedos-project/feature/EmissionConstraintA…
SabineHaas Dec 3, 2024
b788518
Merge branch 'feature/extend_steel_example' of github.com:sedos-proje…
SabineHaas Dec 3, 2024
14dedb4
Update oemof industry installation
SabineHaas Dec 3, 2024
b303bff
Commit missin intiizalization of units dict
SabineHaas Dec 10, 2024
813babd
Put max parameter back to output_parameters
SabineHaas Dec 10, 2024
a319912
Debug mode has 24 steps by default
SabineHaas Dec 10, 2024
26c513e
Move function to calculations
SabineHaas Dec 12, 2024
61b20e6
parameter changed by decommission() depending on
SabineHaas Dec 12, 2024
feb2856
decomissioning via flow shares for mimo
SabineHaas Dec 12, 2024
473e519
Remove line
SabineHaas Dec 12, 2024
a64e494
Move reduce_data_frame func
SabineHaas Dec 12, 2024
d812bdf
reduce max_time_series as debugging mode is used in sedos
SabineHaas Dec 12, 2024
2f1ef83
Set debug mode to 24 time steps per period
SabineHaas Dec 12, 2024
f986f23
Corrections
SabineHaas Dec 12, 2024
a84a61a
Merge branch 'feature/use_flow_shares_for_mimos' into local/steel_flo…
SabineHaas Dec 12, 2024
5818f7d
Correct indent
SabineHaas Dec 12, 2024
cd150ba
Stepsize is 23 in debug mode
SabineHaas Dec 12, 2024
9b6bbd0
Merge branch 'sedos/steel_flow_shares' into sedos/steel_sector
SabineHaas Dec 19, 2024
735627b
Merge branch 'dev' into sedos/steel_sector
SabineHaas Dec 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ __pycache__/
/tests/_files/tabular_datapackage_hack_a_thon/data/
/tests/_files/tabular_datapackage_hack_a_thon/datapackage.json
/tests/_files/tabular_datapackage_mininmal_example/
/tests/_files/tsam/*
/examples/industry/collections/*
/examples/industry/datapackage/*
212 changes: 194 additions & 18 deletions data_adapter_oemof/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from oemof.tabular import facades
from oemof.tabular._facade import Facade
from oemof_industry.mimo_converter import MIMO
from oemof_industry.emission_constraint import CO2EmissionLimit

from data_adapter_oemof import calculations

Expand All @@ -35,6 +36,7 @@ class Adapter:
Field(name="name", type=str),
Field(name="region", type=str),
Field(name="year", type=int),
Field(name="full_load_time_max", type=float),
)
output_parameters = (Field(name="max", type=float), Field(name="min", type=float))
input_parameters = ()
Expand Down Expand Up @@ -158,7 +160,10 @@ def get_data(self, key, field_type: Optional[Type] = None):
f"Using existing timeseries column '{timeseries_key}'."
)
return timeseries_key
logger.warning(f"Could not find timeseries entry for mapped key '{key}'")
logger.warning(
f"For Process {self.process_name}"
f"Could not find timeseries entry for mapped key '{key}'"
)
return None

# 2 Use defaults
Expand Down Expand Up @@ -213,11 +218,12 @@ def get_busses(self) -> dict:
bus_dict = {}
for bus in bus_occurrences_in_fields: # emission_bus
# 1. Check for existing mappings
try:
bus_dict[bus] = self.bus_map[self.__class__.__name__][bus]
continue
except KeyError:
pass
if self.bus_map:
try:
bus_dict[bus] = self.bus_map[self.__class__.__name__][bus]
continue
except KeyError:
pass

# TODO: Make use of Parameter [stuct.csv]?
# Do we need parameter specific Bus structure? Maybe for multiple in/output?
Expand All @@ -236,6 +242,11 @@ def get_busses(self) -> dict:
busses = struct["inputs"]
if bus == "to_bus":
busses = struct["outputs"]
if (
self.__class__.type == "storage"
and struct["inputs"] == struct["outputs"]
):
busses = struct["outputs"]
if len(busses) != 1:
raise MappingError(
f"Could not map {bus} to default bus - too many options"
Expand Down Expand Up @@ -326,25 +337,68 @@ def default_pre_mapping_calculations(self):

"""
calculations.normalize_activity_bonds(self)
calculations.process_availability_constant_to_full_load_time_max(self)

def default_post_mapping_calculations(self, mapped_defaults):
"""
Does default calculations#

I. Decommissioning of existing Capacities
II. Rounding lifetime down to integers
I. Decommissioning of existing Capacities (processes _0) and add
`expandable = True` if process is expandable (_1, _2, not _0)
II. Reformatting of amount in case amount is not a number
a) Multiply timeseries by the repeoctiv yearly amount
b) Analogous to decommissioning of capacities
III. Rounding lifetime down to integers

Returns
-------

"""
if mapped_defaults["type"] == "mimo":
parameter_name = f"flow_share_max_{mapped_defaults['primary']}"
elif len(self.structure["outputs"]) == 0:
parameter_name = "input_parameters"
else:
parameter_name = "output_parameters"

# I:
if self.process_name[-1] == "0":
mapped_defaults = calculations.decommission(
process_name=self.process_name, adapter_dict=mapped_defaults
process_name=self.process_name,
adapter_dict=mapped_defaults,
column="capacity",
change_parameter=parameter_name,
)
elif self.process_name[-1] == "1" or self.process_name[-1] == "2":
mapped_defaults["expandable"] = True
elif "x2x_other_biogas_treatment" in self.process_name:
mapped_defaults["expandable"] = True
logging.warning(
"Setting capacity cost of x2x_other_biogas_treatment to 0 and "
"life time to 20 as this is missing in the data.")
mapped_defaults["capacity_cost"] = 0
mapped_defaults["lifetime"] = 20

# II:
if "amount" in mapped_defaults.keys():
# a)
if "profile" in mapped_defaults.keys():
self.timeseries = calculations.adapt_profile_with_yearly_value(
profile=self.timeseries,
value=mapped_defaults["amount"]
)
mapped_defaults["amount"] = 1

# b)
else:
mapped_defaults = calculations.decommission(
process_name=self.process_name,
adapter_dict=mapped_defaults,
column="amount",
change_parameter=parameter_name,
)

# III:
if "lifetime" in mapped_defaults.keys():
mapped_defaults = calculations.floor_lifetime(mapped_defaults)

Expand Down Expand Up @@ -420,6 +474,53 @@ def get_default_parameters(
if self.get("carrier") == "carrier":
defaults["carrier"] = self.get_busses()["bus"]

if self.get("amount") == None:
amount = 9999999999999
logger.warning(
f"Adding parameter 'amount' with value {amount} to commodity "
f"{self.process_name}. \n "
f"This is beneficial if your commodity is functioning as "
f"shortage or unlimited import/source. "
f"Otherwise please add 'amount' to your commodity!"
)
defaults["amount"] = amount

return defaults


class CommodityGHGAdapter(CommodityAdapter):
"""
CommodityGHGAdapter
"""

type = "commodity_ghg"
facade = facades.CommodityGHG

def get_busses(self) -> dict:
bus_list = self.structure["outputs"]
bus_dict = {}
counter = 0
for bus in bus_list:
if not bus.startswith("emi"):
bus_dict["bus"] = bus
elif bus.startswith("emi"):
bus_dict[f"emission_bus_{counter}"] = bus
counter += 1
return bus_dict

def get_default_parameters(self) -> dict:
defaults = super().get_default_parameters()
for key, value in self.data.items():
if key.startswith("ef"):
# adapt to the naming convention in oemof.tabular commodityGHG facade: emission_factor_<emission_bus_label>
target_label = None
emission_bus_labels = [key for item, key in defaults.items() if item.startswith("emission_bus")]
for label in emission_bus_labels:
if label in key:
target_label = label
if target_label == None:
raise ValueError(f"Emission factor of {self.process_name} is named {key} but None of the emission buses matches: {emission_bus_labels}.")
defaults[f"emission_factor_{target_label}"] = value
return defaults


Expand All @@ -433,6 +534,44 @@ class ConversionAdapter(Adapter):
facade = facades.Conversion


class ConversionGHGAdapter(Adapter):
"""
ConversionGHGAdapter
"""

type = "conversion_ghg"
facade = facades.ConversionGHG

def get_busses(self) -> dict:
def get_bus_from_struct(bus_list: list, bus_key: str) -> dict:
bus_dict = {}
counter = 0
for bus in bus_list:
if not bus.startswith("emi"):
bus_dict[f"{bus_key}"] = bus
elif bus.startswith("emi"):
bus_dict[f"emission_bus_{counter}"] = bus
counter += 1
return bus_dict

return_bus_dict = get_bus_from_struct(
self.structure["inputs"], bus_key="from_bus"
) | get_bus_from_struct(self.structure["outputs"], bus_key="to_bus")

# check that from_bus and to_bus is defined
for key in ["from_bus", "to_bus"]:
if return_bus_dict.get(key) is None:
raise KeyError(f"{self.process_name} is missing {key}.")
return return_bus_dict

def get_default_parameters(self) -> dict:
defaults = super().get_default_parameters()
for key, value in self.data.items():
if key.startswith("ef"):
defaults[key.replace("ef", "emission_factor")] = value
return defaults


class LoadAdapter(Adapter):
"""
LoadAdapter
Expand Down Expand Up @@ -474,6 +613,44 @@ class VolatileAdapter(Adapter):
facade = facades.Volatile


class EmissionConstraintAdapter(Adapter):
"""
EmissionConstraintAdapter
"""

type = "co2_emission_limit"
facade = CO2EmissionLimit # oemof.industry facade - might be moved to oemof.tabular
extra_fields = Adapter.extra_fields + (
Field(name="commodities", type=float),
)

def get_default_parameters(self) -> dict:
defaults = super().get_default_parameters()
del defaults["region"]
del defaults["name"]
del defaults["year"]
# reduce co2 limit by share of steel industry
defaults["co2_limit"] = [limit * self.data["steel_emission_share"] for
limit in defaults["co2_limit"]]

# categorize commodities
commodities = {"co2_commodities": [], "ch4_commodities": [],
"n2o_commodities": [], "negative_co2_commodities": []}
inputs = self.structure["inputs"]
for i in inputs:
if "neg" in i and "co2" in i:
commodities["negative_co2_commodities"].append(i)
elif "co2" in i:
commodities["co2_commodities"].append(i)
elif "ch4" in i:
commodities["ch4_commodities"].append(i)
elif "n2o" in i:
commodities["n2o_commodities"].append(i)
# replace quotes with # to make a json.loads easier later
defaults["commodities"] = json.dumps(commodities).replace('"', "#")
return defaults


class MIMOAdapter(Adapter):
"""
MIMOAdapter
Expand All @@ -485,25 +662,19 @@ class MIMOAdapter(Adapter):
Field(name="name", type=str),
Field(name="region", type=str),
Field(name="year", type=int),
Field(name="full_load_time_max", type=float),
Field(name="groups", type=dict),
Field(name="lifetime", type=float),
Field(name="capacity_cost", type=float),
Field(name="capacity", type=float),
Field(name="expandable", type=bool),
Field(name="activity_bound_min", type=float),
Field(name="activity_bound_max", type=float),
Field(name="activity_bound_fix", type=float),
Field(name="primary", type=str),
)
output_parameters = ()

def default_pre_mapping_calculations(self):
"""
Mimo adapter specific pre calculations
Returns
-------

"""
pass

def get_default_parameters(self) -> dict:
defaults = super().get_default_parameters()
defaults["groups"] = self.get_groups()
Expand All @@ -512,10 +683,13 @@ def get_default_parameters(self) -> dict:
"emissions_factor_",
"conversion_factor_",
"flow_share_",
"ef_",
)
for key, value in self.data.items():
for keyword in keywords:
if key.startswith(keyword):
if key.startswith("ef"):
key = key.replace("ef", "emission_factor")
defaults[key] = value
return defaults

Expand All @@ -524,6 +698,8 @@ def get_bus_from_struct(bus_list: list, prefix: str) -> dict:
buses = {}
counter = 0
for bus_group in bus_list:
if prefix == "to_bus_" and counter == 0:
buses["primary"] = bus_group
if isinstance(bus_group, str):
buses[f"{prefix}{counter}"] = bus_group
counter += 1
Expand Down
Loading
Loading