def make_summaries(networks_dict, country='all'): columns = pd.MultiIndex.from_tuples(networks_dict.keys(),names=["simpl","clusters","ll","opts"]) dfs = {} for output in outputs: dfs[output] = pd.DataFrame(columns=columns,dtype=float) for label, filename in iteritems(networks_dict): print(label, filename) if not os.path.exists(filename): print("does not exist!!") continue try: n = pypsa.Network(filename) except OSError: logger.warning("Skipping {filename}".format(filename=filename)) continue if country != 'all': n = n[n.buses.country == country] Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, snakemake.input[0], snakemake.config['costs'], snakemake.config['electricity']) update_transmission_costs(n, costs, simple_hvdc_costs=False) assign_carriers(n) for output in outputs: dfs[output] = globals()["calculate_" + output](n, label, dfs[output]) return dfs
def set_line_volume_limit(n, lv, Nyears=1.): links_dc_b = n.links.carrier == 'DC' if np.isinf(lv): costs = load_costs(Nyears, snakemake.input.tech_costs, snakemake.config['costs'], snakemake.config['electricity']) update_transmission_costs(n, costs, simple_hvdc_costs=True) else: # Either line_volume cap or cost n.lines['capital_cost'] = 0. n.links.loc[links_dc_b, 'capital_cost'] = 0. if lv > 1.0: lines_s_nom = n.lines.s_nom.where( n.lines.type == '', np.sqrt(3) * n.lines.num_parallel * n.lines.type.map(n.line_types.i_nom) * n.lines.bus0.map(n.buses.v_nom)) n.lines['s_nom_min'] = lines_s_nom n.lines['s_nom_extendable'] = True n.links.loc[links_dc_b, 'p_nom_min'] = n.links.loc[links_dc_b, 'p_nom'] n.links.loc[links_dc_b, 'p_nom_extendable'] = True n.line_volume_limit = lv * ( (lines_s_nom * n.lines['length']).sum() + n.links.loc[links_dc_b].eval('p_nom * length').sum()) return n
def set_line_cost_limit(n, lc, Nyears=1.): links_dc_b = n.links.carrier == 'DC' if not n.links.empty else pd.Series() lines_s_nom = n.lines.s_nom.where( n.lines.type == '', np.sqrt(3) * n.lines.num_parallel * n.lines.type.map(n.line_types.i_nom) * n.lines.bus0.map(n.buses.v_nom) ) n.lines['capital_cost_lc'] = n.lines['capital_cost'] n.links['capital_cost_lc'] = n.links['capital_cost'] total_line_cost = ((lines_s_nom * n.lines['capital_cost_lc']).sum() + n.links.loc[links_dc_b].eval('p_nom * capital_cost_lc').sum()) if lc == 'opt': costs = load_costs(Nyears, snakemake.input.tech_costs, snakemake.config['costs'], snakemake.config['electricity']) update_transmission_costs(n, costs, simple_hvdc_costs=False) else: # Either line_volume cap or cost n.lines['capital_cost'] = 0. n.links.loc[links_dc_b, 'capital_cost'] = 0. if lc == 'opt' or float(lc) > 1.0: n.lines['s_nom_min'] = lines_s_nom n.lines['s_nom_extendable'] = True n.links.loc[links_dc_b, 'p_nom_min'] = n.links.loc[links_dc_b, 'p_nom'] n.links.loc[links_dc_b, 'p_nom_extendable'] = True if lc != 'opt': n.line_cost_limit = float(lc) * total_line_cost return n
def load_network(fn, tech_costs, config, combine_hydro_ps=True): opts = config['plotting'] n = pypsa.Network(fn) n.loads["carrier"] = n.loads.bus.map(n.buses.carrier) + " load" n.stores["carrier"] = n.stores.bus.map(n.buses.carrier) n.links["carrier"] = (n.links.bus0.map(n.buses.carrier) + "-" + n.links.bus1.map(n.buses.carrier)) n.lines["carrier"] = "AC line" n.transformers["carrier"] = "AC transformer" n.lines['s_nom'] = n.lines['s_nom_min'] n.links['p_nom'] = n.links['p_nom_min'] if combine_hydro_ps: n.storage_units.loc[n.storage_units.carrier.isin({'PHS', 'hydro'}), 'carrier'] = 'hydro+PHS' # #if the carrier was not set on the heat storage units # bus_carrier = n.storage_units.bus.map(n.buses.carrier) # n.storage_units.loc[bus_carrier == "heat","carrier"] = "water tanks" for name in opts['heat_links'] + opts['heat_generators']: n.links.loc[n.links.index.to_series().str.endswith(name), "carrier"] = name Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, tech_costs, config['costs'], config['electricity']) update_transmission_costs(n, costs) return n
def set_transmission_limit(n, ll_type, factor, Nyears=1): links_dc_b = n.links.carrier == 'DC' if not n.links.empty else pd.Series() _lines_s_nom = (np.sqrt(3) * n.lines.type.map(n.line_types.i_nom) * n.lines.num_parallel * n.lines.bus0.map(n.buses.v_nom)) lines_s_nom = n.lines.s_nom.where(n.lines.type == '', _lines_s_nom) col = 'capital_cost' if ll_type == 'c' else 'length' ref = (lines_s_nom @ n.lines[col] + n.links[links_dc_b].p_nom @ n.links[links_dc_b][col]) costs = load_costs(Nyears, snakemake.input.tech_costs, snakemake.config['costs'], snakemake.config['electricity']) update_transmission_costs(n, costs, simple_hvdc_costs=False) if factor == 'opt' or float(factor) > 1.0: n.lines['s_nom_min'] = lines_s_nom n.lines['s_nom_extendable'] = True n.links.loc[links_dc_b, 'p_nom_min'] = n.links.loc[links_dc_b, 'p_nom'] n.links.loc[links_dc_b, 'p_nom_extendable'] = True if factor != 'opt': con_type = 'expansion_cost' if ll_type == 'c' else 'volume_expansion' rhs = float(factor) * ref n.add('GlobalConstraint', f'l{ll_type}_limit', type=f'transmission_{con_type}_limit', sense='<=', constant=rhs, carrier_attribute='AC, DC') return n
def load_network_for_plots(fn, tech_costs, config, combine_hydro_ps=True): import pypsa from add_electricity import update_transmission_costs, load_costs opts = config['plotting'] n = pypsa.Network(fn) n.loads["carrier"] = n.loads.bus.map(n.buses.carrier) + " load" n.stores["carrier"] = n.stores.bus.map(n.buses.carrier) n.links["carrier"] = (n.links.bus0.map(n.buses.carrier) + "-" + n.links.bus1.map(n.buses.carrier)) n.lines["carrier"] = "AC line" n.transformers["carrier"] = "AC transformer" n.lines['s_nom'] = n.lines['s_nom_min'] n.links['p_nom'] = n.links['p_nom_min'] if combine_hydro_ps: n.storage_units.loc[n.storage_units.carrier.isin({'PHS', 'hydro'}), 'carrier'] = 'hydro+PHS' # #if the carrier was not set on the heat storage units # bus_carrier = n.storage_units.bus.map(n.buses.carrier) # n.storage_units.loc[bus_carrier == "heat","carrier"] = "water tanks" Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, tech_costs, config['costs'], config['electricity']) update_transmission_costs(n, costs) return n
def load_network_for_plots(fn, tech_costs, config, combine_hydro_ps=True): import pypsa from add_electricity import load_costs, update_transmission_costs n = pypsa.Network(fn) n.loads["carrier"] = n.loads.bus.map(n.buses.carrier) + " load" n.stores["carrier"] = n.stores.bus.map(n.buses.carrier) n.links["carrier"] = ( n.links.bus0.map(n.buses.carrier) + "-" + n.links.bus1.map(n.buses.carrier) ) n.lines["carrier"] = "AC line" n.transformers["carrier"] = "AC transformer" n.lines["s_nom"] = n.lines["s_nom_min"] n.links["p_nom"] = n.links["p_nom_min"] if combine_hydro_ps: n.storage_units.loc[ n.storage_units.carrier.isin({"PHS", "hydro"}), "carrier" ] = "hydro+PHS" # if the carrier was not set on the heat storage units # bus_carrier = n.storage_units.bus.map(n.buses.carrier) # n.storage_units.loc[bus_carrier == "heat","carrier"] = "water tanks" Nyears = n.snapshot_weightings.objective.sum() / 8760.0 costs = load_costs(Nyears, tech_costs, config["costs"], config["electricity"]) update_transmission_costs(n, costs) return n
def make_summaries(networks_dict): columns = pd.MultiIndex.from_tuples( networks_dict.keys(), names=["simpl", "clusters", "lv", "opts"]) dfs = {} for output in outputs: dfs[output] = pd.DataFrame(columns=columns, dtype=float) for label, filename in iteritems(networks_dict): print(label, filename) if not os.path.exists(filename): print("does not exist!!") continue n = pypsa.Network(filename) assign_carriers(n) Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, snakemake.input[0], snakemake.config['costs'], snakemake.config['electricity']) update_transmission_costs(n, costs) for output in outputs: dfs[output] = globals()["calculate_" + output](n, label, dfs[output]) return dfs
def _prepare_connection_costs_per_link(n): if n.links.empty: return {} costs = load_costs(n.snapshot_weightings.sum() / 8760, snakemake.input.tech_costs, snakemake.config['costs'], snakemake.config['electricity']) connection_costs_per_link = {} for tech in snakemake.config['renewable']: if tech.startswith('offwind'): connection_costs_per_link[tech] = ( n.links.length * snakemake.config['lines']['length_factor'] * (n.links.underwater_fraction * costs.at[tech + '-connection-submarine', 'capital_cost'] + (1. - n.links.underwater_fraction) * costs.at[tech + '-connection-underground', 'capital_cost'])) return connection_costs_per_link
def set_transmission_limit(n, ll_type, factor, Nyears=1): links_dc_b = n.links.carrier == "DC" if not n.links.empty else pd.Series() _lines_s_nom = (np.sqrt(3) * n.lines.type.map(n.line_types.i_nom) * n.lines.num_parallel * n.lines.bus0.map(n.buses.v_nom)) lines_s_nom = n.lines.s_nom.where(n.lines.type == "", _lines_s_nom) col = "capital_cost" if ll_type == "c" else "length" ref = (lines_s_nom @ n.lines[col] + n.links.loc[links_dc_b, "p_nom"] @ n.links.loc[links_dc_b, col]) costs = load_costs( Nyears, snakemake.input.tech_costs, snakemake.config["costs"], snakemake.config["electricity"], ) update_transmission_costs(n, costs, simple_hvdc_costs=False) if factor == "opt" or float(factor) > 1.0: n.lines["s_nom_min"] = lines_s_nom n.lines["s_nom_extendable"] = True n.links.loc[links_dc_b, "p_nom_min"] = n.links.loc[links_dc_b, "p_nom"] n.links.loc[links_dc_b, "p_nom_extendable"] = True if factor != "opt": con_type = "expansion_cost" if ll_type == "c" else "volume_expansion" rhs = float(factor) * ref n.add( "GlobalConstraint", f"l{ll_type}_limit", type=f"transmission_{con_type}_limit", sense="<=", constant=rhs, carrier_attribute="AC, DC", ) return n
def set_line_volume_limit(n, lv, Nyears=1.): links_dc_b = n.links.carrier == 'DC' if not n.links.empty else pd.Series() lines_s_nom = n.lines.s_nom.where( n.lines.type == '', np.sqrt(3) * n.lines.num_parallel * n.lines.type.map(n.line_types.i_nom) * n.lines.bus0.map(n.buses.v_nom)) total_line_volume = ((lines_s_nom * n.lines['length']).sum() + n.links.loc[links_dc_b].eval('p_nom * length').sum()) if lv == 'opt': costs = load_costs(Nyears, snakemake.input.tech_costs, snakemake.config['costs'], snakemake.config['electricity']) update_transmission_costs(n, costs, simple_hvdc_costs=True) else: # Either line_volume cap or cost n.lines['capital_cost'] = 0. n.links.loc[links_dc_b, 'capital_cost'] = 0. if lv == 'opt' or float(lv) > 1.0: n.lines['s_nom_min'] = lines_s_nom n.lines['s_nom_extendable'] = True n.links.loc[links_dc_b, 'p_nom_min'] = n.links.loc[links_dc_b, 'p_nom'] n.links.loc[links_dc_b, 'p_nom_extendable'] = True if lv != 'opt': line_volume = float(lv) * total_line_volume n.add('GlobalConstraint', 'lv_limit', type='transmission_volume_expansion_limit', sense='<=', constant=line_volume, carrier_attribute='AC, DC') return n
def _prepare_connection_costs_per_link(n): if n.links.empty: return {} Nyears = n.snapshot_weightings.objective.sum() / 8760 costs = load_costs( Nyears, snakemake.input.tech_costs, snakemake.config["costs"], snakemake.config["electricity"], ) connection_costs_per_link = {} for tech in snakemake.config["renewable"]: if tech.startswith("offwind"): connection_costs_per_link[tech] = ( n.links.length * snakemake.config["lines"]["length_factor"] * (n.links.underwater_fraction * costs.at[tech + "-connection-submarine", "capital_cost"] + (1.0 - n.links.underwater_fraction) * costs.at[tech + "-connection-underground", "capital_cost"])) return connection_costs_per_link
n_clusters = int(snakemake.wildcards.clusters) aggregate_carriers = None # All if n_clusters == len(n.buses): # Fast-path if no clustering is necessary busmap = n.buses.index.to_series() linemap = n.lines.index.to_series() clustering = pypsa.networkclustering.Clustering( n, busmap, linemap, linemap, pd.Series(dtype='O')) else: line_length_factor = snakemake.config['lines']['length_factor'] Nyears = n.snapshot_weightings.objective.sum() / 8760 hvac_overhead_cost = (load_costs(snakemake.input.tech_costs, snakemake.config['costs'], snakemake.config['electricity'], Nyears).at['HVAC overhead', 'capital_cost']) def consense(x): v = x.iat[0] assert ((x == v).all() or x.isnull().all()), ( "The `potential` configuration option must agree for all renewable carriers, for now!" ) return v potential_mode = consense( pd.Series([ snakemake.config['renewable'][tech]['potential'] for tech in renewable_carriers ]))
if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake os.chdir(os.path.dirname(os.path.abspath(__file__))) snakemake = mock_snakemake( "augmented_line_connections", network="elec", simpl="", clusters="10" ) configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) Nyears = n.snapshot_weightings.sum().values[0] / 8760.0 costs = load_costs( Nyears, snakemake.input.tech_costs, snakemake.config["costs"], snakemake.config["electricity"], ) options = snakemake.config["augmented_line_connection"] min_expansion_option = options.get("min_expansion") k_edge_option = options.get("connectivity_upgrade", 3) line_type_option = options.get("new_line_type", "HVDC") # k_edge algorithm implementation G = nx.Graph() network_buses = n.buses.loc[n.buses.carrier == "AC"].index G.add_nodes_from(np.unique(network_buses.values)) # TODO: Currently only AC lines are read in and meshed. One need to combine # AC & DC lines and then move on.
else: n_clusters = int(snakemake.wildcards.clusters) aggregate_carriers = None if n_clusters == len(n.buses): # Fast-path if no clustering is necessary busmap = n.buses.index.to_series() linemap = n.lines.index.to_series() clustering = pypsa.networkclustering.Clustering( n, busmap, linemap, linemap, pd.Series(dtype="O")) else: line_length_factor = snakemake.config["lines"]["length_factor"] Nyears = n.snapshot_weightings.objective.sum() / 8760 hvac_overhead_cost = load_costs( Nyears, tech_costs=snakemake.input.tech_costs, config=snakemake.config["costs"], elec_config=snakemake.config["electricity"], ).at["HVAC overhead", "capital_cost"] def consense(x): v = x.iat[0] assert (x == v).all() or x.isnull().all( ), "The `potential` configuration option must agree for all renewable carriers, for now!" return v potential_mode = consense( pd.Series([ snakemake.config["renewable"][tech]["potential"] for tech in renewable_carriers ])) custom_busmap = snakemake.config["enable"].get("custom_busmap", False)
n.generators.carrier.unique()).difference(renewable_carriers) else: n_clusters = int(snakemake.wildcards.clusters) aggregate_carriers = None # All if n_clusters == len(n.buses): # Fast-path if no clustering is necessary busmap = n.buses.index.to_series() linemap = n.lines.index.to_series() clustering = pypsa.networkclustering.Clustering( n, busmap, linemap, linemap, pd.Series(dtype='O')) else: line_length_factor = snakemake.config['lines']['length_factor'] hvac_overhead_cost = (load_costs( n.snapshot_weightings.sum() / 8760, tech_costs=snakemake.input.tech_costs, config=snakemake.config['costs'], elec_config=snakemake.config['electricity']).at['HVAC overhead', 'capital_cost']) def consense(x): v = x.iat[0] assert ((x == v).all() or x.isnull().all()), ( "The `potential` configuration option must agree for all renewable carriers, for now!" ) return v potential_mode = consense( pd.Series([ snakemake.config['renewable'][tech]['potential'] for tech in renewable_carriers ]))
snakemake.output = Dict() for item in outputs: snakemake.output[item] = snakemake.config[ 'summary_dir'] + '/{name}/csvs/{item}.csv'.format( name=snakemake.config['run'], item=item) networks_dict = {(cluster,lv,opt+sector_opt) : snakemake.config['results_dir'] + snakemake.config['run'] + '/postnetworks/elec_s{simpl}_{cluster}_lv{lv}_{opt}_{sector_opt}.nc'\ .format(simpl=simpl, cluster=cluster, opt=opt, lv=lv, sector_opt=sector_opt)\ for simpl in snakemake.config['scenario']['simpl'] \ for cluster in snakemake.config['scenario']['clusters'] \ for opt in snakemake.config['scenario']['opts'] \ for sector_opt in snakemake.config['scenario']['sector_opts'] \ for lv in snakemake.config['scenario']['lv']} print(networks_dict) costs_db = load_costs(Nyears=1., tech_costs="data/costs.csv", config=snakemake.config["costs"], elec_config=snakemake.config['electricity']) df = make_summaries(networks_dict) df["metrics"].loc["total costs"] = df["costs"].sum() to_csv(df)
if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake snakemake = mock_snakemake('prepare_network', network='elec', simpl='', clusters='40', ll='v0.3', opts='Co2L-24H') configure_logging(snakemake) opts = snakemake.wildcards.opts.split('-') n = pypsa.Network(snakemake.input[0]) Nyears = n.snapshot_weightings.objective.sum() / 8760. costs = load_costs(snakemake.input.tech_costs, snakemake.config['costs'], snakemake.config['electricity'], Nyears) set_line_s_max_pu(n, snakemake.config['lines']['s_max_pu']) for o in opts: m = re.match(r'^\d+h$', o, re.IGNORECASE) if m is not None: n = average_every_nhours(n, m.group(0)) break for o in opts: m = re.match(r'^\d+seg$', o, re.IGNORECASE) if m is not None: solver_name = snakemake.config["solving"]["solver"]["name"] n = apply_time_segmentation(n, m.group(0)[:-3], solver_name) break
length=h2_links.length.values, capital_cost=costs.at['H2 pipeline', 'capital_cost'] * h2_links.length, efficiency=costs.at['H2 pipeline', 'efficiency'], carrier="H2 pipeline") if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake snakemake = mock_snakemake('add_extra_components', network='elec', simpl='', clusters=5) configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) Nyears = n.snapshot_weightings.sum() / 8760. costs = load_costs(Nyears, tech_costs=snakemake.input.tech_costs, config=snakemake.config['costs'], elec_config=snakemake.config['electricity']) attach_storageunits(n, costs) attach_stores(n, costs) attach_hydrogen_pipelines(n, costs) add_nice_carrier_names(n, config=snakemake.config) n.export_to_netcdf(snakemake.output[0])
length=h2_links.length.values, capital_cost=costs.at['H2 pipeline', 'capital_cost'] * h2_links.length, efficiency=costs.at['H2 pipeline', 'efficiency'], carrier="H2 pipeline") if __name__ == "__main__": if 'snakemake' not in globals(): from _helpers import mock_snakemake snakemake = mock_snakemake('add_extra_components', network='elec', simpl='', clusters=5) configure_logging(snakemake) n = pypsa.Network(snakemake.input.network) elec_config = snakemake.config['electricity'] Nyears = n.snapshot_weightings.objective.sum() / 8760. costs = load_costs(snakemake.input.tech_costs, snakemake.config['costs'], elec_config, Nyears) attach_storageunits(n, costs, elec_config) attach_stores(n, costs, elec_config) attach_hydrogen_pipelines(n, costs, elec_config) add_nice_carrier_names(n, snakemake.config) n.export_to_netcdf(snakemake.output[0])