move uc assigment to add_electricity
make code backwards-compatible
This commit is contained in:
parent
cc6bae282f
commit
519a4f2a2a
@ -254,6 +254,8 @@ renewable:
|
|||||||
clip_min_inflow: 1.0
|
clip_min_inflow: 1.0
|
||||||
|
|
||||||
conventional:
|
conventional:
|
||||||
|
unit_commitment: false
|
||||||
|
dynamic_fuel_price: false
|
||||||
nuclear:
|
nuclear:
|
||||||
p_max_pu: "data/nuclear_p_max_pu.csv" # float of file name
|
p_max_pu: "data/nuclear_p_max_pu.csv" # float of file name
|
||||||
|
|
||||||
@ -345,8 +347,6 @@ solar_thermal:
|
|||||||
|
|
||||||
# only relevant for foresight = myopic or perfect
|
# only relevant for foresight = myopic or perfect
|
||||||
existing_capacities:
|
existing_capacities:
|
||||||
unit_commitment: true # if unit commitment (UC) for conventional power plants is used
|
|
||||||
# UC is only applied to extendable plants if linearized UC is used
|
|
||||||
grouping_years_power: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030]
|
grouping_years_power: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030]
|
||||||
grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] # these should not extend 2020
|
grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] # these should not extend 2020
|
||||||
threshold_capacity: 10
|
threshold_capacity: 10
|
||||||
|
@ -243,6 +243,8 @@ renewable:
|
|||||||
clip_min_inflow: 1.0
|
clip_min_inflow: 1.0
|
||||||
|
|
||||||
conventional:
|
conventional:
|
||||||
|
unit_commitment: true
|
||||||
|
dynamic_fuel_price: true
|
||||||
nuclear:
|
nuclear:
|
||||||
p_max_pu: "data/nuclear_p_max_pu.csv" # float of file name
|
p_max_pu: "data/nuclear_p_max_pu.csv" # float of file name
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ rule add_electricity:
|
|||||||
countries=config["countries"],
|
countries=config["countries"],
|
||||||
renewable=config["renewable"],
|
renewable=config["renewable"],
|
||||||
electricity=config["electricity"],
|
electricity=config["electricity"],
|
||||||
conventional=config.get("conventional", {}),
|
conventional=config["conventional"],
|
||||||
costs=config["costs"],
|
costs=config["costs"],
|
||||||
input:
|
input:
|
||||||
**{
|
**{
|
||||||
@ -306,6 +306,7 @@ rule add_electricity:
|
|||||||
**{
|
**{
|
||||||
f"conventional_{carrier}_{attr}": fn
|
f"conventional_{carrier}_{attr}": fn
|
||||||
for carrier, d in config.get("conventional", {None: {}}).items()
|
for carrier, d in config.get("conventional", {None: {}}).items()
|
||||||
|
if carrier in config["electricity"]["conventional_carriers"]
|
||||||
for attr, fn in d.items()
|
for attr, fn in d.items()
|
||||||
if str(fn).startswith("data/")
|
if str(fn).startswith("data/")
|
||||||
},
|
},
|
||||||
@ -315,6 +316,7 @@ rule add_electricity:
|
|||||||
powerplants=RESOURCES + "powerplants.csv",
|
powerplants=RESOURCES + "powerplants.csv",
|
||||||
hydro_capacities=ancient("data/bundle/hydro_capacities.csv"),
|
hydro_capacities=ancient("data/bundle/hydro_capacities.csv"),
|
||||||
geth_hydro_capacities="data/geth2015_hydro_capacities.csv",
|
geth_hydro_capacities="data/geth2015_hydro_capacities.csv",
|
||||||
|
unit_commitment="data/unit_commitment.csv",
|
||||||
fuel_price="data/validation/monthly_fuel_price.csv",
|
fuel_price="data/validation/monthly_fuel_price.csv",
|
||||||
load=RESOURCES + "load.csv",
|
load=RESOURCES + "load.csv",
|
||||||
nuts3_shapes=RESOURCES + "nuts3_shapes.geojson",
|
nuts3_shapes=RESOURCES + "nuts3_shapes.geojson",
|
||||||
|
@ -12,7 +12,6 @@ rule solve_network:
|
|||||||
"co2_sequestration_potential", 200
|
"co2_sequestration_potential", 200
|
||||||
),
|
),
|
||||||
input:
|
input:
|
||||||
unit_commitment_params="data/unit_commitment.csv",
|
|
||||||
network=RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc",
|
network=RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc",
|
||||||
output:
|
output:
|
||||||
network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc",
|
network=RESULTS + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc",
|
||||||
|
@ -366,12 +366,13 @@ def attach_wind_and_solar(
|
|||||||
def attach_conventional_generators(
|
def attach_conventional_generators(
|
||||||
n,
|
n,
|
||||||
costs,
|
costs,
|
||||||
fuel_price,
|
|
||||||
ppl,
|
ppl,
|
||||||
conventional_carriers,
|
conventional_carriers,
|
||||||
extendable_carriers,
|
extendable_carriers,
|
||||||
conventional_params,
|
conventional_params,
|
||||||
conventional_inputs,
|
conventional_inputs,
|
||||||
|
unit_commitment=None,
|
||||||
|
fuel_price=None,
|
||||||
):
|
):
|
||||||
carriers = set(conventional_carriers) | set(extendable_carriers["Generator"])
|
carriers = set(conventional_carriers) | set(extendable_carriers["Generator"])
|
||||||
_add_missing_carriers_from_costs(n, costs, carriers)
|
_add_missing_carriers_from_costs(n, costs, carriers)
|
||||||
@ -383,19 +384,30 @@ def attach_conventional_generators(
|
|||||||
)
|
)
|
||||||
ppl["efficiency"] = ppl.efficiency.fillna(ppl.efficiency_r)
|
ppl["efficiency"] = ppl.efficiency.fillna(ppl.efficiency_r)
|
||||||
|
|
||||||
fuel_price = fuel_price.assign(OCGT=fuel_price["gas"], CCGT=fuel_price["gas"]).drop(
|
if unit_commitment is not None:
|
||||||
"gas", axis=1
|
committable_attrs = ppl.carrier.isin(unit_commitment).to_frame('committable')
|
||||||
)
|
for attr in unit_commitment.index:
|
||||||
fuel_price = fuel_price.reindex(ppl.carrier, axis=1)
|
default = pypsa.components.component_attrs['Generator'].default[attr]
|
||||||
fuel_price.fillna(costs.fuel, inplace=True)
|
committable_attrs[attr] = ppl.carrier.map(unit_commitment.loc[attr]).fillna(default)
|
||||||
fuel_price.columns = ppl.index
|
else:
|
||||||
marginal_cost = (fuel_price.div(ppl.efficiency)).add(ppl.carrier.map(costs.VOM))
|
committable_attrs = {}
|
||||||
|
|
||||||
logger.info(
|
|
||||||
"Adding {} generators with capacities [GW] \n{}".format(
|
if fuel_price is not None:
|
||||||
len(ppl), ppl.groupby("carrier").p_nom.sum().div(1e3).round(2)
|
fuel_price = (fuel_price.assign(OCGT=fuel_price['gas'],
|
||||||
)
|
CCGT=fuel_price['gas'])
|
||||||
)
|
.drop("gas", axis=1))
|
||||||
|
missing_carriers = list(carriers - set(fuel_price))
|
||||||
|
fuel_price = fuel_price.assign(**costs.fuel[missing_carriers])
|
||||||
|
fuel_price = fuel_price.reindex(ppl.carrier, axis=1)
|
||||||
|
fuel_price.columns = ppl.index
|
||||||
|
marginal_cost = fuel_price.div(ppl.efficiency).add(ppl.carrier.map(costs.VOM))
|
||||||
|
else:
|
||||||
|
marginal_cost = ppl.carrier.map(costs.VOM) + ppl.carrier.map(costs.fuel) / ppl.efficiency
|
||||||
|
|
||||||
|
# Define generators using modified ppl DataFrame
|
||||||
|
caps = ppl.groupby("carrier").p_nom.sum().div(1e3).round(2)
|
||||||
|
logger.info(f"Adding {len(ppl)} generators with capacities [GW] \n{caps}")
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Generator",
|
"Generator",
|
||||||
@ -410,9 +422,10 @@ def attach_conventional_generators(
|
|||||||
capital_cost=ppl.capital_cost,
|
capital_cost=ppl.capital_cost,
|
||||||
build_year=ppl.datein.fillna(0).astype(int),
|
build_year=ppl.datein.fillna(0).astype(int),
|
||||||
lifetime=(ppl.dateout - ppl.datein).fillna(np.inf),
|
lifetime=(ppl.dateout - ppl.datein).fillna(np.inf),
|
||||||
|
**committable_attrs
|
||||||
)
|
)
|
||||||
|
|
||||||
for carrier in conventional_params:
|
for carrier in set(conventional_params) & carriers:
|
||||||
# Generators with technology affected
|
# Generators with technology affected
|
||||||
idx = n.generators.query("carrier == @carrier").index
|
idx = n.generators.query("carrier == @carrier").index
|
||||||
|
|
||||||
@ -752,18 +765,28 @@ if __name__ == "__main__":
|
|||||||
k: v for k, v in snakemake.input.items() if k.startswith("conventional_")
|
k: v for k, v in snakemake.input.items() if k.startswith("conventional_")
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fuel_price = pd.read_csv(snakemake.input.fuel_price, index_col=[0], header=[0])
|
if params.conventional["unit_commitment"]:
|
||||||
m_fuel_price.index = pd.date_range(start="2019-01-01", end="2019-12-01", freq="MS")
|
unit_commitment = pd.read_csv(snakemake.input.unit_commitment, index_col=0)
|
||||||
fuel_price = m_fuel_price.reindex(n.snapshots).fillna(method="ffill")
|
else:
|
||||||
|
unit_commitment = None
|
||||||
|
|
||||||
|
if params.conventional["dynamic_fuel_price"]:
|
||||||
|
monthly_fuel_price = pd.read_csv(snakemake.input.fuel_price, index_col=0, header=0)
|
||||||
|
monthly_fuel_price.index = pd.date_range(start=n.snapshots[0], end=n.snapshots[-1], freq='MS')
|
||||||
|
fuel_price = monthly_fuel_price.reindex(n.snapshots).fillna(method="ffill")
|
||||||
|
else:
|
||||||
|
fuel_price = None
|
||||||
|
|
||||||
attach_conventional_generators(
|
attach_conventional_generators(
|
||||||
n,
|
n,
|
||||||
costs,
|
costs,
|
||||||
fuel_price,
|
|
||||||
ppl,
|
ppl,
|
||||||
conventional_carriers,
|
conventional_carriers,
|
||||||
extendable_carriers,
|
extendable_carriers,
|
||||||
params.conventional,
|
params.conventional,
|
||||||
conventional_inputs,
|
conventional_inputs,
|
||||||
|
unit_commitment=unit_commitment,
|
||||||
|
fuel_price=fuel_price,
|
||||||
)
|
)
|
||||||
|
|
||||||
attach_wind_and_solar(
|
attach_wind_and_solar(
|
||||||
|
@ -149,8 +149,6 @@ def prepare_network(
|
|||||||
planning_horizons=None,
|
planning_horizons=None,
|
||||||
co2_sequestration_potential=None,
|
co2_sequestration_potential=None,
|
||||||
):
|
):
|
||||||
if snakemake.config["existing_capacities"]["unit_commitment"]:
|
|
||||||
add_unit_commitment(n, snakemake.input.unit_commitment_params)
|
|
||||||
|
|
||||||
if "clip_p_max_pu" in solve_opts:
|
if "clip_p_max_pu" in solve_opts:
|
||||||
for df in (
|
for df in (
|
||||||
@ -600,19 +598,6 @@ def extra_functionality(n, snapshots):
|
|||||||
add_pipe_retrofit_constraint(n)
|
add_pipe_retrofit_constraint(n)
|
||||||
|
|
||||||
|
|
||||||
def add_unit_commitment(n, fn):
|
|
||||||
"""
|
|
||||||
Add unit commitment.
|
|
||||||
"""
|
|
||||||
c = "Generator"
|
|
||||||
uc_data = pd.read_csv(fn, index_col=0)
|
|
||||||
n.df(c).loc[n.df(c).carrier.isin(uc_data.columns), "committable"] = True
|
|
||||||
for attr in uc_data.index:
|
|
||||||
n.df(c)[attr].update(n.df(c)["carrier"].map(uc_data.loc[attr]).dropna())
|
|
||||||
gen_i = n.df(c).query("carrier in @uc_data.columns").index
|
|
||||||
n.df(c).loc[gen_i, "committable"] = True
|
|
||||||
|
|
||||||
|
|
||||||
def solve_network(n, config, solving, opts="", **kwargs):
|
def solve_network(n, config, solving, opts="", **kwargs):
|
||||||
set_of_options = solving["solver"]["options"]
|
set_of_options = solving["solver"]["options"]
|
||||||
solver_options = solving["solver_options"][set_of_options] if set_of_options else {}
|
solver_options = solving["solver_options"][set_of_options] if set_of_options else {}
|
||||||
|
Loading…
Reference in New Issue
Block a user