Skip to content

Fixes/#220 #237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 47 commits into
base: release/v0.4.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
32026ec
Replace part of timeseries script
Feb 21, 2018
69172ef
Fix import
Feb 21, 2018
bb91a0e
Handle generator data for neighbours
Mar 19, 2018
b5f54ec
Add helper file
Mar 19, 2018
2d56679
Remove sql part of timeseries generator script
Mar 19, 2018
e2bc798
Update import statement
Mar 19, 2018
5f51049
Rename files
Mar 19, 2018
3ea0e4d
Update eGo_data_processing with new script files
Mar 19, 2018
68e7b4f
Address name changes in import statements
Mar 19, 2018
f70d08a
Add missing orm classes
Apr 1, 2018
9bf70be
Begin handling p_max_pu
Apr 1, 2018
f4765af
Calculate average feedin per aggr_id, source
Apr 2, 2018
afccca9
Fix wrong return value in weighted_average_feedin
Apr 2, 2018
6cb7671
Retrieve PQ-Sets for update
Apr 2, 2018
750486e
Update comment
Apr 2, 2018
a11f01d
Update p_max_pu on existing PQ-Sets
Apr 2, 2018
d5cb1e3
Separate assignment of p_max_pu
Apr 9, 2018
2aafccd
Update renpass_gis helper container
Apr 9, 2018
cf5d3ff
Use log function with stored variable
Apr 9, 2018
4f741ae
Refactor timeseries generator
Apr 9, 2018
5b90b30
Rename constant FUEL_TO_SOURCE
Apr 9, 2018
5f6447e
Update header
Apr 17, 2018
986ce56
Add logging in timeseries generator
Apr 17, 2018
78a31dc
Move generator assignment for neighbouring countries
Apr 17, 2018
ca372ed
Merge branch 'release/v0.4.0' into fixes/#220
Apr 17, 2018
02e34ca
Add logging
Apr 17, 2018
6804f86
Comment out logging info
Apr 17, 2018
9df8de1
Rename files
Apr 17, 2018
c9e0e70
Rename file
Apr 17, 2018
1e38ca1
Filter for neighboursid
Apr 17, 2018
6ff96c6
Remove assignment of generators
Apr 17, 2018
a8a2138
Include p_nom in generator assignment
Apr 17, 2018
f0132cd
Replace tab with whitespace in main executable
Apr 17, 2018
2948d0c
Update main executable
Apr 17, 2018
cb98354
Rename file
Apr 17, 2018
71968a2
Update main executable
Apr 17, 2018
f74b5f3
Rename file
Apr 17, 2018
114dc45
Rename file
Apr 17, 2018
9f885b0
Update main executable
Apr 17, 2018
fbf450c
Bugfix in other_p_set
Apr 17, 2018
77cd70c
Rename file
Apr 22, 2018
bfa0757
Add missing orm class
Apr 22, 2018
77284bc
Do not write p_sets for renewables
Apr 22, 2018
e6fdb88
Add script handling p_max_pu neighbouring countries
Apr 22, 2018
b66bc1f
Add script handling offshore feedins
Apr 22, 2018
6657ae7
Update main executable
Apr 22, 2018
ea28b6a
Update comments / pep8
Apr 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions dataprocessing/eGo_data_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Also see corresponding BPML diagram.
"""

__copyright__ = "Reiner Lemoine Institut"
__copyright__ = "Reiner Lemoine Institut gGmbH"
__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)"
__url__ = "https://github.com/openego/data_processing/blob/master/LICENSE"
__author__ = "gplssm, Ludee"
Expand Down Expand Up @@ -89,31 +89,37 @@ def data_processing():
# 'rea/ego_dp_rea_results.sql', # Results and statistics

## POWERFLOW
# 'ego_dp_powerflow_assignment_otgid.sql', # assign otg_id to pp lists
# 'ego_dp_powerflow_assignment_unid.sql', # create a unified_id over all pp (res and conv)
# 'ego_dp_powerflow_create_pp_mview.sql', # create mviews to display power plants per scenario
# 'ego_dp_powerflow_hv_setup.sql', # Set schema/tables for EHV/HV powerflow calculations up
# 'ego_dp_powerflow_osmtgmod_to_pypsa.sql', # Include data from osmTGmod into EHV/HV powerflow schema
# 'ego_dp_powerflow_electrical_neighbour.sql', # Create border crossing lines and buses in neighbouring countries
# 'ego_dp_powerflow_fix_ehv_subnetworks.sql', # Fix topological errors in eHV grid
# 'ego_dp_powerflow_grid_future_scenarios.sql', # Copy grid to future scenarios
# 'ego_dp_powerflow_assignment_generator.sql', # Assign generators to corresponding substation (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_assignment_load.sql', # Assign loads to their corresponding substation (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_assignment_storage.sql', # Assign storages to their corresponding substation (SQ, NEP 2035, eGo 100)
# 'ego_dp_powerflow_timeseries_generator.sql', # Transfer renpassG!S results into the corresponding powerflow table
# 'ego_dp_powerflow_griddistrict_demand.py', # Demand per MV Griddistrict
# 'ego_dp_powerflow_timeseries_demand.sql', # Insert demand series into corresponding powerflow table (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_lopf_data.sql', # Set marginal costs for generators and storages


# 'ego_dp_powerflow_assignment_otgid.sql', # assign otg_id to pp lists
# 'ego_dp_powerflow_assignment_unid.sql', # create a unified_id over all pp (res and conv)
# 'ego_dp_powerflow_create_pp_mview.sql', # create mviews to display power plants per scenario
# 'ego_dp_powerflow_hv_setup.sql', # Set schema/tables for EHV/HV powerflow calculations up
# 'ego_dp_powerflow_osmtgmod_to_pypsa.sql', # Include data from osmTGmod into EHV/HV powerflow schema
# 'ego_dp_powerflow_electrical_neighbour.sql', # Create border crossing lines and buses in neighbouring countries
# 'ego_dp_powerflow_fix_ehv_subnetworks.sql', # Fix topological errors in eHV grid
# 'ego_dp_powerflow_grid_future_scenarios.sql', # Copy grid to future scenarios
# 'ego_dp_powerflow_assignment_generator.sql', # Assign generators to corresponding substation (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_create_generator_neighbours.py', # Create generators for neighbouring countries (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_assignment_load.sql', # Assign loads to their corresponding substation (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_create_load_neighbours.sql', # Create loads for neighouring countries (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_assignment_storage.sql', # Assign storages to their corresponding substation (SQ, NEP 2035, eGo 100)
# 'ego_dp_powerflow_timeseries_generator_de_p_set.py' # Assign p_sets for Germany based on renpassG!S optimization results (SQ, NEP 2035, eGo 100)
# 'ego_dp_powerflow_timeseries_generator_other_p_set.py' # Assign p_sets for neighbouring countries based on renpassG!S optimization results (SQ, NEP 2035, eGo 100)
# 'ego_dp_powerflow_timeseries_generator_de_p_max_pu.py' # Assign p_max_pu based on feedin timeseries data (Germany) (SQ, NEP 2035, eGo 100)
# 'ego_dp_powerflow_timeseries_generator_other_p_max_pu.py' # Assign p_max_pu based on feedin timeseries data (Neighbouring Countries) (SQ, NEP 2035, eGo 100)
# 'ego_dp_powerflow_timeseries_generator_offshore_p_max_pu.py' # Assign p_max_pu based on feedin timeseries data (Neighbouring countries Offshore) (SQ, NEP 2035, eGo 100)
# 'ego_dp_powerflow_griddistrict_demand.py', # Demand per MV Griddistrict
# 'ego_dp_powerflow_timeseries_demand.sql', # Insert demand series into corresponding powerflow table (SQ, NEP2035, eGo100)
# 'ego_dp_powerflow_lopf_data.sql', # Set marginal costs for generators and storages


## VERSIONING
# 'ego_dp_versioning.sql', # Versioning
# 'ego_dp_versioning_mviews.sql' , # Versioning of mviews

## POST-PROCESSING
# 'post_processing/ego_pp_nep2035_grid_variations.sql' # Create extension_tables and insert NEP-data


## VACUUM FULL
# 'ego_dp_vacuum_full.sql'
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
""" Transfer scenario definition as defined in FlEnS open_eGo scenarios
of LinearTransformers and Sources to eGo powerflow generator table.
"""

__copyright__ = "ZNES Flensburg"
__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)"
__url__ = "https://github.com/openego/data_processing/blob/master/LICENSE"
__author__ = "wolfbunke"

import pandas as pd

from dataprocessing.tools.io import oedb_session
from dataprocessing.python_scripts.functions.ego_scenario_log import write_ego_scenario_log
from sqlalchemy.orm import sessionmaker
from ego_dp_powerflow_timeseries_generator_helper import OBJ_LABEL_TO_SOURCE, SCENARIOMAP, \
TEMPID, NEIGHBOURSID, _flatten, map_on_partial_string, missing_orm_classes
from egoio.db_tables.model_draft import EgoGridPfHvGenerator as Generator, \
EgoGridHvElectricalNeighboursBus as Neighbour

conn = oedb_session(section='test')
Session = sessionmaker(bind=conn)
session = Session()

# obligatory delete statement based on NEIGHBOURSID
session.query(Generator).filter(Generator.generator_id >= NEIGHBOURSID).\
delete(synchronize_session='fetch')

###############################################################################

*_, Transformer, Source, Results = missing_orm_classes(session)

# get DataFrame each row representing one electrical neighbour by applying
# filter on id and v_nom, not affected by scenario name
query = session.query(Neighbour)
neighbours = pd.read_sql(query.statement, query.session.bind)

ix = (neighbours['id'] <= 27) & (neighbours['v_nom'] == 380)
neighbours = neighbours.loc[ix, :]
neighbours.set_index('cntr_id', inplace=True)

# for each scenario
logged = 0
for scn_name, scn_nr in SCENARIOMAP.items():

# get renpass_gis scenario data on linear transformers. Parameters are
# defined on those edges directed from the component to the bus.
filters = [Transformer.scenario_id == scn_nr,
~Transformer.source.like('%powerline%'),
Transformer.label == Transformer.source] # direction

query = session.query(Transformer).filter(*filters)
transformers = pd.read_sql(query.statement, query.session.bind)
transformers['type'] = 'linear transformer'

# get data on sources
filters = [Source.scenario_id == scn_nr, ~Source.label.like('GL%')]
query = session.query(Source).filter(*filters)
sources = pd.read_sql(query.statement, query.session.bind)
sources['type'] = 'source'

# sources and transformers, distinct in renpass_gis, are both seen as
# generators and can be handled together
generators = pd.concat([sources, transformers], ignore_index=True)

# parameters in renpass_gis are not necessarily scalars and stored in lists
# lists of len one are flattened
generators = generators.applymap(_flatten)

# 0 does not equal zero. In case a class with zero nominal value
# should be defined for the purpose of scenario definition very small
# values are used in the scenario files.
ix = generators['nominal_value'] < 1e-7
generators = generators.loc[~ix, :]

# source in the context of eGo has a different meaning. The column has to
# be renamed
generators.rename(columns={'source': 'renpass_gis_source'}, inplace=True)

# rename nominal_value to p_nom
generators.rename(columns={'nominal_value': 'p_nom'}, inplace=True)

# map from obj label string -> source
generators['source'] = map_on_partial_string(
generators['label'], {i: k for k, i in OBJ_LABEL_TO_SOURCE.items()})

generators['cntr_id'] = generators['label'].str[:2]

# exclude Germany
generators = generators.loc[generators['cntr_id'] != 'DE', :]

# exclude unmatched sources
generators = generators.loc[~generators['source'].isnull(), :]

# assign bus_ids according to neighbours DataFrame
generators['bus'] = generators['cntr_id'].map(neighbours['bus_id'])

# set control, and dispatch parameter
generators['control'] = 'PV'
generators['dispatch'] = generators['type'].map(
{'linear transformer': 'flexible', 'source': 'variable'})

# set scenario name, temporal id
generators['scn_name'] = scn_name
generators['temp_id'] = TEMPID
generators['generator_id'] = generators.index + NEIGHBOURSID

# prepare DataFrames to be exported
generator_ex = generators[
['scn_name', 'generator_id', 'bus', 'dispatch', 'control', 'source',
'p_nom']]

# write to db
for i in generator_ex.to_dict(orient='records'):
session.add(Generator(**i))

session.commit()

write_ego_scenario_log(conn=conn,
version='v0.4.0',
io='input',
schema='model_draft',
table=Generator.__tablename__,
script=__file__,
entries=logged)
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
""" This script assigns feedin timeseries data generated with feedinlib
as p_max_pu parameter to high-voltage powerflow generators within Germany.
"""

__copyright__ = "ZNES Flensburg"
__license__ = "GNU Affero General Public License Version 3 (AGPL-3.0)"
__url__ = "https://github.com/openego/data_processing/blob/master/LICENSE"
__author__ = "wolfbunke"

import pandas as pd

from dataprocessing.tools.io import oedb_session
from sqlalchemy.orm import sessionmaker
from sqlalchemy import case
from dataprocessing.python_scripts.functions.ego_scenario_log \
import write_ego_scenario_log

from egoio.db_tables.model_draft import EgoSupplyPfGeneratorSingle \
as GeneratorSingle, EgoGridPfHvGeneratorPqSet as PqSet
from ego_dp_powerflow_timeseries_generator_helper import OBJ_LABEL_TO_SOURCE, SCENARIOMAP, \
TEMPID, missing_orm_classes

# Get database connection
conn = oedb_session(section='test')
Session = sessionmaker(bind=conn)
session = Session()

_, PowerClass, Feedin, *_, Results = missing_orm_classes(session)

logged = 0
for scn_name, scn_nr in SCENARIOMAP.items():

# Select the correct sources
# Map source_id to feedin source name
sources = ['wind_onshore', 'wind_offshore', 'solar']
sources_dict = {
k: v for k, v in OBJ_LABEL_TO_SOURCE.items() if k in sources}

# Wrap case around feedin source to return source_id instead of name
casestr = case(sources_dict, value=Feedin.source, else_=None)

# Get a unique represenation of PfGeneratorSingle with regard to aggr_id,
# source, w_id, power_class
filters = (
GeneratorSingle.scn_name == scn_name, GeneratorSingle.aggr_id != None)
fields = [GeneratorSingle.aggr_id, GeneratorSingle.source,
GeneratorSingle.w_id, GeneratorSingle.power_class]
grouper = GeneratorSingle.aggr_id, GeneratorSingle.source,\
GeneratorSingle.w_id, GeneratorSingle.power_class

# Construct a subquery with filters, fields and grouper
t = session.query(*fields).group_by(*grouper).filter(*filters).subquery()

# Use subquery and Feedin table to get the correct feedin for each
# generator
query = session.query(t, Feedin.feedin.label('p_max_pu')).filter(
t.c.w_id == Feedin.w_id, t.c.power_class == Feedin.power_class,
t.c.source == casestr)

generators = pd.read_sql(query.statement, query.session.bind)

# Substation's aggr_id are the basis for generators in high-voltage
# powerflow
# Rename column aggr_id to generator_id
generators.rename(columns={'aggr_id': 'generator_id'}, inplace=True)

generators['temp_id'] = TEMPID
generators['scn_name'] = scn_name

# Select fields for PqSets
# Write PqSets to database
fields = ['generator_id', 'p_max_pu', 'scn_name', 'temp_id']
for i in generators[fields].to_dict(orient='records'):
session.add(PqSet(**i))

session.commit()

logged += len(generators)

write_ego_scenario_log(conn=conn,
version='v0.4.0',
io='input',
schema='model_draft',
table=PqSet.__tablename__,
script=__file__,
entries=logged)
Loading