|
13 | 13 | import pandas as pd |
14 | 14 | import pypsa |
15 | 15 | from numpy import isclose |
| 16 | +from pypsa.statistics import get_transmission_carriers |
16 | 17 |
|
17 | 18 | from scripts._helpers import configure_logging, mock_snakemake |
18 | 19 | from scripts.add_electricity import calculate_annuity, load_costs |
@@ -4294,15 +4295,188 @@ def get_policy(n, investment_year): |
4294 | 4295 | def get_economy(n, region): |
4295 | 4296 | var = pd.Series() |
4296 | 4297 |
|
4297 | | - s = n.statistics |
4298 | | - grouper = ["country", "carrier"] |
4299 | | - system_cost = s.capex(groupby=grouper).add(s.opex(groupby=grouper)) |
| 4298 | + def get_tsc(n, country): |
| 4299 | + n.statistics.set_parameters(drop_zero=False) |
| 4300 | + capex = n.statistics.capex( |
| 4301 | + groupby=pypsa.statistics.groupers["name", "carrier"], nice_names=False |
| 4302 | + ) |
4300 | 4303 |
|
4301 | | - # Cost|Total Energy System Cost in billion EUR2020/yr |
4302 | | - var["Cost|Total Energy System Cost"] = round( |
4303 | | - system_cost.groupby("country").sum()[region] / 1e9, 4 |
| 4304 | + opex = n.statistics.opex( |
| 4305 | + groupby=pypsa.statistics.groupers["name", "carrier"], nice_names=False |
| 4306 | + ) |
| 4307 | + |
| 4308 | + # filter inter country transmission lines and links |
| 4309 | + inter_country_lines = n.lines.bus0.map(n.buses.country) != n.lines.bus1.map( |
| 4310 | + n.buses.country |
| 4311 | + ) |
| 4312 | + inter_country_links = n.links.bus0.map(n.buses.country) != n.links.bus1.map( |
| 4313 | + n.buses.country |
| 4314 | + ) |
| 4315 | + # |
| 4316 | + transmission_carriers = get_transmission_carriers(n).get_level_values("carrier") |
| 4317 | + transmission_lines = n.lines.carrier.isin(transmission_carriers) |
| 4318 | + transmission_links = n.links.carrier.isin(transmission_carriers) |
| 4319 | + # |
| 4320 | + country_transmission_lines = ( |
| 4321 | + (n.lines.bus0.str.contains(country)) & ~(n.lines.bus1.str.contains(country)) |
| 4322 | + ) | ( |
| 4323 | + ~(n.lines.bus0.str.contains(country)) & (n.lines.bus1.str.contains(country)) |
| 4324 | + ) |
| 4325 | + country_tranmission_links = ( |
| 4326 | + (n.links.bus0.str.contains(country)) & ~(n.links.bus1.str.contains(country)) |
| 4327 | + ) | ( |
| 4328 | + ~(n.links.bus0.str.contains(country)) & (n.links.bus1.str.contains(country)) |
| 4329 | + ) |
| 4330 | + # |
| 4331 | + inter_country_transmission_lines = ( |
| 4332 | + inter_country_lines & transmission_lines & country_transmission_lines |
| 4333 | + ) |
| 4334 | + inter_country_transmission_links = ( |
| 4335 | + inter_country_links & transmission_links & country_tranmission_links |
| 4336 | + ) |
| 4337 | + inter_country_transmission_lines_i = inter_country_transmission_lines[ |
| 4338 | + inter_country_transmission_lines |
| 4339 | + ].index |
| 4340 | + inter_country_transmission_links_i = inter_country_transmission_links[ |
| 4341 | + inter_country_transmission_links |
| 4342 | + ].index |
| 4343 | + inter_country_transmission_i = inter_country_transmission_lines_i.union( |
| 4344 | + inter_country_transmission_links_i |
| 4345 | + ) |
| 4346 | + |
| 4347 | + # |
| 4348 | + tsc = pd.concat([capex, opex], axis=1, keys=["capex", "opex"]) |
| 4349 | + tsc = tsc.reset_index().set_index("name") |
| 4350 | + tsc.loc[inter_country_transmission_i, ["capex", "opex"]] = ( |
| 4351 | + tsc.loc[inter_country_transmission_i, ["capex", "opex"]] / 2 |
| 4352 | + ) |
| 4353 | + tsc.rename( |
| 4354 | + index={ |
| 4355 | + index: index + " " + country for index in inter_country_transmission_i |
| 4356 | + }, |
| 4357 | + inplace=True, |
| 4358 | + ) |
| 4359 | + # rename inter region links and lines |
| 4360 | + to_rename_links = n.links[ |
| 4361 | + (n.links.bus0.str.contains(region)) |
| 4362 | + & (n.links.bus1.str.contains(region)) |
| 4363 | + & ~(n.links.index.str.contains(region)) |
| 4364 | + ].index |
| 4365 | + to_rename_lines = n.lines[ |
| 4366 | + (n.lines.bus0.str.contains(region)) |
| 4367 | + & (n.lines.bus1.str.contains(region)) |
| 4368 | + & ~(n.lines.index.str.contains(region)) |
| 4369 | + ].index |
| 4370 | + tsc.rename( |
| 4371 | + index={index: index + " " + region for index in to_rename_links}, |
| 4372 | + inplace=True, |
| 4373 | + ) |
| 4374 | + tsc.rename( |
| 4375 | + index={index: index + " " + region for index in to_rename_lines}, |
| 4376 | + inplace=True, |
| 4377 | + ) |
| 4378 | + |
| 4379 | + tsc = ( |
| 4380 | + tsc.filter(like=country, axis=0) |
| 4381 | + .drop("component", axis=1) |
| 4382 | + .groupby("carrier") |
| 4383 | + .sum() |
| 4384 | + ) |
| 4385 | + |
| 4386 | + return tsc |
| 4387 | + |
| 4388 | + def get_link_opex(n, carriers, region, sw): |
| 4389 | + # get flow of electricity/hydrogen... |
| 4390 | + # multiply it with the marginal costs |
| 4391 | + supplying = n.links[ |
| 4392 | + (n.links.carrier.isin(carriers)) |
| 4393 | + & (n.links.bus0.str.startswith(region)) |
| 4394 | + & (~n.links.bus1.str.startswith(region)) |
| 4395 | + ].index |
| 4396 | + |
| 4397 | + receiving = n.links[ |
| 4398 | + (n.links.carrier.isin(carriers)) |
| 4399 | + & (~n.links.bus0.str.startswith(region)) |
| 4400 | + & (n.links.bus1.str.startswith(region)) |
| 4401 | + ].index |
| 4402 | + |
| 4403 | + trade_out = 0 |
| 4404 | + for index in supplying: |
| 4405 | + # price of energy in trade country |
| 4406 | + marg_price = n.buses_t.marginal_price[n.links.loc[index].bus0] |
| 4407 | + trade = n.links_t.p1[index].mul(sw) |
| 4408 | + trade_out += marg_price.mul(trade).sum() |
| 4409 | + |
| 4410 | + trade_in = 0 |
| 4411 | + for index in receiving: |
| 4412 | + # price of energy in Germany |
| 4413 | + marg_price = n.buses_t.marginal_price[n.links.loc[index].bus0] |
| 4414 | + trade = n.links_t.p1[index].mul(sw) |
| 4415 | + trade_in += marg_price.mul(trade).sum() |
| 4416 | + return abs(trade_in) - abs(trade_out) |
| 4417 | + # > 0: costs for Germany |
| 4418 | + # < 0: profit for Germany |
| 4419 | + |
| 4420 | + def get_line_opex(n, region, sw): |
| 4421 | + supplying = n.lines[ |
| 4422 | + (n.lines.carrier.isin(["AC"])) |
| 4423 | + & (n.lines.bus0.str.startswith(region)) |
| 4424 | + & (~n.lines.bus1.str.startswith(region)) |
| 4425 | + ].index |
| 4426 | + receiving = n.lines[ |
| 4427 | + (n.lines.carrier.isin(["AC"])) |
| 4428 | + & (~n.lines.bus0.str.startswith(region)) |
| 4429 | + & (n.lines.bus1.str.startswith(region)) |
| 4430 | + ].index |
| 4431 | + |
| 4432 | + # i have to clip the trade |
| 4433 | + net_out = 0 |
| 4434 | + for index in supplying: |
| 4435 | + trade = n.lines_t.p1[index].mul(sw) |
| 4436 | + trade_out = trade.clip(lower=0) # positive |
| 4437 | + trade_in = trade.clip(upper=0) # negative |
| 4438 | + marg_price_DE = n.buses_t.marginal_price[n.lines.loc[index].bus0] |
| 4439 | + marg_price_EU = n.buses_t.marginal_price[n.lines.loc[index].bus1] |
| 4440 | + net_out += ( |
| 4441 | + trade_out.mul(marg_price_DE).sum() + trade_in.mul(marg_price_EU).sum() |
| 4442 | + ) |
| 4443 | + # net_out > 0: Germany is exporting more electricity |
| 4444 | + # net_out < 0: Germany is importing more electricity |
| 4445 | + |
| 4446 | + net_in = 0 |
| 4447 | + for index in receiving: |
| 4448 | + trade = n.lines_t.p1[index].mul(sw) |
| 4449 | + trade_in = trade.clip(lower=0) # positive |
| 4450 | + trade_out = trade.clip(upper=0) # negative |
| 4451 | + trade_out = trade_out.clip(upper=0) |
| 4452 | + marg_price_EU = n.buses_t.marginal_price[n.lines.loc[index].bus0] |
| 4453 | + marg_price_DE = n.buses_t.marginal_price[n.lines.loc[index].bus1] |
| 4454 | + net_in += ( |
| 4455 | + trade_in.mul(marg_price_EU).sum() + trade_out.mul(marg_price_DE).sum() |
| 4456 | + ) |
| 4457 | + # net_in > 0: Germany is importing more electricity |
| 4458 | + # net_in < 0: Germany is exporting more electricity |
| 4459 | + |
| 4460 | + return -net_out + net_in |
| 4461 | + |
| 4462 | + trade_carriers = [ |
| 4463 | + "DC", |
| 4464 | + "H2 pipeline", |
| 4465 | + "H2 pipeline (Kernnetz)", |
| 4466 | + "H2 pipeline retrofittedrenewable oil", |
| 4467 | + "renewable gas", |
| 4468 | + "methanol", |
| 4469 | + ] |
| 4470 | + |
| 4471 | + sw = n.snapshot_weightings.generators |
| 4472 | + tsc = get_tsc(n, region).sum().sum() |
| 4473 | + trade_costs = get_link_opex(n, trade_carriers, region, sw) + get_line_opex( |
| 4474 | + n, region, sw |
4304 | 4475 | ) |
4305 | 4476 |
|
| 4477 | + # Cost|Total Energy System Cost in billion EUR2020/yr |
| 4478 | + var["Cost|Total Energy System Cost"] = round((tsc + trade_costs) / 1e9, 4) |
| 4479 | + |
4306 | 4480 | return var |
4307 | 4481 |
|
4308 | 4482 |
|
|
0 commit comments