diff --git a/config.default.yaml b/config.default.yaml index c0143d01..6a1d77cb 100644 --- a/config.default.yaml +++ b/config.default.yaml @@ -25,10 +25,10 @@ scenario: # solar+c0.5 reduces the capital cost of solar to 50\% of reference value # solar+p3 multiplies the available installable potential by factor 3 # dist{n} includes distribution grids with investment cost of n times cost in data/costs.csv - # for myopic/perfect foresight cb states the carbon budget in GtCO2 (cumulative - # emissions throughout the transition path in the timeframe determined by the + # for myopic/perfect foresight cb states the carbon budget in GtCO2 (cumulative + # emissions throughout the transition path in the timeframe determined by the # planning_horizons), be:beta decay; ex:exponential decay - # cb40ex0 distributes a carbon budget of 40 GtCO2 following an exponential + # cb40ex0 distributes a carbon budget of 40 GtCO2 following an exponential # decay with initial growth rate 0 planning_horizons : [2030] # investment years for myopic and perfect; or costs year for overnight # for example, set to [2020, 2030, 2040, 2050] for myopic foresight @@ -71,6 +71,7 @@ pypsa_eur: "Link": ["DC"] "Generator": ["onwind", "offwind-ac", "offwind-dc", "solar", "ror"] "StorageUnit": ["PHS","hydro"] + "Store": [] biomass: year: 2030 diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 1971ed77..4ee7cb9e 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -4,8 +4,11 @@ Release Notes Future release =================== -*For the myopic option, a carbon budget and a type of decay (exponential or beta) can be selected in the config file to distribute the budget across the planning_horizons. -*Added an option to alter the capital cost or maximum capacity of carriers by a factor via ``carrier+factor`` in the ``{opts}`` wildcard. This can be useful for exploring uncertain cost parameters. Example: ``solar+c0.5`` reduces the capital cost of solar to 50\% of original values. Similarly ``solar+p3`` multiplies the p_nom_max by 3. +* For the myopic option, a carbon budget and a type of decay (exponential or beta) can be selected in the config file to distribute the budget across the planning_horizons. +* Added an option to alter the capital cost or maximum capacity of carriers by a factor via ``carrier+factor`` in the ``{opts}`` wildcard. This can be useful for exploring uncertain cost parameters. Example: ``solar+c0.5`` reduces the capital cost of solar to 50\% of original values. Similarly ``solar+p3`` multiplies the p_nom_max by 3. +* Bugfix: Fix reading in of ``pypsa-eur/resources/powerplants.csv`` to PyPSA-Eur Version 0.3.0 (use ``DateIn`` instead of old ``YearDecommissioned``). +* Bugfix: Make sure that ``Store`` components (battery and H2) are also removed from PyPSA-Eur, so they can be added later by PyPSA-Eur-Sec. + PyPSA-Eur-Sec 0.4.0 (11th December 2020) ========================================= diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index fd8321c4..316eb672 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -53,14 +53,14 @@ def co2_emissions_year(cts, opts, year): calculate co2 emissions in one specific year (e.g. 1990 or 2018). """ eea_co2 = build_eea_co2(year) - - #TODO: read Eurostat data from year>2014, this only affects the estimation of + + #TODO: read Eurostat data from year>2014, this only affects the estimation of # CO2 emissions for "BA","RS","AL","ME","MK" if year > 2014: eurostat_co2 = build_eurostat_co2(year=2014) else: eurostat_co2 = build_eurostat_co2(year) - + co2_totals=build_co2_totals(eea_co2, eurostat_co2, year) co2_emissions = co2_totals.loc[cts, "electricity"].sum() @@ -79,51 +79,51 @@ def co2_emissions_year(cts, opts, year): def build_carbon_budget(o): #distribute carbon budget following beta or exponential transition path - if "be" in o: + if "be" in o: #beta decay carbon_budget = float(o[o.find("cb")+2:o.find("be")]) - be=float(o[o.find("be")+2:]) - if "ex" in o: + be=float(o[o.find("be")+2:]) + if "ex" in o: #exponential decay carbon_budget = float(o[o.find("cb")+2:o.find("ex")]) r=float(o[o.find("ex")+2:]) - + pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0) pop_layout["ct"] = pop_layout.index.str[:2] - cts = pop_layout.ct.value_counts().index - - e_1990 = co2_emissions_year(cts, opts, year=1990) - + cts = pop_layout.ct.value_counts().index + + e_1990 = co2_emissions_year(cts, opts, year=1990) + #emissions at the beginning of the path (last year available 2018) - e_0 = co2_emissions_year(cts, opts, year=2018) + e_0 = co2_emissions_year(cts, opts, year=2018) #emissions in 2019 and 2020 assumed equal to 2018 and substracted carbon_budget -= 2*e_0 planning_horizons = snakemake.config['scenario']['planning_horizons'] - CO2_CAP = pd.DataFrame(index = pd.Series(data=planning_horizons, + CO2_CAP = pd.DataFrame(index = pd.Series(data=planning_horizons, name='planning_horizon'), columns=pd.Series(data=[], - name='paths', + name='paths', dtype='float')) t_0 = planning_horizons[0] - if "be" in o: - #beta decay - t_f = t_0 + (2*carbon_budget/e_0).round(0) # final year in the path + if "be" in o: + #beta decay + t_f = t_0 + (2*carbon_budget/e_0).round(0) # final year in the path #emissions (relative to 1990) CO2_CAP[o] = [(e_0/e_1990)*(1-beta.cdf((t-t_0)/(t_f-t_0), be, be)) for t in planning_horizons] - - if "ex" in o: + + if "ex" in o: #exponential decay without delay T=carbon_budget/e_0 m=(1+np.sqrt(1+r*T))/T CO2_CAP[o] = [(e_0/e_1990)*(1+(m+r)*(t-t_0))*np.exp(-m*(t-t_0)) for t in planning_horizons] - - CO2_CAP.to_csv(path_cb + 'carbon_budget_distribution.csv', sep=',', - line_terminator='\n', float_format='%.3f') + + CO2_CAP.to_csv(path_cb + 'carbon_budget_distribution.csv', sep=',', + line_terminator='\n', float_format='%.3f') countries=pd.Series(data=cts) - countries.to_csv(path_cb + 'countries.csv', sep=',', + countries.to_csv(path_cb + 'countries.csv', sep=',', line_terminator='\n', float_format='%.3f') - + def add_lifetime_wind_solar(n): """ Add lifetime for solar and wind generators @@ -1854,7 +1854,7 @@ if __name__ == "__main__": from vresutils.snakemake import MockSnakemake snakemake = MockSnakemake( wildcards=dict(network='elec', simpl='', clusters='37', lv='1.0', - opts='', planning_horizons='2020', + opts='', planning_horizons='2020', sector_opts='120H-T-H-B-I-onwind+p3-dist1-cb48be3'), input=dict( network='../pypsa-eur/networks/{network}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc', energy_totals_name='resources/energy_totals.csv', @@ -1999,19 +1999,19 @@ if __name__ == "__main__": print("CO2 limit set to",limit) for o in opts: - if "cb" in o: + if "cb" in o: path_cb = snakemake.config['results_dir'] + snakemake.config['run'] + '/csvs/' if not os.path.exists(path_cb): os.makedirs(path_cb) try: CO2_CAP=pd.read_csv(path_cb + 'carbon_budget_distribution.csv', index_col=0) - except: + except: build_carbon_budget(o) CO2_CAP=pd.read_csv(path_cb + 'carbon_budget_distribution.csv', index_col=0) - - limit=CO2_CAP.loc[investment_year] + + limit=CO2_CAP.loc[investment_year] print("overriding CO2 limit with scenario limit",limit) - + for o in opts: if "Co2L" in o: limit = o[o.find("Co2L")+4:] @@ -2032,13 +2032,13 @@ if __name__ == "__main__": if snakemake.config["sector"]['electricity_distribution_grid']: insert_electricity_distribution_grid(n) - + for o in opts: if "+" in o: oo = o.split("+") - carrier_list=np.hstack((n.generators.carrier.unique(), n.links.carrier.unique(), - n.stores.carrier.unique(), n.storage_units.carrier.unique())) - suptechs = map(lambda c: c.split("-", 2)[0], carrier_list) + carrier_list=np.hstack((n.generators.carrier.unique(), n.links.carrier.unique(), + n.stores.carrier.unique(), n.storage_units.carrier.unique())) + suptechs = map(lambda c: c.split("-", 2)[0], carrier_list) if oo[0].startswith(tuple(suptechs)): carrier = oo[0] attr_lookup = {"p": "p_nom_max", "c": "capital_cost"} @@ -2051,12 +2051,12 @@ if __name__ == "__main__": comps = {"Generator", "Link", "StorageUnit"} if attr=='p_nom_max' else {"Generator", "Link", "StorageUnit", "Store"} for c in n.iterate_components(comps): if carrier=='solar': - sel = c.df.carrier.str.contains(carrier) & ~c.df.carrier.str.contains("solar rooftop") + sel = c.df.carrier.str.contains(carrier) & ~c.df.carrier.str.contains("solar rooftop") else: sel = c.df.carrier.str.contains(carrier) c.df.loc[sel,attr] *= factor print("changing", attr ,"for",carrier,"by factor",factor) - + if snakemake.config["sector"]['gas_distribution_grid']: insert_gas_distribution_costs(n) if snakemake.config["sector"]['electricity_grid_connection']: