Since today's industrial electricity demand is distributed by
population and GDP, subtract this from the regular electricity demand
(which already has space/water heating subtracted).
Now regular electricity demand is only non-heating electricity demand
in residential and tertiary sectors.
Add back new industry electricity demand at the correct locations, as
determined using the hotmaps database.
I.e. per sector geographical distribution of industrial facilities
within each country.
Drop facilities outside Europe and with no geocoordinates.
Use ETS emissions as a distribution key; where emissions data is
missing, substitute with an average for that sector and that country
(strong assumption).
I.e. when the generators are clustered to the "simplified" network
resolution, but the grid is clustered further, e.g. by using the
clusters = 37m "m" option.
List classes in config.yaml, rather than integer selection in
build_biomass_potentials.py.
Also output potentials for all years and scenarios for analysis.
I.e. when the generators are clustered to the "simplified" network
resolution, but the grid is clustered further, e.g. by using the
clusters = 37m "m" option.
Don't fix uniform ratios e.g. of 0.3:0.7 primary:secondary for steel
and aluminium, but convert the necessary amount of existing primary in
each country so that the overall ratio applies at European level.
This stops sudden swings from primary to secondary in countries
dominated by primary production.
Remove non-existing biomass from chemicals and cement, since these
need higher temperatures than achievable with residues and waste.
Increase biomass in pulp and paper (since already used extensively
here and T < 500), and replace methane with biomass in food, beverages
and tobacco, since temperatures needed are low (T < 500).
This allows us to control the substitution of natural gas for hydrogen
in NH3 production.
Remaining basic chemicals are olefins, BTX and chlorine.
For 2015 NH3 production, we use the USGS data source.
This was handled before in industry_sector_ratios.csv which was
confusing.
Now industry_sector_ratios.csv represents the genuine energy
consumption per tonne of material for each industrial route
(MWh/tMaterial).
An new file is created with ktMaterial/a in
industrial_production_per_country_tomorrow.csv which contains changes
to the fraction of primary/secondary routes compared to today's
production in industrial_production_per_country.csv.
This is less confusing I think.
Rather than taking a mean of the clustered connection costs.
Apply cost update also for overnight scenarios based on planning year.
Add land costs for onshore wind.
- add_brownfield.py: Have to make sure that for each CHP there is both
a heat and electric link, but they have different p_nom for each
CHP, so have to make sure we don't remove one without the other.
- solve_network.py: Make sure extra_functionality constraints for CHP
power-heat feasibility graph also work for non-extendable CHPs.
This simplifies the structure of add_brownfield.py dramatically.
Some other changes need to be make elsewhere because of name
changes (e.g. battery constraints in solve_network.py).
In order to calculate connection costs, average values for underground_fraction and average_distance are calculated for all the buses in the initial network mapped to the clustered network.
Previously they were distributed only by country to the first node in
the country.
Now conventional power plants are assigned to the correct node using
the bus map from PyPSA-Eur.
Wind and solar are distributed in each country by capacity factor.
The code has been refactored and a bug was fixed whereby total
capacities of wind and solar in each country were not correct.
Now the years in the config.yaml for myopic are integers not strings.
In prepare_costs, you need the min_count=1 in the sum so that it
generates NaNs for missing data (rather than 0) so that NaNs can be
subsituted by .fillna in the next line. Otherwise many values
(discount rates and efficiencies for solar, wind) are set to zero.
Also added carriers, storage and generators for coal, nuclear and
oil. (This needs to be organized better soon so that the carriers are
defined in config.yaml.)
Existing onwind and offwind capacity are now read from IRENA database, similarly to solar capacities. Previously we were using thewindpower.net database which is not open.
These geometries are apparently invalid due to self-crossing or
self-touching polygons.
The geometries are created by pypsa-eur/scripts/cluster_network.py but
appear to be valid before being written to file.
They are only valid after being read back in from file.
This seems to indicate some numerical issue relating to file reading
and writing.
Now the geometries are cleaned after being read in.
This commit now work with PyPSA-Eur 0.1.0 (tested with commit
bb3477 from 14th April 2020).
Changes to line/link_widths/colors for plotting networks in PyPSA
0.17.0.
Other corrections to plotting code so it works with this version.
Include oil boilers in colors in config.yaml.
* prepare_sector_network:
- add link for oil boiler in function add_industry()
- add function for partitioning clusters into different heat node types
* config.yaml: add option for oil_boiler
* costs.csv: add costs for oil boiler
* changes for retrofitting
* changed Snakefile to work with new pypsa-eur version, change solve_network.py to clip also n.generators_t.p_min_pu
* removed retrofitting data files
Use s_nom_min for the reference point for the transmission
reinforcement not s_nom, since s_nom is now overwritten for LV > 1.0
(the old pyomo code kept the s_nom variable fixed in the pyomo model
rather than via pypsa setting s_nom_extendable = False, like the
nomopyomo code now does).
The legend scale of the H2 network electrolyzers is wrong. I don't yet
understand why. Possibly the cost scale in the other map is also wrong.
df.loc[idx[a,b,some_list],label] does NOT preserve the ordering of
some_list, but sorts it instead. Therefore the pattern:
df.loc[idx[a,b,s.index],label] = s.values
was mismatching the index and values.
Remove emissions from hydrogen production for ammonia (since H2 now
comes from electrolysis).
Allow process emissions from petrochemical production to be captured
(the carbon is not necessarily fossil, but could come from CCU).
With new pandas:
pd.Index([])|pd.MultiIndex(...)
returns a pd.Index, not a pd.MultiIndex, so just reversed:
pd.MultiIndex(...)|pd.Index([])
This returns a pd.MultiIndex.
These are different for residential and services demand.
Also include Snakefile in config files copied for each run.
Use gurobi settings from gurobi support for speed.
Commented out settings for testing randomness for noise.
All urban central (i.e. district heating) is aggregated to the same
profile and bus.
The code is now written to cycle over each heating sector to add
demand and supply technologies, only changing what is necessary to
change, rather than just copying chunks of code and modifying
parameters there. This should make it easier to get an overview of
what's going on.
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.
Because there was insufficient solid biomass in 3-4 countries to
supply industry for it locally, and we need to account for transport
of solid biomass.
Should be replaced by transport cost links between countries.
Heat buses renamed to:
rural (for low-density areas where district heating not possible)
urban decentral (for high-density areas without district heating and
individual heating technologies) (used to be called "urban")
urban central (for high-density areas with district heating) (used to
be called "central")
District heating losses applied only to urban central.
Before both initial SOC and final SOC were set to be zero, which
prevents synthetic fuel transfer over the year boundary, and prevents
the use of fossil fuels for non-zero CO2 scenarios.
Now done properly with cyclic Store (prevents accumulation of fossil
fuels as a form of sequestration) and Generator (to imitate fossil
fuel extraction).
tech name must only appear, but not be identical to generator
carrier. This allows to use the name "offshore" for both "offshore-ac"
and "offshore-dc", but then "solar" also catches "solar thermal",
which is fine since for solar thermal potentials are np.inf, unless
limit is 0 since np.inf*0 is nan.
Remove non-renewable generator and storage units from electricity-only
base network, since they're added differently here with links.
Remove unncessary cruft from config.yaml which is not used by
PyPSA-Eur-Sec (e.g. renewable configuration parameters).
Rename "naptha" to correct "naphtha".