pypsa-eur icon indicating copy to clipboard operation
pypsa-eur copied to clipboard

Add endogenous transport option

Open s8au opened this issue 2 years ago • 15 comments

  • select with endogenous_transport in config file
  • it is possible to select transport shares for part of the fuel types
  • creates ICE-vehicle-fleet for baseyear if myopic is selected and no transport share is defined
  • adds constraints for endogenously chosen EVs in solve_network

relies on PR in technology-data repository: BertoGBG:master Closes https://github.com/PyPSA/pypsa-eur/issues/507.

Changes proposed in this Pull Request

Checklist

  • [x] I tested my contribution locally and it seems to work fine.
  • [ ] Code and workflow changes are sufficiently documented.
  • [x] Changed dependencies are added to envs/environment.yaml.
  • [x] Changes in configuration options are added in all of config.default.yaml.
  • [x] Changes in configuration options are also documented in doc/configtables/*.csv.
  • [x] A release note doc/release_notes.rst is added.

s8au avatar Sep 06 '23 12:09 s8au

The current definition of p_nom for the link "land transport EV" needs to be changed. Currently, it is based on the maximum value of the transport demand

n.links.loc[ (n.links.carrier == "land transport EV") & (n.links.bus1.str.contains(place)), "p_nom", ] = electric_share * max(p_nom[place])

This represents the minimum number of cars needed to supply that demand, but in reality, cars are most of the time parked and we should use the total number of cars, as it was done before

https://github.com/PyPSA/pypsa-eur/blob/706942957ba2d8a11a669357adb6d6289b5fea78/scripts/prepare_sector_network.py#L1501

This is important to avoid problems when calculating the cost associated with cars.

martavp avatar Sep 18 '23 09:09 martavp

There is a bug when adding the storage for EVs exogenous. The following code

n.stores.loc[ (n.stores.carrier == "EV battery storage") & (n.links.bus1.str.contains(place)), "e_nom", ] = ( number_cars[place] * options.get("bev_energy", 0.05) * options["bev_availability"] * electric_share )

Should be:

n.stores.loc[ (n.stores.carrier == "EV battery storage") & (n.stores.bus.str.contains(place)), "e_nom", ] = ( number_cars[place] * options.get("bev_energy", 0.05) * options["bev_availability"] * electric_share )

martavp avatar Sep 18 '23 10:09 martavp

The constraint relating the BEV charge rate and the storage capacity of the batteries, needs to take into account that in the config file it can be selected that only a percentage of the BEV provides flexibility

lhs2 = ( n.model.variables["Store-e_nom"].loc[ev_store] / n.config["sector"]["bev_energy"] )

should be:

lhs2 = ( n.model.variables["Store-e_nom"].loc[ev_store] / (n.config["sector"]["bev_energy"]*n.config["sector"]["bev_availability"]) )

martavp avatar Sep 18 '23 12:09 martavp

EDITED on 20/09/2023 at 8:35

I found a bug in the definition of p_max_pu and p_min_pu of the link "land transport oil" The following

n.links_t.p_max_pu[ n.links[ (n.links.carrier == "land transport oil") & (n.links.bus1.str.contains(place)) ].index.values[0] ] = ((p_nom[place]) / max(p_nom[place]) * ice_efficiency / p_set[place])

should be:

n.links_t.p_max_pu[ n.links[ (n.links.carrier == "land transport oil") & (n.links.bus1.str.contains(place)) ].index.values[0] ] = p_nom[place]/ (max(p_nom[place]* ice_efficiency)

otherwise, since p_nom and p_set are defined to be equal on a previous line, p_max_pu becomes a constant number and the flow of energy through that link is not able to supply the land transport demand.

The definition of the efficiency in the link should also be modified:

the current definition:

efficiency=1.0 / options["transport_internal_combustion_efficiency"] * p_set[nodes],

should be:

efficiency=options["transport_internal_combustion_efficiency"]

IMPORTANT: This should be changed for p_max_pu and p_min pu of both links 'land transport oil' and 'land transport fuel cell'

martavp avatar Sep 18 '23 13:09 martavp

@martavp @s8au thanks a lot for all your work on this!

Tom and I just had a look at the code since we would like to have the endogenous land transport in the main repository quite soon. Two main points came to our mind:

1.) As a first step it made make sense to fix the number of cars and not allow switching between cars by assuming a p_min_pu=p_max_pu=profile transport demand for all three links (EV, H2 Fuel Cell and ICEs). This should also speed up the solving. 2.) Further the transport demand profile p_set should not be shifted since this was only done for smoothing the EV charging. We can first just leave out the shifting completely when defining p_set . In a second step one could think about adding a time-dependent efficiency to the EV links to account for different charging times.

@s8au would you have time to include it in the next two weeks or should we give it a try? Did you have time to check also for newer cost assumptions for EVs?

lisazeyen avatar Oct 26 '23 13:10 lisazeyen

@lisazeyen

Tom and I just had a look at the code since we would like to have the endogenous land transport in the main repository quite soon. Two main points came to our mind:

1.) As a first step it made make sense to fix the number of cars and not allow switching between cars by assuming a p_min_pu=p_max_pu=profile transport demand for all three links (EV, H2 Fuel Cell and ICEs). This should also speed up the solving. 2.) Further the transport demand profile p_set should not be shifted since this was only done for smoothing the EV charging. We can first just leave out the shifting completely when defining p_set . In a second step one could think about adding a time-dependent efficiency to the EV links to account for different charging times.

@s8au would you have time to include it in the next two weeks or should we give it a try? Did you have time to check also for newer cost assumptions for EVs?

Thank you both for looking over it and your suggestions. I will try to include the p_min_pu/p_max_pu constraint and remove the smoothing next week. I looked a bit around but so far I only found a datasheet for commercial freight and passenger transport . Did you have something specific in mind?

s8au avatar Oct 27 '23 15:10 s8au

@lisazeyen

Tom and I just had a look at the code since we would like to have the endogenous land transport in the main repository quite soon. Two main points came to our mind: 1.) As a first step it made make sense to fix the number of cars and not allow switching between cars by assuming a p_min_pu=p_max_pu=profile transport demand for all three links (EV, H2 Fuel Cell and ICEs). This should also speed up the solving. 2.) Further the transport demand profile p_set should not be shifted since this was only done for smoothing the EV charging. We can first just leave out the shifting completely when defining p_set . In a second step one could think about adding a time-dependent efficiency to the EV links to account for different charging times. @s8au would you have time to include it in the next two weeks or should we give it a try? Did you have time to check also for newer cost assumptions for EVs?

Thank you both for looking over it and your suggestions. I will try to include the p_min_pu/p_max_pu constraint and remove the smoothing next week. I looked a bit around but so far I only found a datasheet for commercial freight and passenger transport . Did you have something specific in mind?

Great! I think the technology data is a good source for the heavy duty vehicles. For the light vehicles I guess there is a Bloomberg report for at least EVs. But I think every source for light vehicles which is a bit more up to date (like after 2020) should be fine!

lisazeyen avatar Oct 30 '23 11:10 lisazeyen

Great! I think the technology data is a good source for the heavy duty vehicles. For the light vehicles I guess there is a Bloomberg report for at least EVs. But I think every source for light vehicles which is a bit more up to date (like after 2020) should be fine!

BNEF include cost assumption for trucks in Figure 4 in https://assets.bbhub.io/professional/sites/24/2431510_BNEFElectricVehicleOutlook2023_ExecSummary.pdf (here, we agree that using DEA is better)

and cost assumptions for EVs until 2030 in Figure 28. https://www.transportenvironment.org/discover/hitting-the-ev-inflection-point/ (because the data only covers until 2030 and the report includes a disclaimer saying that we should not use the data, I suggest we keep using Fraunhofer data), unless @s8au and I have missed some additional BNEF database?

But you are totally right @lisazeyen that is too pessimistic about EV costs. See below the cost comparison for EVs between our current assumptions and BNEF (red dots). We will implement a cost sensitivity analysis soon so that we can learn about the impacts.

BNEF_vs_Fraunhofer

martavp avatar Nov 02 '23 10:11 martavp

Great! I think the technology data is a good source for the heavy duty vehicles. For the light vehicles I guess there is a Bloomberg report for at least EVs. But I think every source for light vehicles which is a bit more up to date (like after 2020) should be fine!

BNEF include cost assumption for trucks in Figure 4 in https://assets.bbhub.io/professional/sites/24/2431510_BNEFElectricVehicleOutlook2023_ExecSummary.pdf (here, we agree that using DEA is better)

and cost assumptions for EVs until 2030 in Figure 28. https://www.transportenvironment.org/discover/hitting-the-ev-inflection-point/ (because the data only covers until 2030 and the report includes a disclaimer saying that we should not use the data, I suggest we keep using Fraunhofer data), unless @s8au and I have missed some additional BNEF database?

But you are totally right @lisazeyen that is too pessimistic about EV costs. See below the cost comparison for EVs between our current assumptions and BNEF (red dots). We will implement a cost sensitivity analysis soon so that we can learn about the impacts.

BNEF_vs_Fraunhofer

Yes, I guess a cost sensitivity is the best way!

lisazeyen avatar Nov 02 '23 12:11 lisazeyen

The current definition of p_nom for the link "land transport EV" needs to be changed. Currently, it is based on the maximum value of the transport demand

n.links.loc[ (n.links.carrier == "land transport EV") & (n.links.bus1.str.contains(place)), "p_nom", ] = electric_share * max(p_nom[place])

This represents the minimum number of cars needed to supply that demand, but in reality, cars are most of the time parked and we should use the total number of cars, as it was done before

https://github.com/PyPSA/pypsa-eur/blob/706942957ba2d8a11a669357adb6d6289b5fea78/scripts/prepare_sector_network.py#L1501

This is important to avoid problems when calculating the cost associated with cars.

I updated it for the exogenous land transport EV I also indicate with the :rocket: that I fixed the problems in the other comments

s8au avatar Nov 03 '23 08:11 s8au

Hi @s8au ,

I mentioned to @lisazeyen yesterday that she can start reviewing this. To facilitate the review, Can you update the PR to the last version of the master branch and check that everything run smoothly? This facilitates the revision (currently endogenous-transport-related and non-related changes are shown and make the revision cumbersome)

There are two additional small issues:

[ ] 1. I think the link representing the "capacity" of EVs to supply transport demand is not correct. The current definition represents the capacity for charging the cars since options.get("bev_charge_rate", 0.011) is the capacity to charge a car. Can you please correct this? (similarly to the exogenous capacity definition for H2 and ICE cars)?

[] 2. I understand how you estimated the capacity of the "land transport oil." In essence, you calculate the minimum capacity needed to supply the demand for land transport today and then decommission a percentage of it in every future planning horizon. The approach is fine for me.

However, in reality, we have many more cars than "needed". Can you calculate the ratio between the existing number of cars and the cars that you calculate that are needed to supply the demand and write it as a log message? Something like: "Although, existing ICE vehicles in 2020 account for XXXX, the model assumes only the minimum number of ICE vehicles to supply the transport demand which represents XXX"

martavp avatar Nov 08 '23 06:11 martavp

@martavp @lisazeyen I updated the branch with the master branch and I ran a test case for the exogenous and the endogenous transport each (resulting in again being behind by 4 commits). Since these are only minor changes I would prefer to update them with additional changes to my code.

s8au avatar Nov 13 '23 14:11 s8au

I updated the PR with the newest version, so we can discuss the changes, but I still have to check if the added code in the add_brownfield works because the Gurobi license on our cluster has expired. @lisazeyen I had to move the calculation of the profiles for the p_min_pu/p_max_pu constraints after the links have their new temporal resolution because the efficiencies are now time dependent with the temperature corrections. Due to this, taking the mean of the profiles gives wrong values. Gurobi has some trouble with setting these profiles and then solving the land transport when the links p_nom_extendable is set to True. I am currently trying to only constrain two out of three links directly (which works fine) and then constrain the third link for the myopic pathway in the add_brownfield script (WIP). The exogenous pathway should work fine, it runs - depending on the CO2 budget - until 2040/2050 before becoming infeasible. But that was also what I experienced with the unmodified code from the repository.

s8au avatar Feb 06 '24 13:02 s8au

@martavp I added a commit with the fixed bug, so it should run now

s8au avatar Feb 15 '24 09:02 s8au

@s8au @martavp I am currently planning to integrate as the land transport demand as one single node and then the links for the different car types. I made a suggestion, which you can see the PR here #957.

lisazeyen avatar Mar 04 '24 08:03 lisazeyen