|
20 | 20 | broadcast,
|
21 | 21 | nodes_ex_world,
|
22 | 22 | package_data_path,
|
| 23 | + same_node, |
23 | 24 | )
|
24 | 25 |
|
| 26 | +from .util import read_yaml_file |
| 27 | + |
25 | 28 | if TYPE_CHECKING:
|
26 | 29 | from message_ix import Scenario
|
27 | 30 |
|
@@ -421,9 +424,9 @@ def read_sector_data(
|
421 | 424 | list_ef = data_df[["Parameter", "Species", "Mode"]].apply(list, axis=1)
|
422 | 425 |
|
423 | 426 | data_df["parameter"] = list_series.str.join("|")
|
424 |
| - data_df.loc[data_df["Parameter"] == "emission_factor", "parameter"] = ( |
425 |
| - list_ef.str.join("|") |
426 |
| - ) |
| 427 | + data_df.loc[ |
| 428 | + data_df["Parameter"] == "emission_factor", "parameter" |
| 429 | + ] = list_ef.str.join("|") |
427 | 430 |
|
428 | 431 | data_df = data_df.drop(["Parameter", "Level", "Commodity", "Mode"], axis=1)
|
429 | 432 | data_df = data_df.drop(data_df[data_df.Value == ""].index)
|
@@ -1859,3 +1862,95 @@ def calibrate_for_SSPs(scenario: "Scenario") -> None:
|
1859 | 1862 | scenario.commit("increase gro up for loil_i/gas_i/heat_i CHN 2020")
|
1860 | 1863 |
|
1861 | 1864 | return
|
| 1865 | + |
| 1866 | + |
| 1867 | +def gen_plastics_emission_factors( |
| 1868 | + info, species: Literal["methanol", "HVCs"] |
| 1869 | +) -> pd.DataFrame: |
| 1870 | + """Generate "CO2_Emission" relation parameter that |
| 1871 | + represents stored carbon in produced plastics. |
| 1872 | + The calculation considers: |
| 1873 | + * carbon content of feedstocks, |
| 1874 | + * the share that is converted to plastics |
| 1875 | + * the end-of-life treatment (i.e. incineration, landfill, etc.) |
| 1876 | +
|
| 1877 | + Values are negative since they need to be deducted |
| 1878 | + from top-down accounting, which assumes that all extracted |
| 1879 | + carbonaceous resources are released as carbon emissions. |
| 1880 | + (Which is not correct for carbon used in long-lived products) |
| 1881 | +
|
| 1882 | + Parameters |
| 1883 | + ---------- |
| 1884 | + species: |
| 1885 | + feedstock species to generate relation for |
| 1886 | + info: ScenarioInfo |
| 1887 | +
|
| 1888 | + Returns |
| 1889 | + ------- |
| 1890 | + pd.DataFrame |
| 1891 | + """ |
| 1892 | + |
| 1893 | + if species != "HVCs": |
| 1894 | + raise NotImplementedError |
| 1895 | + |
| 1896 | + tec_species_map = {"methanol": NotImplemented, "HVCs": "production_HVC"} |
| 1897 | + |
| 1898 | + # TODO: do same calculation for methanol not used for MTO but other plastics |
| 1899 | + carbon_pars = read_yaml_file( |
| 1900 | + package_data_path( |
| 1901 | + "material", "petrochemicals", "chemicals_carbon_parameters.yaml" |
| 1902 | + ) |
| 1903 | + ) |
| 1904 | + # TODO: move EOL parameters to a different file to disassociate from methanol model |
| 1905 | + end_of_life_pars = pd.read_excel( |
| 1906 | + package_data_path("material", "methanol", "methanol_sensitivity_pars.xlsx"), |
| 1907 | + sheet_name="Sheet1", |
| 1908 | + dtype=object, |
| 1909 | + ) |
| 1910 | + seq_carbon = { |
| 1911 | + k: (v["carbon mass"] / v["molar mass"]) * v["plastics use"] |
| 1912 | + for k, v in carbon_pars[species].items() |
| 1913 | + } |
| 1914 | + end_of_life_pars = end_of_life_pars.set_index("par").to_dict()["value"] |
| 1915 | + common = { |
| 1916 | + "unit": "Mt C", |
| 1917 | + "relation": "CO2_Emission", |
| 1918 | + "mode": seq_carbon.keys(), |
| 1919 | + "technology": tec_species_map[species], |
| 1920 | + } |
| 1921 | + co2_emi_rel = make_df("relation_activity", **common).drop(columns="value") |
| 1922 | + co2_emi_rel = co2_emi_rel.merge( |
| 1923 | + pd.Series(seq_carbon, name="value").to_frame().reset_index(), |
| 1924 | + left_on="mode", |
| 1925 | + right_on="index", |
| 1926 | + ).drop(columns="index") |
| 1927 | + |
| 1928 | + years = info.Y # [2020, 2025] |
| 1929 | + co2_emi_rel = co2_emi_rel.pipe(broadcast, year_act=years) |
| 1930 | + co2_emi_rel["year_rel"] = co2_emi_rel["year_act"] |
| 1931 | + |
| 1932 | + co2_emi_rel = co2_emi_rel.pipe(broadcast, node_loc=nodes_ex_world(info.N)).pipe( |
| 1933 | + same_node |
| 1934 | + ) |
| 1935 | + |
| 1936 | + def apply_eol_factor(row, pars): |
| 1937 | + if row["year_act"] < pars["incin_trend_end"]: |
| 1938 | + share = pars["incin_rate"] + pars["incin_trend"] * (row["year_act"] - 2020) |
| 1939 | + else: |
| 1940 | + share = 0.5 |
| 1941 | + return row["value"] * (1 - share) |
| 1942 | + |
| 1943 | + co2_emi_rel["value"] = co2_emi_rel.apply( |
| 1944 | + lambda x: apply_eol_factor(x, end_of_life_pars), axis=1 |
| 1945 | + ).mul(-1) |
| 1946 | + return co2_emi_rel |
| 1947 | + |
| 1948 | + |
| 1949 | +if __name__ == "__main__": |
| 1950 | + from ixmp import Platform |
| 1951 | + from message_ix import Scenario |
| 1952 | + |
| 1953 | + mp = Platform("ixmp_dev") |
| 1954 | + scen = Scenario(mp, "MESSAGEix-Materials", "test_c901_refactoring") |
| 1955 | + s_info = ScenarioInfo(scen) |
| 1956 | + gen_plastics_emission_factors(s_info, "methanol") |
0 commit comments