From d3a0f7e67d82c4744a5fee541a2849e0ffd5b005 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Thu, 1 Aug 2019 15:43:04 +0200 Subject: [PATCH] Diff intraday heat profiles for (res, services) x (water, space) These are specified in data/heat_load_profile.csv. The resulting heat_demand df has MultiIndex columns, where the first level is ["sector use"], and the second level level is nodes. --- Snakefile | 2 +- data/heat_load_profile.csv | 25 +++++++++++++++ scripts/prepare_sector_network.py | 52 +++++++++++++++++-------------- 3 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 data/heat_load_profile.csv diff --git a/Snakefile b/Snakefile index 7efdf18e..1cb625b2 100644 --- a/Snakefile +++ b/Snakefile @@ -178,7 +178,7 @@ rule prepare_sector_network: transport_name='data/transport_data.csv', biomass_potentials='data/biomass_potentials.csv', timezone_mappings='data/timezone_mappings.csv', - heat_profile="data/heat_load_profile_DK_AdamJensen.csv", + heat_profile="data/heat_load_profile.csv", costs="data/costs.csv", clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv", industrial_demand="resources/industrial_demand_{network}_s{simpl}_{clusters}.csv", diff --git a/data/heat_load_profile.csv b/data/heat_load_profile.csv new file mode 100644 index 00000000..f1e13ea4 --- /dev/null +++ b/data/heat_load_profile.csv @@ -0,0 +1,25 @@ +hour,residential space weekday,residential space weekend,residential water weekday,residential water weekend,services space weekday,services space weekend,services water weekday,services water weekend +0,0.9181438689,0.9421512708,1,1,0.9181438689,0.9421512708,1,1 +1,0.9172359071,0.9400891069,1,1,0.9172359071,0.9400891069,1,1 +2,0.9269464481,0.9461062015,1,1,0.9269464481,0.9461062015,1,1 +3,0.9415047932,0.9535084941,1,1,0.9415047932,0.9535084941,1,1 +4,0.9656299507,0.9651094993,1,1,0.9656299507,0.9651094993,1,1 +5,1.0221166443,0.9834676747,1,1,1.0221166443,0.9834676747,1,1 +6,1.1553090493,1.0124171051,1,1,1.1553090493,1.0124171051,1,1 +7,1.2093411031,1.0446615927,1,1,1.2093411031,1.0446615927,1,1 +8,1.1470295942,1.088203419,1,1,1.1470295942,1.088203419,1,1 +9,1.0877191341,1.1110334576,1,1,1.0877191341,1.1110334576,1,1 +10,1.0418327372,1.0926752822,1,1,1.0418327372,1.0926752822,1,1 +11,1.0062977133,1.055488209,1,1,1.0062977133,1.055488209,1,1 +12,0.9837030359,1.0251266112,1,1,0.9837030359,1.0251266112,1,1 +13,0.9667570278,0.9990015154,1,1,0.9667570278,0.9990015154,1,1 +14,0.9548320932,0.9782897278,1,1,0.9548320932,0.9782897278,1,1 +15,0.9509232061,0.9698167237,1,1,0.9509232061,0.9698167237,1,1 +16,0.9636973319,0.974288587,1,1,0.9636973319,0.974288587,1,1 +17,0.9799372563,0.9886456216,1,1,0.9799372563,0.9886456216,1,1 +18,1.0046501848,1.0084159643,1,1,1.0046501848,1.0084159643,1,1 +19,1.0079452419,1.0171243296,1,1,1.0079452419,1.0171243296,1,1 +20,0.9860566481,0.9994722379,1,1,0.9860566481,0.9994722379,1,1 +21,0.9705228074,0.982761591,1,1,0.9705228074,0.982761591,1,1 +22,0.9586485819,0.9698167237,1,1,0.9586485819,0.9698167237,1,1 +23,0.9335023778,0.9515079292,1,1,0.9335023778,0.9515079292,1,1 diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 07f85fd4..c7c75cae 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -282,18 +282,6 @@ def prepare_data(network): ############## - #copy forward the daily average heat demand into each hour, so it can be multipled by the intraday profile - heat_demand_df = xr.open_dataarray(snakemake.input.heat_demand_total).T.to_pandas().reindex(index=network.snapshots, method="ffill") - - - intraday_profiles = pd.read_csv(snakemake.input.heat_profile,index_col=0) - - intraday_year_profiles = generate_periodic_profiles(heat_demand_df.index.tz_localize("UTC"), - nodes=heat_demand_df.columns, - weekly_profile=(list(intraday_profiles["weekday"])*5 + list(intraday_profiles["weekend"])*2)).tz_localize(None) - - heat_demand_df = heat_demand_df*intraday_year_profiles - ashp_cop = xr.open_dataarray(snakemake.input.cop_air_total).T.to_pandas().reindex(index=network.snapshots) gshp_cop = xr.open_dataarray(snakemake.input.cop_soil_total).T.to_pandas().reindex(index=network.snapshots) @@ -307,18 +295,31 @@ def prepare_data(network): nodal_energy_totals.index = pop_layout.index nodal_energy_totals = nodal_energy_totals.multiply(pop_layout.fraction,axis=0) + #copy forward the daily average heat demand into each hour, so it can be multipled by the intraday profile + daily_space_heat_demand = xr.open_dataarray(snakemake.input.heat_demand_total).T.to_pandas().reindex(index=network.snapshots, method="ffill") + + intraday_profiles = pd.read_csv(snakemake.input.heat_profile,index_col=0) + sectors = ["residential","services"] + uses = ["water","space"] - nodal_energy_totals["Space Heating"] = options['space_heating_fraction']*nodal_energy_totals[["total {sector} space".format(sector=sector) for sector in sectors]].sum(axis=1) - nodal_energy_totals["Water Heating"] = nodal_energy_totals[["total {sector} water".format(sector=sector) for sector in sectors]].sum(axis=1) + heat_demand = {} + for sector in sectors: + for use in uses: + intraday_year_profile = generate_periodic_profiles(daily_space_heat_demand.index.tz_localize("UTC"), + nodes=daily_space_heat_demand.columns, + weekly_profile=(list(intraday_profiles["{} {} weekday".format(sector,use)])*5 + list(intraday_profiles["{} {} weekend".format(sector,use)])*2)).tz_localize(None) - space_heat_demand = (heat_demand_df/heat_demand_df.sum()).multiply(nodal_energy_totals["Space Heating"])*1e6*Nyears - - water_heat_demand = (nodal_energy_totals["Water Heating"]/8760.)*1e6 - - heat_demand = space_heat_demand + water_heat_demand + if use == "space": + heat_demand_shape = daily_space_heat_demand*intraday_year_profile + factor = options['space_heating_fraction'] + else: + heat_demand_shape = intraday_year_profile + factor = 1. + heat_demand["{} {}".format(sector,use)] = factor*(heat_demand_shape/heat_demand_shape.sum()).multiply(nodal_energy_totals["total {} {}".format(sector,use)])*1e6 + heat_demand = pd.concat(heat_demand,axis=1) ############## @@ -413,7 +414,7 @@ def prepare_data(network): - return nodal_energy_totals, heat_demand, space_heat_demand, water_heat_demand, ashp_cop, gshp_cop, solar_thermal, transport, avail_profile, dsm_profile, co2_totals, nodal_transport_data + return nodal_energy_totals, heat_demand, ashp_cop, gshp_cop, solar_thermal, transport, avail_profile, dsm_profile, co2_totals, nodal_transport_data def prepare_costs(): @@ -695,6 +696,9 @@ def add_heat(network): print("adding heat") + #aggregate all residential, services and water, space heat + aggregated_heat_demand = heat_demand.groupby(level=1,axis=1).sum() + #rural are areas with low heating density #urban are areas with high heating density #urban can be split into district heating (central) and individual heating (decentral) @@ -741,21 +745,21 @@ def add_heat(network): suffix=" rural heat", bus=rural + " rural heat", carrier="rural heat", - p_set= heat_demand[rural].multiply((1-urban_fraction[rural]))) + p_set= aggregated_heat_demand[rural].multiply((1-urban_fraction[rural]))) network.madd("Load", urban_central, suffix=" urban central heat", bus=urban_central + " urban central heat", carrier="urban central heat", - p_set= heat_demand[urban_central].multiply(urban_fraction[urban_central]*(1+options['district_heating_loss']))) + p_set= aggregated_heat_demand[urban_central].multiply(urban_fraction[urban_central]*(1+options['district_heating_loss']))) network.madd("Load", urban_decentral, suffix=" urban decentral heat", bus=urban_decentral + " urban decentral heat", carrier="urban decentral heat", - p_set= heat_demand[urban_decentral].multiply(urban_fraction[urban_decentral])) + p_set= aggregated_heat_demand[urban_decentral].multiply(urban_fraction[urban_decentral])) network.madd("Link", @@ -1432,7 +1436,7 @@ if __name__ == "__main__": print(o,limit) options['space_heating_fraction'] = limit - nodal_energy_totals, heat_demand, space_heat_demand, water_heat_demand, ashp_cop, gshp_cop, solar_thermal, transport, avail_profile, dsm_profile, co2_totals, nodal_transport_data = prepare_data(n) + nodal_energy_totals, heat_demand, ashp_cop, gshp_cop, solar_thermal, transport, avail_profile, dsm_profile, co2_totals, nodal_transport_data = prepare_data(n) if "nodistrict" in opts: options["central"] = False