def solve(self, with_duals=False, tee=True, logfile=None, solver=None): if solver is None: solver_name = cfg.get('general', 'solver') else: solver_name = solver logging.info("Optimising using {0}.".format(solver_name)) if with_duals: self.model.receive_duals() if self.debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'reegis.lp') logging.info('Store lp-file in {0}.'.format(filename)) self.model.write(filename, io_options={'symbolic_solver_labels': True}) self.model.solve(solver=solver_name, solve_kwargs={ 'tee': tee, 'logfile': logfile }) self.es.results['main'] = outputlib.processing.results(self.model) self.es.results['meta'] = outputlib.processing.meta_results(self.model) self.es.results['param'] = outputlib.processing.parameter_as_dict( self.es) self.es.results['scenario'] = self.scenario_info(solver_name) self.es.results['meta']['in_location'] = self.location self.es.results['meta']['file_date'] = datetime.datetime.fromtimestamp( os.path.getmtime(self.location)) self.es.results['meta']['oemof_version'] = logger.get_version() self.results = self.es.results['main']
def solve(self, with_duals=False, tee=True, logfile=None, solver=None): logging.info("Optimising using {0}.".format(solver)) if with_duals: self.model.receive_duals() if self.debug: filename = os.path.join(helpers.extend_basic_path("lp_files"), "reegis.lp") logging.info("Store lp-file in {0}.".format(filename)) self.model.write(filename, io_options={"symbolic_solver_labels": True}) self.model.solve(solver=solver, solve_kwargs={ "tee": tee, "logfile": logfile }) self.es.results["main"] = processing.results(self.model) self.es.results["meta"] = processing.meta_results(self.model) self.es.results["param"] = processing.parameter_as_dict(self.es) self.es.results["meta"]["scenario"] = self.scenario_info(solver) self.es.results["meta"]["in_location"] = self.location self.es.results["meta"]["file_date"] = datetime.datetime.fromtimestamp( os.path.getmtime(self.location)) self.es.results["meta"]["oemof_version"] = logger.get_version() self.results = self.es.results["main"]
def setup_class(self): self.objective_pattern = re.compile("^objective.*(?=s\.t\.)", re.DOTALL | re.MULTILINE) self.date_time_index = pd.date_range('1/1/2012', periods=3, freq='H') self.tmppath = helpers.extend_basic_path('tmp') logging.info(self.tmppath)
def setup_class(cls): cls.objective_pattern = re.compile(r'^objective.*(?=s\.t\.)', re.DOTALL | re.MULTILINE) cls.date_time_index = pd.date_range('1/1/2012', periods=3, freq='H') cls.tmpdir = helpers.extend_basic_path('tmp') logging.info(cls.tmpdir)
def setup_class(self): self.objective_pattern = re.compile("^objective.*(?=s\.t\.)", re.DOTALL|re.MULTILINE) self.date_time_index = pd.date_range('1/1/2012', periods=3, freq='H') self.tmppath = helpers.extend_basic_path('tmp') logging.info(self.tmppath)
def define_logging(inifile='logging.ini', basicpath=None, subdir='log_files'): r"""Initialise the logger using the logging.conf file in the local path. Several sentences providing an extended description. Refer to variables using back-ticks, e.g. `var`. Parameters ---------- inifile : string, optional (default: logging.ini) Name of the configuration file to define the logger. If no ini-file exist a default ini-file will be downloaded from 'http://vernetzen.uni-flensburg.de/~git/logging_default.ini' and used. basicpath : string, optional (default: '.oemof' in HOME) The basicpath for different oemof related informations. By default a ".oemof' folder is created in your home directory. subdir : string, optional (default: 'log_files') The name of the subfolder of the basicpath where the log-files are stored. Notes ----- By default the INFO level is printed on the screen and the debug level in a file, but you can easily configure the ini-file. Every module that wants to create logging messages has to import the logging module. The oemof logger module has to be imported once to initialise it. Examples -------- To define the default logge you have to import the python logging library and this function. The first logging message should be the path where the log file is saved to. >>> import logging >>> from oemof.tools import logger >>> logger.define_logging() # doctest: +SKIP 17:56:51-INFO-Path for logging: /HOME/.oemof/log_files ... >>> logging.debug("Hallo") """ url = 'http://vernetzen.uni-flensburg.de/~git/logging_default.ini' if basicpath is None: basicpath = helpers.get_basic_path() logpath = helpers.extend_basic_path(subdir) log_filename = os.path.join(basicpath, 'logging.ini') if not os.path.isfile(log_filename): helpers.download_file(log_filename, url) logging.config.fileConfig(os.path.join(basicpath, 'logging.ini')) logger = logging.getLogger('simpleExample') logger.debug('*********************************************************') logging.info('Path for logging: %s' % logpath) try: check_git_branch() except: check_version()
def setUpClass(self): self.objective_pattern = re.compile("^objective.*(?=s\.t\.)", re.DOTALL|re.MULTILINE) self.time_index = pd.date_range('1/1/2012', periods=3, freq='H') self.sim = es.Simulation( timesteps=range(len(self.time_index)), solver='glpk', objective_options={ 'function': predefined_objectives.minimize_cost}) self.tmppath = helpers.extend_basic_path('tmp') logging.info(self.tmppath)
########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') # initialise the operational model model = solph.Model(energysystem) # This is for debugging only. It is not(!) necessary to solve the problem and # should be set to True to save time and disc space in normal use. For # debugging the timesteps should be set to 3, to increase the readability of # the lp-file. if debug: filename = os.path.join( helpers.extend_basic_path('lp_files'), r'C:\Users\Winfried\Oemof\results\lp\TI8784O.lp') logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') # The processing module of the outputlib can be used to extract the results # from the model transfer them into a homogeneous structured dictionary. # add results to the energy system to make it possible to store them. energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model)
inputs={bel: solph.Flow(nominal_value=10)}, outputs={bel: solph.Flow(nominal_value=10, variable_costs=0.001)}, capacity_loss=0.00, initial_capacity=None, inflow_conversion_factor=1, outflow_conversion_factor=1,) energysystem.add(storage) logging.info('Optimise the energy system') model = solph.Model(energysystem) # nur für debug. kann ignoriert werden if debug: filename = os.path.join( helpers.extend_basic_path('lp_files'), 'basic_example.lp') logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') # add results to the energy system to make it possible to store them. energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model)
def optimise_storage_size(energysystem, filename="variable_chp.csv", solver='cbc', debug=True, tee_switch=True): # Read data file with heat and electrical demand (192 hours) full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") ########################################################################## # Create oemof.solph objects ########################################################################## logging.info('Create oemof.solph objects') # create natural gas bus bgas = solph.Bus(label="natural_gas") # create commodity object for gas resource solph.Source(label='rgas', outputs={bgas: solph.Flow(variable_costs=50)}) # create two electricity buses and two heat buses bel = solph.Bus(label="electricity") bel2 = solph.Bus(label="electricity_2") bth = solph.Bus(label="heat") bth2 = solph.Bus(label="heat_2") # create excess components for the elec/heat bus to allow overproduction solph.Sink(label='excess_bth_2', inputs={bth2: solph.Flow()}) solph.Sink(label='excess_therm', inputs={bth: solph.Flow()}) solph.Sink(label='excess_bel_2', inputs={bel2: solph.Flow()}) solph.Sink(label='excess_elec', inputs={bel: solph.Flow()}) # create simple sink object for electrical demand for each electrical bus solph.Sink(label='demand_elec', inputs={bel: solph.Flow( actual_value=data['demand_el'], fixed=True, nominal_value=1)}) solph.Sink(label='demand_el_2', inputs={bel2: solph.Flow( actual_value=data['demand_el'], fixed=True, nominal_value=1)}) # create simple sink object for heat demand for each thermal bus solph.Sink(label='demand_therm', inputs={bth: solph.Flow( actual_value=data['demand_th'], fixed=True, nominal_value=741000)}) solph.Sink(label='demand_th_2', inputs={bth2: solph.Flow( actual_value=data['demand_th'], fixed=True, nominal_value=741000)}) # This is just a dummy transformer with a nominal input of zero solph.LinearTransformer( label='fixed_chp_gas', inputs={bgas: solph.Flow(nominal_value=0)}, outputs={bel: solph.Flow(), bth: solph.Flow()}, conversion_factors={bel: 0.3, bth: 0.5}) # create a fixed transformer to distribute to the heat_2 and elec_2 buses solph.LinearTransformer( label='fixed_chp_gas_2', inputs={bgas: solph.Flow(nominal_value=10e10)}, outputs={bel2: solph.Flow(), bth2: solph.Flow()}, conversion_factors={bel2: 0.3, bth2: 0.5}) # create a fixed transformer to distribute to the heat and elec buses solph.VariableFractionTransformer( label='variable_chp_gas', inputs={bgas: solph.Flow(nominal_value=10e10)}, outputs={bel: solph.Flow(), bth: solph.Flow()}, conversion_factors={bel: 0.3, bth: 0.5}, conversion_factor_single_flow={bel: 0.5} ) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') om = solph.OperationalModel(energysystem) if debug: filename = os.path.join( helpers.extend_basic_path('lp_files'), 'variable_chp.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver=solver, solve_kwargs={'tee': tee_switch}) return energysystem
initial_storage_level=param_value['init_capacity_storage_el'], inflow_conversion_factor=param_value[ 'inflow_conv_factor_storage_el'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_el'])) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') model = solph.Model(energysystem) if cfg['debug']: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'model.lp') logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') model.solve(solver=cfg['solver'], solve_kwargs={'tee': cfg['solver_verbose']}) logging.info('Store the energy system with the results.') energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) energysystem.dump(dpath=abs_path + "/results/optimisation_results/dumps", filename="model.oemof")
def test_helpers(): ok_(os.path.isdir(os.path.join(os.path.expanduser('~'), '.oemof'))) new_dir = helpers.extend_basic_path('test_xf67456_dir') ok_(os.path.isdir(new_dir)) os.rmdir(new_dir) ok_(not os.path.isdir(new_dir))
def run_model_flexchp(config_path, scenario_nr): with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile) if cfg['debug']: number_of_time_steps = 3 else: number_of_time_steps = 8760 solver = cfg['solver'] debug = cfg['debug'] periods = number_of_time_steps solver_verbose = cfg['solver_verbose'] abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) logger.define_logging(logpath=abs_path + '/results/optimisation_results/log/', logfile=cfg['filename_logfile'] + '_scenario_{0}.log'.format(scenario_nr), screen_level=logging.INFO, file_level=logging.DEBUG) logging.info('Use parameters for scenario {0}'.format(scenario_nr)) logging.info('Initialize the energy system') date_time_index = pd.date_range(cfg['start_date'], periods=number_of_time_steps, freq=cfg['frequency']) energysystem = solph.EnergySystem(timeindex=date_time_index) ########################################################################## # Read time series and parameter values from data files ########################################################################## file_path_demand_ts = abs_path + cfg['demand_time_series'] data = pd.read_csv(file_path_demand_ts) file_path_param_01 = abs_path + cfg['parameters_energy_system'][scenario_nr - 1] file_path_param_02 = abs_path + cfg['parameters_all_energy_systems'] param_df_01 = pd.read_csv(file_path_param_01, index_col=1) param_df_02 = pd.read_csv(file_path_param_02, index_col=1) param_df = pd.concat([param_df_01, param_df_02], sort=True) param_value = param_df['value'] ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') bgas = solph.Bus(label="natural_gas") bel = solph.Bus(label="electricity") bth = solph.Bus(label='heat') energysystem.add(bgas, bel, bth) # Sources and sinks energysystem.add( solph.Sink( label='excess_bel', inputs={ bel: solph.Flow(variable_costs=param_value['var_costs_excess_bel']) })) energysystem.add( solph.Sink( label='excess_bth', inputs={ bth: solph.Flow(variable_costs=param_value['var_costs_excess_bth']) })) energysystem.add( solph.Source( label='shortage_bel', outputs={ bel: solph.Flow( variable_costs=param_value['var_costs_shortage_bel']) })) energysystem.add( solph.Source( label='shortage_bth', outputs={ bth: solph.Flow( variable_costs=param_value['var_costs_shortage_bth']) })) energysystem.add( solph.Source(label='rgas', outputs={ bgas: solph.Flow( nominal_value=param_value['nom_val_gas'], summed_max=param_value['sum_max_gas'], variable_costs=param_value['var_costs_gas']) })) energysystem.add( solph.Source( label='P2H', outputs={ bth: solph.Flow(actual_value=data['neg_residual_el'], nominal_value=param_value['nom_val_neg_residual'] * param_value['conversion_factor_p2h'], fixed=True) })) energysystem.add( solph.Sink(label='demand_el', inputs={ bel: solph.Flow( actual_value=data['demand_el'], nominal_value=param_value['nom_val_demand_el'], fixed=True) })) energysystem.add( solph.Sink(label='demand_th', inputs={ bth: solph.Flow( actual_value=data['demand_th'], nominal_value=param_value['nom_val_demand_th'], fixed=True) })) energysystem.add( solph.components.GenericCHP( label='CHP_01', fuel_input={ bgas: solph.Flow(H_L_FG_share_max=[ param_value['H_L_FG_share_max'] for p in range(0, periods) ]) }, electrical_output={ bel: solph.Flow(P_max_woDH=[ param_value['P_max_woDH'] for p in range(0, periods) ], P_min_woDH=[ param_value['P_min_woDH'] for p in range(0, periods) ], Eta_el_max_woDH=[ param_value['Eta_el_max_woDH'] for p in range(0, periods) ], Eta_el_min_woDH=[ param_value['Eta_el_min_woDH'] for p in range(0, periods) ]) }, heat_output={ bth: solph.Flow(Q_CW_min=[ param_value['Q_CW_min_chp'] for p in range(0, periods) ]) }, Beta=[param_value['Beta_chp'] for p in range(0, periods)], back_pressure=False)) energysystem.add( solph.Transformer( label='boiler', inputs={bgas: solph.Flow()}, outputs={ bth: solph.Flow(nominal_value=param_value['nom_val_out_boiler'], variable_costs=param_value['var_costs_boiler']) }, conversion_factors={bth: param_value['conversion_factor_boiler']})) if param_value['nom_capacity_storage_th'] > 0: storage_th = solph.components.GenericStorage( nominal_capacity=param_value['nom_capacity_storage_th'], label='storage_th', inputs={ bth: solph.Flow( nominal_value=param_value['nom_val_input_bth_storage_th'], variable_costs=param_value[ 'var_costs_input_bth_storage_th']) }, outputs={ bth: solph.Flow( nominal_value=param_value['nom_val_output_bth_storage_th'], variable_costs=param_value[ 'var_costs_output_bth_storage_th']) }, capacity_loss=param_value['capacity_loss_storage_th'], initial_capacity=param_value['init_capacity_storage_th'], inflow_conversion_factor=param_value[ 'inflow_conv_factor_storage_th'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_th']) energysystem.add(storage_th) if param_value['nom_capacity_storage_el'] > 0: storage_el = solph.components.GenericStorage( nominal_capacity=param_value['nom_capacity_storage_el'], label='storage_el', inputs={ bel: solph.Flow( nominal_value=param_value['nom_val_input_bel_storage_el'], variable_costs=param_value[ 'var_costs_input_bel_storage_el']) }, outputs={ bel: solph.Flow( nominal_value=param_value['nom_val_output_bel_storage_el'], variable_costs=param_value[ 'var_costs_output_bel_storage_el']) }, capacity_loss=param_value['capacity_loss_storage_el'], initial_capacity=param_value['init_capacity_storage_el'], inflow_conversion_factor=param_value[ 'inflow_conv_factor_storage_el'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_el']) energysystem.add(storage_el) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') model = solph.Model(energysystem) if debug: lpfile_name = 'flexCHP_scenario_{0}.lp'.format(scenario_nr) filename = os.path.join(helpers.extend_basic_path('lp_files'), lpfile_name) logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) energysystem.dump(dpath=abs_path + "/results/optimisation_results/dumps", filename=cfg['filename_dumb'] + '_scenario_{0}.oemof'.format(scenario_nr))
def define_logging(inifile='logging.ini', basicpath=None, subdir='log_files', log_version=True): r"""Initialise the logger using the logging.conf file in the local path. Several sentences providing an extended description. Refer to variables using back-ticks, e.g. `var`. Parameters ---------- inifile : string, optional (default: logging.ini) Name of the configuration file to define the logger. If no ini-file exist a default ini-file will be copied from 'default_files' and used. basicpath : string, optional (default: '.oemof' in HOME) The basicpath for different oemof related information. By default a ".oemof' folder is created in your home directory. subdir : string, optional (default: 'log_files') The name of the subfolder of the basicpath where the log-files are stored. log_version : boolean If True the actual version or commit is logged while initialising the logger. Notes ----- By default the INFO level is printed on the screen and the debug level in a file, but you can easily configure the ini-file. Every module that wants to create logging messages has to import the logging module. The oemof logger module has to be imported once to initialise it. Examples -------- To define the default logger you have to import the python logging library and this function. The first logging message should be the path where the log file is saved to. >>> import logging >>> from oemof.tools import logger >>> logger.define_logging() # doctest: +SKIP 17:56:51-INFO-Path for logging: /HOME/.oemof/log_files ... >>> logging.debug("Hallo") """ if basicpath is None: basicpath = helpers.get_basic_path() logpath = helpers.extend_basic_path(subdir) log_filename = os.path.join(basicpath, inifile) default_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'default_files', 'logging_default.ini') if not os.path.isfile(log_filename): shutil.copyfile(default_file, log_filename) logging.config.fileConfig(os.path.join(basicpath, inifile)) logger = logging.getLogger('simpleExample') logger.debug('*********************************************************') logging.info('Path for logging: %s' % logpath) if log_version: try: check_git_branch() except FileNotFoundError: check_version()
def main(): # **************************************************************************** # ********** PART 1 - Define and optimise the energy system ****************** # **************************************************************************** ############################################################################### # imports ############################################################################### # Default logger of oemof from oemof.tools import logger from oemof.tools import helpers import oemof.solph as solph import oemof.outputlib as outputlib import logging import os import pandas as pd import pprint as pp try: import matplotlib.pyplot as plt except ImportError: plt = None solver = 'cbc' # 'glpk', 'gurobi',.... debug = False # Set number_of_timesteps to 3 to get a readable lp-file. number_of_time_steps = 24 * 7 * 8 solver_verbose = False # show/hide solver output # initiate the logger (see the API docs for more information) logger.define_logging(logfile='oemof_example.log', screen_level=logging.INFO, file_level=logging.DEBUG) logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2012', periods=number_of_time_steps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # Read data file filename = os.path.join(os.path.dirname(__file__), 'basic_example.csv') data = pd.read_csv(filename) ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') # The bus objects were assigned to variables which makes it easier to connect # components to these buses (see below). # create natural gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") # adding the buses to the energy system energysystem.add(bgas, bel) # create excess component for the electricity bus to allow overproduction energysystem.add(solph.Sink(label='excess_bel', inputs={bel: solph.Flow()})) # create source object representing the natural gas commodity (annual limit) energysystem.add( solph.Source( label='rgas', outputs={bgas: solph.Flow(nominal_value=29825293, summed_max=1)})) # create fixed source object representing wind power plants energysystem.add( solph.Source(label='wind', outputs={ bel: solph.Flow(actual_value=data['wind'], nominal_value=1000000, fixed=True) })) # create fixed source object representing pv power plants energysystem.add( solph.Source(label='pv', outputs={ bel: solph.Flow(actual_value=data['pv'], nominal_value=582000, fixed=True) })) # create simple sink object representing the electrical demand energysystem.add( solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) })) # create simple transformer object representing a gas power plant energysystem.add( solph.Transformer( label="pp_gas", inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58})) # create storage object representing a battery storage = solph.components.GenericStorage( nominal_capacity=10077997, label='storage', inputs={bel: solph.Flow()}, outputs={bel: solph.Flow(variable_costs=0.001)}, capacity_loss=0.00, initial_capacity=None, nominal_input_capacity_ratio=1 / 6, nominal_output_capacity_ratio=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, ) energysystem.add(storage) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') # initialise the operational model model = solph.Model(energysystem) # This is for debugging only. It is not(!) necessary to solve the problem and # should be set to False to save time and disc space in normal use. For # debugging the timesteps should be set to 3, to increase the readability of # the lp-file. if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') # The processing module of the outputlib can be used to extract the results # from the model transfer them into a homogeneous structured dictionary. # add results to the energy system to make it possible to store them. energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) # The default path is the '.oemof' folder in your $HOME directory. # The default filename is 'es_dump.oemof'. # You can omit the attributes (as None is the default value) for testing cases. # You should use unique names/folders for valuable results to avoid # overwriting. # store energy system with results energysystem.dump(dpath=None, filename=None) # **************************************************************************** # ********** PART 2 - Processing the results ********************************* # **************************************************************************** logging.info('**** The script can be divided into two parts here.') logging.info('Restore the energy system and the results.') energysystem = solph.EnergySystem() energysystem.restore(dpath=None, filename=None) # define an alias for shorter calls below (optional) results = energysystem.results['main'] storage = energysystem.groups['storage'] # print a time slice of the state of charge print('') print('********* State of Charge (slice) *********') print(results[( storage, None)]['sequences']['2012-02-25 08:00:00':'2012-02-26 15:00:00']) print('') # get all variables of a specific component/bus custom_storage = outputlib.views.node(results, 'storage') electricity_bus = outputlib.views.node(results, 'electricity') # plot the time series (sequences) of a specific component/bus if plt is not None: custom_storage['sequences'].plot(kind='line', drawstyle='steps-post') plt.show() electricity_bus['sequences'].plot(kind='line', drawstyle='steps-post') plt.show() # print the solver results print('********* Meta results *********') pp.pprint(energysystem.results['meta']) print('') # print the sums of the flows around the electricity bus print('********* Main results *********') print(electricity_bus['sequences'].sum(axis=0))
def optimise_storage_size(energysystem, filename="variable_chp.csv", solver='cbc', debug=True, tee_switch=True): # Read data file with heat and electrical demand (192 hours) full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") ########################################################################## # Create oemof.solph objects ########################################################################## logging.info('Create oemof.solph objects') # create natural gas bus bgas = solph.Bus(label="natural_gas") # create commodity object for gas resource solph.Source(label='rgas', outputs={bgas: solph.Flow(variable_costs=50)}) # create two electricity buses and two heat buses bel = solph.Bus(label="electricity") bel2 = solph.Bus(label="electricity_2") bth = solph.Bus(label="heat") bth2 = solph.Bus(label="heat_2") # create excess components for the elec/heat bus to allow overproduction solph.Sink(label='excess_bth_2', inputs={bth2: solph.Flow()}) solph.Sink(label='excess_therm', inputs={bth: solph.Flow()}) solph.Sink(label='excess_bel_2', inputs={bel2: solph.Flow()}) solph.Sink(label='excess_elec', inputs={bel: solph.Flow()}) # create simple sink object for electrical demand for each electrical bus solph.Sink(label='demand_elec', inputs={ bel: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) solph.Sink(label='demand_el_2', inputs={ bel2: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) # create simple sink object for heat demand for each thermal bus solph.Sink(label='demand_therm', inputs={ bth: solph.Flow(actual_value=data['demand_th'], fixed=True, nominal_value=741000) }) solph.Sink(label='demand_th_2', inputs={ bth2: solph.Flow(actual_value=data['demand_th'], fixed=True, nominal_value=741000) }) # This is just a dummy transformer with a nominal input of zero solph.LinearTransformer(label='fixed_chp_gas', inputs={bgas: solph.Flow(nominal_value=0)}, outputs={ bel: solph.Flow(), bth: solph.Flow() }, conversion_factors={ bel: 0.3, bth: 0.5 }) # create a fixed transformer to distribute to the heat_2 and elec_2 buses solph.LinearTransformer(label='fixed_chp_gas_2', inputs={bgas: solph.Flow(nominal_value=10e10)}, outputs={ bel2: solph.Flow(), bth2: solph.Flow() }, conversion_factors={ bel2: 0.3, bth2: 0.5 }) # create a fixed transformer to distribute to the heat and elec buses solph.VariableFractionTransformer( label='variable_chp_gas', inputs={bgas: solph.Flow(nominal_value=10e10)}, outputs={ bel: solph.Flow(), bth: solph.Flow() }, conversion_factors={ bel: 0.3, bth: 0.5 }, conversion_factor_single_flow={bel: 0.5}) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') om = solph.OperationalModel(energysystem) if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'variable_chp.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver=solver, solve_kwargs={'tee': tee_switch}) return energysystem
def define_logging(inifile='logging.ini', basicpath=None, subdir='log_files', log_version=True): r"""Initialise the logger using the logging.conf file in the local path. Several sentences providing an extended description. Refer to variables using back-ticks, e.g. `var`. Parameters ---------- inifile : string, optional (default: logging.ini) Name of the configuration file to define the logger. If no ini-file exist a default ini-file will be copied from 'default_files' and used. basicpath : string, optional (default: '.oemof' in HOME) The basicpath for different oemof related information. By default a ".oemof' folder is created in your home directory. subdir : string, optional (default: 'log_files') The name of the subfolder of the basicpath where the log-files are stored. log_version : boolean If True the actual version or commit is logged while initialising the logger. Returns ------- str : Place where the log file is stored. Notes ----- By default the INFO level is printed on the screen and the debug level in a file, but you can easily configure the ini-file. Every module that wants to create logging messages has to import the logging module. The oemof logger module has to be imported once to initialise it. Examples -------- To define the default logger you have to import the python logging library and this function. The first logging message should be the path where the log file is saved to. >>> import logging >>> from oemof.tools import logger >>> logger.define_logging() # doctest: +SKIP 17:56:51-INFO-Path for logging: /HOME/.oemof/log_files ... >>> logging.debug("Hallo") """ if basicpath is None: basicpath = helpers.get_basic_path() logpath = helpers.extend_basic_path(subdir) log_filename = os.path.join(basicpath, inifile) default_file = os.path.join(os.path.dirname( os.path.realpath(__file__)), 'default_files', 'logging_default.ini') if not os.path.isfile(log_filename): shutil.copyfile(default_file, log_filename) logging.config.fileConfig(os.path.join(basicpath, inifile)) try: returnpath = logging.getLoggerClass().root.handlers[1].baseFilename except AttributeError: returnpath = None logger = logging.getLogger('simpleExample') logger.debug('*********************************************************') logging.info('Path for logging: %s' % logpath) if log_version: try: check_git_branch() except FileNotFoundError: check_version() return returnpath
def run_model(config_path, team_number): with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile, Loader=yaml.CLoader) if cfg['debug']: number_of_time_steps = 3 else: number_of_time_steps = 8760 solver = cfg['solver'] debug = cfg['debug'] periods = number_of_time_steps solver_verbose = cfg['solver_verbose'] # show/hide solver output # initiate the logger (see the API docs for more information) logger.define_logging(logfile='model_team_{0}.log'.format(team_number + 1), screen_level=logging.INFO, file_level=logging.DEBUG) logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2030', periods=number_of_time_steps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) ########################################################################## # Read time series and parameter values from data files ########################################################################## abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) file_path_ts = abs_path + '/data/' + cfg['time_series_file_name'] data = pd.read_csv(file_path_ts) # file_path_weather_ts = abs_path + '/data_preprocessed/' + cfg[ # 'weather_time_series'] # weather_data = pd.read_csv(file_path_weather_ts) file_name_param_01 = cfg['design_parameters_file_name'][team_number] file_name_param_02 = cfg['parameters_file_name'] file_path_param_01 = (abs_path + '/data/' + file_name_param_01) file_path_param_02 = (abs_path + '/data/' + file_name_param_02) param_df_01 = pd.read_csv(file_path_param_01, index_col=1) param_df_02 = pd.read_csv(file_path_param_02, index_col=1) param_df = pd.concat([param_df_01, param_df_02], sort=True) param_value = param_df['value'] ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') bgas = solph.Bus(label="natural_gas") bel = solph.Bus(label="electricity") bth = solph.Bus(label='heat') energysystem.add(bgas, bel, bth) # Sources and sinks energysystem.add( solph.Sink( label='excess_bel', inputs={ bel: solph.Flow(variable_costs=param_value['var_costs_excess_bel']) })) energysystem.add( solph.Sink( label='excess_bth', inputs={ bth: solph.Flow(variable_costs=param_value['var_costs_excess_bth']) })) energysystem.add( solph.Source( label='shortage_bel', outputs={ bel: solph.Flow( variable_costs=param_value['var_costs_shortage_bel']) })) energysystem.add( solph.Source( label='shortage_bth', outputs={ bth: solph.Flow( variable_costs=param_value['var_costs_shortage_bth']) })) energysystem.add( solph.Source(label='rgas', outputs={ bgas: solph.Flow( nominal_value=param_value['nom_val_gas'], summed_max=param_value['sum_max_gas'], variable_costs=param_value['var_costs_gas']) })) if param_value['number_of_windturbines'] > 0: energysystem.add( solph.Source( label='wind_turbine', outputs={ bel: solph.Flow( actual_value=(data['Wind_power [kW/unit]'] * param_value['number_of_windturbines'] * 0.001), # [MWh] nominal_value=1, fixed=True) })) energysystem.add( solph.Sink( label='demand_el', inputs={ bel: solph.Flow( actual_value=data['Demand_el [MWh]'], # [MWh] nominal_value=1, fixed=True) })) energysystem.add( solph.Sink( label='demand_th', inputs={ bth: solph.Flow( actual_value=data['Demand_th [MWh]'], # [MWh] nominal_value=1, fixed=True) })) # Open-field photovoltaic power plant if param_value['number_of_PV_pp'] > 0: energysystem.add( solph.Source( label='PV_pp', outputs={ bel: solph.Flow( actual_value=(data['Sol_irradiation [Wh/sqm]'] * 0.000001 * param_value['eta_PV']), # [MWh/m²] nominal_value=param_value['PV_pp_surface_area'] * 10000, # [m²] fixed=True) })) # Rooftop photovoltaic if param_value['area_PV'] > 0: energysystem.add( solph.Source( label='PV', outputs={ bel: solph.Flow( actual_value=(data['Sol_irradiation [Wh/sqm]'] * 0.000001 * param_value['eta_PV']), # [MWh/m²] nominal_value=param_value['area_PV'] * 10000, # [m²] fixed=True) })) # Rooftop solar thermal if param_value['area_solar_th'] > 0: energysystem.add( solph.Source( label='solar_thermal', outputs={ bth: solph.Flow( actual_value=(data['Sol_irradiation [Wh/sqm]'] * 0.000001 * param_value['eta_solar_th']), # [MWh/m²] nominal_value=param_value['area_solar_th'] * 10000, # [m²] fixed=True) })) if param_value['number_of_chps'] > 0: energysystem.add( solph.Transformer( label='chp', inputs={bgas: solph.Flow()}, outputs={ bth: solph.Flow(nominal_value=param_value['number_of_chps'] * 0.5), # [MW] bel: solph.Flow() }, conversion_factors={ bth: param_value['conversion_factor_bth_chp'], bel: param_value['conversion_factor_bel_chp'] })) if param_value['number_of_heat_pumps'] > 0: energysystem.add( solph.Transformer( label='heat_pump', inputs={bel: solph.Flow()}, outputs={ bth: solph.Flow( nominal_value=(param_value['number_of_heat_pumps'] * param_value['COP_heat_pump'])) }, # [MW] conversion_factors={bth: param_value['COP_heat_pump']})) if param_value['number_of_boilers'] > 0: energysystem.add( solph.Transformer( label='boiler', inputs={bgas: solph.Flow()}, outputs={ bth: solph.Flow(nominal_value=param_value['number_of_boilers'] * 3) }, # [MW] conversion_factors={ bth: param_value['conversion_factor_boiler'] })) if param_value['capacity_thermal_storage'] > 0: storage_th = solph.components.GenericStorage( nominal_storage_capacity=(param_value['capacity_thermal_storage'] * param_value['daily_demand_th']), label='storage_th', inputs={ bth: solph.Flow( nominal_value=(param_value['capacity_thermal_storage'] * param_value['daily_demand_th'] / param_value['charge_time_storage_th'])) }, outputs={ bth: solph.Flow( nominal_value=(param_value['capacity_thermal_storage'] * param_value['daily_demand_th'] / param_value['charge_time_storage_th'])) }, loss_rate=param_value['capacity_loss_storage_th'], initial_storage_level=param_value['init_capacity_storage_th'], inflow_conversion_factor=param_value[ 'inflow_conv_factor_storage_th'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_th']) energysystem.add(storage_th) if param_value['capacity_electr_storage'] > 0: storage_el = solph.components.GenericStorage( nominal_storage_capacity=(param_value['capacity_electr_storage'] * param_value['daily_demand_el']), label='storage_el', inputs={ bel: solph.Flow( nominal_value=(param_value['capacity_electr_storage'] * param_value['daily_demand_el'] / param_value['charge_time_storage_el'])) }, outputs={ bel: solph.Flow( nominal_value=(param_value['capacity_electr_storage'] * param_value['daily_demand_el'] / param_value['charge_time_storage_el'])) }, loss_rate=param_value['capacity_loss_storage_el'], initial_storage_level=param_value['init_capacity_storage_el'], inflow_conversion_factor=param_value[ 'inflow_conv_factor_storage_el'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_el']) energysystem.add(storage_el) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') model = solph.Model(energysystem) if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'model_team_{0}.lp'.format(team_number + 1)) logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info( 'Solve the optimization problem of team {0}'.format(team_number + 1)) model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) energysystem.dump(dpath=abs_path + "/results/optimisation_results/dumps", filename="model_team_{0}.oemof".format(team_number + 1))
def optimise_storage_size(filename="storage_investment.csv", solver='cbc', debug=True, number_timesteps=8760, tee_switch=True): logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2012', periods=number_timesteps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # Read data file full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') # create natural gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") # create excess component for the electricity bus to allow overproduction solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) # create source object representing the natural gas commodity (annual limit) solph.Source(label='rgas', outputs={bgas: solph.Flow( nominal_value=194397000 * number_timesteps / 8760, summed_max=1)}) # create fixed source object representing wind power plants solph.Source(label='wind', outputs={bel: solph.Flow( actual_value=data['wind'], nominal_value=1000000, fixed=True, fixed_costs=20)}) # create fixed source object representing pv power plants solph.Source(label='pv', outputs={bel: solph.Flow( actual_value=data['pv'], nominal_value=582000, fixed=True, fixed_costs=15)}) # create simple sink object representing the electrical demand solph.Sink(label='demand', inputs={bel: solph.Flow( actual_value=data['demand_el'], fixed=True, nominal_value=1)}) # create simple transformer object representing a gas power plant solph.LinearTransformer( label="pp_gas", inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58}) # If the period is one year the equivalent periodical costs (epc) of an # investment are equal to the annuity. Use oemof's economic tools. epc = economics.annuity(capex=1000, n=20, wacc=0.05) # create storage object representing a battery solph.Storage( label='storage', inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, capacity_loss=0.00, initial_capacity=0, nominal_input_capacity_ratio=1/6, nominal_output_capacity_ratio=1/6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, fixed_costs=35, investment=solph.Investment(ep_costs=epc), ) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') # initialise the operational model om = solph.OperationalModel(energysystem) # if debug is true an lp-file will be written if debug: filename = os.path.join( helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') om.solve(solver=solver, solve_kwargs={'tee': tee_switch}) return energysystem
def run_model_flexchp(config_path, variation_nr): with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile) if cfg['debug']: number_of_time_steps = 3 else: number_of_time_steps = 8760 solver = cfg['solver'] debug = cfg['debug'] solver_verbose = cfg['solver_verbose'] # show/hide solver output abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) # initiate the logger (see the API docs for more information) logger.define_logging(logpath=(abs_path + '/results/optimisation_results/log/'), logfile=(cfg['filename_logfile']+'_scenario_{0}.log'. format(variation_nr)), screen_level=logging.INFO, file_level=logging.DEBUG) logging.info('Use parameters for scenario {0}'.format(variation_nr)) logging.info('Initialize the energy system') date_time_index = pd.date_range(cfg['start_date'], periods=number_of_time_steps, freq=cfg['frequency']) energysystem = solph.EnergySystem(timeindex=date_time_index) ########################################################################## # Read time series and parameter values from data files ########################################################################## file_path_demand_ts = abs_path + cfg['demand_time_series'] data = pd.read_csv(file_path_demand_ts) file_path_param_01 = abs_path + cfg['parameters_energy_system'] file_path_param_02 = abs_path + cfg['parameter_variation'][variation_nr] param_df_01 = pd.read_csv(file_path_param_01, index_col=1) param_df_02 = pd.read_csv(file_path_param_02, index_col=1) param_df = pd.concat([param_df_01, param_df_02], sort=True) param_value = param_df['value'] ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') bgas = solph.Bus(label="natural_gas") bel = solph.Bus(label="electricity") bel_residual = solph.Bus(label="residual") bth = solph.Bus(label='heat') energysystem.add(bgas, bel, bel_residual, bth) # Sources and sinks energysystem.add(solph.Sink( label='excess_bel', inputs={bel: solph.Flow( variable_costs=param_value['var_costs_excess_bel'])})) energysystem.add(solph.Sink( label='excess_bth', inputs={bth: solph.Flow( variable_costs=param_value['var_costs_excess_bth'])})) energysystem.add(solph.Source( label='shortage_bel', outputs={bel: solph.Flow( variable_costs=param_value['var_costs_shortage_bel'])})) energysystem.add(solph.Source( label='shortage_bth', outputs={bth: solph.Flow( variable_costs=param_value['var_costs_shortage_bth'])})) energysystem.add(solph.Source( label='rgas', outputs={bgas: solph.Flow( nominal_value=param_value['nom_val_gas'], summed_max=param_value['sum_max_gas'], variable_costs=(param_value['var_costs_gas'] * param_value['gas_price_variation']))})) energysystem.add(solph.Source( label='residual_el', outputs={bel_residual: solph.Flow( actual_value=data['neg_residual_el'], nominal_value=param_value['nom_val_neg_residual'], fixed=True)})) if cfg['price_el_quadratic'] == True: energysystem.add(solph.Sink( label='demand_el', inputs={bel: solph.Flow( variable_costs=(param_value['el_price'] * param_value['price_factor_sqr'] * param_value['el_price_variation'] * data['demand_el']**2), nominal_value=8000)})) if cfg['price_el_quadratic'] == False: energysystem.add(solph.Sink( label='demand_el', inputs={bel: solph.Flow( variable_costs=(param_value['el_price'] * param_value['el_price_variation'] * data['demand_el']), nominal_value=8000)})) energysystem.add(solph.Sink( label='demand_th', inputs={bth: solph.Flow( actual_value=data['demand_th'], nominal_value=param_value['nom_val_demand_th'], fixed=True, variable_costs=(- param_value['var_costs_gas'] / param_value['conversion_factor_boiler']))})) # Auxiliary component to prevent CHP electricity being used in P2H (not # representing a physical component!) energysystem.add(solph.Transformer( label='oneway', inputs={bel_residual: solph.Flow( nominal_value=param_value['nom_val_neg_residual'])}, outputs={bel: solph.Flow()}, conversion_factors={bel: 1})) # Combined Heat and Power Plant (CHP) # Calculate annuity per installed unit of power [€/MW] ep_costs_CHP = economics.annuity( capex=param_value['capex_CHP'], n=param_value['lifetime_CHP'], wacc=param_value['wacc_CHP']) # Add CHP with its technical specifications to the energy system energysystem.add(ExtractionTurbineCHP( label='CHP_01', inputs={bgas: solph.Flow( investment=solph.Investment( ep_costs=(ep_costs_CHP*param_value['conv_factor_full_cond']), maximum=1667))}, outputs={ bel: solph.Flow(), bth: solph.Flow()}, conversion_factors={ bel: param_value['conv_factor_bel_CHP'], bth: param_value['conv_factor_bth_CHP']}, conversion_factor_full_condensation={ bel: param_value['conv_factor_full_cond']})) # Peak load gas boiler # Calculate annuity per installed unit of power [€/MW] ep_costs_boiler = economics.annuity( capex=param_value['capex_boiler'], n=param_value['lifetime_boiler'], wacc=param_value['wacc_boiler']) # Add boiler with its technical specifications to the energy system energysystem.add(solph.Transformer( label='boiler', inputs={bgas: solph.Flow()}, outputs={bth: solph.Flow(investment=solph.Investment( ep_costs=ep_costs_boiler))}, conversion_factors={bth: param_value['conversion_factor_boiler']})) ep_costs_p2h = economics.annuity( capex=param_value['capex_p2h'], n=param_value['lifetime_p2h'], wacc=param_value['wacc_p2h']) energysystem.add(solph.Transformer( label='P2H', inputs={bel_residual: solph.Flow()}, outputs={bth: solph.Flow(investment=solph.Investment( ep_costs=ep_costs_p2h))}, conversion_factors={bth: param_value['conversion_factor_p2h']})) ep_costs_TES = economics.annuity( capex=(param_value['capex_TES']*param_value['TES_capex_variation']), n=param_value['lifetime_TES'], wacc=param_value['wacc_TES']) storage_th = solph.components.GenericStorage( label='storage_th', inputs={bth: solph.Flow()}, outputs={bth: solph.Flow()}, capacity_loss=param_value['capacity_loss_storage_th'], initial_capacity=param_value['init_capacity_storage_th'], inflow_conversion_factor=param_value['inflow_conv_factor_storage_th'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_th'], invest_relation_input_capacity=1/param_value[ 'charging_time_storage_th'], invest_relation_output_capacity=1/param_value[ 'charging_time_storage_th'], investment=solph.Investment(ep_costs=ep_costs_TES)) energysystem.add(storage_th) ep_costs_EES = economics.annuity( capex=param_value['capex_EES']*param_value['EES_capex_variation'], n=param_value['lifetime_EES'], wacc=param_value['wacc_EES']) storage_el = solph.components.GenericStorage( label='storage_el', inputs={bel: solph.Flow()}, outputs={bel: solph.Flow()}, capacity_loss=param_value['capacity_loss_storage_el'], initial_capacity=param_value['init_capacity_storage_el'], inflow_conversion_factor=param_value['inflow_conv_factor_storage_el'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_el'], invest_relation_input_capacity=1 / param_value[ 'charging_time_storage_el'], invest_relation_output_capacity=1 / param_value[ 'charging_time_storage_el'], investment=solph.Investment(ep_costs=ep_costs_EES)) energysystem.add(storage_el) ########################################################################## # Optimise the energy system and store the results ########################################################################## logging.info('Optimise the energy system') model = solph.Model(energysystem) if debug: lpfile_name = 'flexCHP_scenario_{0}.lp'.format(variation_nr) filename = os.path.join( helpers.extend_basic_path('lp_files'), lpfile_name) logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) if cfg['price_el_quadratic']: energysystem.dump( dpath=(abs_path + "/results/optimisation_results/dumps/" "quadratic_price_relationship"), filename=(cfg['filename_dumb']+'_scenario_{0}.oemof'. format(variation_nr))) if cfg['price_el_quadratic'] == False: energysystem.dump( dpath=(abs_path + "/results/optimisation_results/dumps/" "linear_price_relationship"), filename=(cfg['filename_dumb']+'_scenario_{0}.oemof'.format( variation_nr)))
def write_lp_file(): filename = os.path.join( helpers.extend_basic_path('lp_files'), 'variable_chp.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True})
def berlin_model(berlin_e_system): """ Parameters ---------- berlin_e_system : solph.EnergySystem Returns ------- """ time_index = berlin_e_system.time_idx p = preferences.Basic() d = preferences.Data() logging.info("Adding objects to the energy system...") # Electricity solph.Bus(label='bus_el') heat_demand = heat.DemandHeat(time_index) heating_systems = [s for s in heat_demand.get().columns if "frac_" in s] remove_string = 'frac_' heat_demand.demand_by('total_loss_pres', heating_systems, d.bt_dict, remove_string, percentage=True) heat_demand.df = heat_demand.dissolve('bezirk', 'demand_by', index=True) heat_demand.df = heat_demand.df.rename( columns={ k: k.replace('frac_', '') for k in heat_demand.df.columns.get_level_values(1) }) for t in p.types: heat_demand.df[t] = ( heat_demand.df[t].multiply( d.sanierungsanteil[t] * d.sanierungsreduktion[t]) + heat_demand.df[t].multiply(1 - d.sanierungsanteil[t])) * 1000 ep = dict() ep['basic'] = pd.read_csv('/home/uwe/e_p.csv', ';') ep['stromanteil'] = pd.read_csv('/home/uwe/stromanteil_e_p.csv', ';') fraction_heating_system_saniert = { 'off-peak_electricity_heating': 0, 'district_heating': 0.6, 'natural_gas_heating': 0.4, 'oil_heating': 0.4, 'coal_stove': 0, 'wp': 1, } fraction_electrical_dhw = { 'off-peak_electricity_heating': 1, 'district_heating': 0.11, 'natural_gas_heating': 0.09, 'oil_heating': 0.58, 'coal_stove': 1, 'wp': 0, } ep_mix = dict() for e in ep.keys(): ep_mix[e] = dict() for b in p.types: ep_mix[e][b] = dict() cols = [x.replace('_int_DHW', '') for x in ep[e].columns] cols = set([x.replace('_el_DHW', '') for x in cols]) cols.remove('gtype') cols.remove('building') cols.remove('heating_system') for h in cols: tmp = dict() for bs in ['saniert', 'unsaniert']: tmp[bs] = dict() for hs in ['saniert', 'unsaniert']: qu = 'gtype=="{0}"'.format(b.upper()) qu += ' and building=="{0}"'.format(bs) qu += ' and heating_system=="{0}"'.format(hs) # Mix internal DHW and electrical DHW ep[e].ix[(ep[e].gtype == b.upper()) & (ep[e].building == bs) & (ep[e].heating_system == hs), h] = (ep[e].query(qu)[h + '_int_DHW'] * (1 - fraction_electrical_dhw[h]) + ep[e].query(qu)[h + '_el_DHW'] * fraction_electrical_dhw[h]) tmp[bs][hs] = ep[e].query(qu)[h] ep_mix[e][b][h] = ( float(tmp['saniert']['saniert']) * d.sanierungsanteil[b] * fraction_heating_system_saniert[h] + float(tmp['saniert']['unsaniert']) * d.sanierungsanteil[b] * (1 - fraction_heating_system_saniert[h]) + float(tmp['unsaniert']['saniert']) * (1 - d.sanierungsanteil[b]) * fraction_heating_system_saniert[h] + float(tmp['unsaniert']['unsaniert']) * (1 - d.sanierungsanteil[b]) * (1 - fraction_heating_system_saniert[h])) add_dict = { 'district_dz': 'district_heating', 'district_z': 'district_heating', 'bhkw': 'district_heating', } for e in ep_mix.keys(): for b in ep_mix[e].keys(): for new_key in add_dict.keys(): ep_mix[e][b][new_key] = ep_mix[e][b][add_dict[new_key]] # Add heating systems sum_wp = 6.42e+10 # Bei 2000 Volllaststunden sum_bhkw = 6.75e+11 # Bei 2000 Volllaststunden # sum_wp = 50e+9 # sum_bhkw = 50e+9 sum_existing = heat_demand.df.sum().sum() reduction = (sum_existing - (sum_wp + sum_bhkw)) / sum_existing frac_mfh = heat_demand.df.mfh.sum().sum() / heat_demand.df.sum().sum() new = { 'efh': { 'wp': sum_wp * (1 - frac_mfh), 'bhkw': sum_bhkw * (1 - frac_mfh) }, 'mfh': { 'wp': sum_wp * frac_mfh, 'bhkw': sum_bhkw * frac_mfh } } heat_demand.df *= reduction # Join some categories ol = d.other_demand.pop('oil_light') oh = d.other_demand.pop('oil_heavy') oo = d.other_demand.pop('oil_other') for c in ['ghd', 'i']: d.other_demand['oil_heating'][c] = ol[c] + oh[c] + oo[c] d.other_demand['natural_gas_heating'][c] += d.other_demand[ 'liquid_gas'][c] d.other_demand.pop('liquid_gas') heat_demand.df.sortlevel(axis='columns', inplace=True) # noinspection PyTypeChecker district_z = heat_demand.df.loc[:, (slice(None), 'district_heating')].multiply( d.fw_verteilung, axis=0).sum() # noinspection PyTypeChecker district_dz = heat_demand.df.loc[:, (slice(None), 'district_heating')].multiply( (1 - d.fw_verteilung), axis=0).sum() dsum = heat_demand.df.sum() for b in ['efh', 'mfh']: dsum[b, 'district_dz'] = district_dz[b]['district_heating'] dsum[b, 'district_z'] = district_z[b]['district_heating'] dsum[b, 'bhkw'] = new[b]['bhkw'] dsum[b, 'wp'] = new[b]['wp'] dsum.drop('district_heating', 0, 'second', True) dsum.sort_index(inplace=True) ew = pd.read_csv('/home/uwe/chiba/RLI/data/stadtnutzung_erweitert.csv')[[ 'ew', 'schluessel_planungsraum' ]] grp = ew.schluessel_planungsraum.astype(str).str[:-8] grp = grp.apply(lambda x: '{0:0>2}'.format(x)) ew = ew.groupby(grp).sum().drop('schluessel_planungsraum', 1) # dhw_profile = pd.read_csv('/home/uwe/dhw_demand.csv') # *ew.sum() * 657 dhw = ew.sum() * 657000 # 657000 Wh pro EW dhw_factor = (dsum.sum().sum() + float(dhw)) / dsum.sum().sum() dsum *= dhw_factor dfull = d.other_demand aux_elec = dict() sum_aux = 0 print(ep_mix) for b in dsum.keys().levels[0]: for h in dsum[b].keys(): dfull.setdefault(h, dict()) aux_elec.setdefault(h, dict()) aux_elec[h][b] = (dsum[b][h] * ep_mix['basic'][b][h] * ep_mix['stromanteil'][b][h] / 100) print("{:.2E}".format(aux_elec[h][b])) sum_aux += aux_elec[h][b] dfull[h][b] = dsum[b][h] * ep_mix['basic'][b][h] - aux_elec[h][b] # print(dfull) # e = 0 # for a in dfull.keys(): # for b in dfull[a].keys(): # if b in ['i']: # print(a, b, dfull[a][b]) # e += dfull[a][b] # print(e) # exit(0) create_objects.heating_systems(berlin_e_system, dfull, aux_elec, p) mylist = list(berlin_e_system.groups.items()) # Add excess and slack for every BUS for k, g in mylist: if isinstance(g, solph.Bus): solph.Sink(label='excess_{0}'.format(k), inputs={g: solph.Flow(variable_costs=9000)}) solph.Source(label='slack_{0}'.format(k), outputs={g: solph.Flow(variable_costs=9000)}) # slacks = ['bus_el', 'bus_district_z', 'bus_district_dz'] # for s in slacks: # obj = berlin_e_system.groups[s] # solph.Source(label='slack_{0}'.format(s), # outputs={obj: solph.Flow(variable_costs=9000)}) # sources source_costs = { 'lignite': 90, 'natural_gas': 120, 'fuel_bio': 150, 'solar_thermal': 0, 'biomass': 140, 'oil': 130, 'coal': 100 } for src in source_costs: if 'bus_' + src in berlin_e_system.groups: solph.Source(label=src, outputs={ berlin_e_system.groups['bus_' + src]: solph.Flow(variable_costs=source_costs[src]) }) else: logging.warning("No need for a {0} source.".format(src)) # import pprint as pp # pp.pprint(berlin_e_system.groups) logging.info('Optimise the energy system') om = solph.OperationalModel(berlin_e_system) filename = os.path.join(helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver='gurobi', solve_kwargs={'tee': True}) berlin_e_system.dump('/home/uwe/') return berlin_e_system
def run_model(config_path, team_number): with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile, Loader=yaml.CLoader) if cfg['debug']: number_of_time_steps = 3 else: number_of_time_steps = 8760 solver = cfg['solver'] debug = cfg['debug'] periods = number_of_time_steps solver_verbose = cfg['solver_verbose'] # show/hide solver output logger.define_logging(logfile='model_team_{0}.log'.format(team_number + 1), screen_level=logging.INFO, file_level=logging.DEBUG) logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2019', periods=number_of_time_steps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # timestr = time.strftime("%Y%m%d") ########################################################################## # Einlesen der Zeitreihen und Variablen aus den Dateien ########################################################################## abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) file_path_ts = abs_path + '/data_raw/' + cfg['time_series_file_name'] data = pd.read_csv(file_path_ts, sep=';') file_name_param_01 = cfg['design_parameters_file_name'][team_number] file_path_param_01 = (abs_path + '/data/' + file_name_param_01) param_df_01 = pd.read_csv(file_path_param_01, index_col=1, sep=';', encoding='unicode_escape') param_value = param_df_01['value'] # periodische Kosten epc_PV = economics.annuity(capex=param_value['capex_PV'], n=param_value['n_PV'], wacc=param_value['wacc']) epc_Solarthermie = economics.annuity(capex=param_value['capex_Sol'], n=param_value['n_Sol'], wacc=param_value['wacc']) epc_gas_boiler = economics.annuity(capex=param_value['capex_Gaskessel'], n=param_value['n_Gaskessel'], wacc=param_value['wacc']) epc_BHKW = economics.annuity(capex=param_value['capex_BHKW'], n=param_value['n_BHKW'], wacc=param_value['wacc']) epc_heat_pump = economics.annuity(capex=param_value['capex_Waermepumpe'], n=param_value['n_Waermepumpe'], wacc=param_value['wacc']) epc_el_storage = economics.annuity( capex=param_value['capex_Stromspeicher'], n=param_value['n_Stromspeicher'], wacc=param_value['wacc']) epc_th_storage = economics.annuity( capex=param_value['capex_Waermespeicher'], n=param_value['n_Waermespeicher'], wacc=param_value['wacc']) ########################################################################## # Erstellung der Oemof-Komponenten ########################################################################## logging.info('Create oemof objects') ### Definition der bus'es ################################################# # Erdgasbus b_gas = solph.Bus(label="Erdgas") # Strombus b_el = solph.Bus(label="Strom") # Waermebus b_th = solph.Bus(label="Waerme") # Hinzufügen zum Energiesystem energysystem.add(b_gas, b_el, b_th) ### Definition des Ueberschusses ######################################### # Senke fuer Stromueberschusss energysystem.add( solph.Sink(label='excess_bel', inputs={b_el: solph.Flow()})) # Senke fuer Waermeueberschuss energysystem.add( solph.Sink(label='excess_bth', inputs={b_th: solph.Flow()})) ### Definition Quellen ################################################# # Quelle: Erdgasnetz energysystem.add( solph.Source(label='Gasnetz', outputs={ b_gas: solph.Flow(variable_costs=param_value['vc_gas'] + param_value['vc_CO2']) })) #[€/kWh] # Quelle: Stromnetz energysystem.add( solph.Source(label='Strombezug', outputs={ b_el: solph.Flow(variable_costs=param_value['vc_el']) })) #[€/kWh] # Quelle: Waermenetz/Fernwaerme energysystem.add( solph.Source(label='Waermebezug', outputs={ b_th: solph.Flow(variable_costs=param_value['vc_th']) })) #[€/kWh] # Quelle: Solaranlage if param_value['A_Kollektor_gesamt'] > 0: energysystem.add( solph.Source( label='PV', outputs={ b_el: solph.Flow( actual_value=(data['Sol_irradiation [Wh/sqm]'] * 0.001 * param_value['cf_PV']), #[kWh/m²] fixed=True, investment=solph.Investment( ep_costs=epc_PV, minimum=param_value['A_min_PV'] * 1 * param_value['cf_PV'])) })) # Quelle: Solarthermieanlage if param_value['A_Kollektor_gesamt'] > 0: energysystem.add( solph.Source( label='Solarthermie', outputs={ b_th: solph.Flow( actual_value=(data['Sol_irradiation [Wh/sqm]'] * 0.001 * param_value['cf_Sol']), #[kWh/m²] fixed=True, investment=solph.Investment( ep_costs=epc_Solarthermie, minimum=param_value['A_min_Sol'] * 1 * param_value['cf_Sol'])) })) ### Definition Bedarf ################################################ # Strombedarf energysystem.add( solph.Sink( label='Strombedarf', inputs={ b_el: solph.Flow( actual_value=data['P*'], nominal_value=param_value['W_el'], #[kWh] fixed=True) })) # Waermebedarf energysystem.add( solph.Sink( label='Waermebedarf', inputs={ b_th: solph.Flow( actual_value=data['Q*'], nominal_value=param_value['W_th'], #[kWh] fixed=True) })) ### Definition Systemkomponenten ######################################### # Transformer: Gaskessel if param_value['max_Gaskessel'] > 0: energysystem.add( solph.Transformer( label="Gaskessel", inputs={b_gas: solph.Flow()}, outputs={ b_th: solph.Flow(investment=solph.Investment( ep_costs=epc_gas_boiler, minimum=param_value['min_Gaskessel'], #[kW] maximum=param_value['max_Gaskessel'])) }, #[kW] conversion_factors={b_th: param_value['cf_Gaskessel']})) # Transformer: BHKW if param_value['max_BHKW'] > 0: energysystem.add( solph.Transformer( label="BHKW", inputs={b_gas: solph.Flow()}, outputs={ b_el: solph.Flow(), b_th: solph.Flow(investment=solph.Investment( ep_costs=epc_BHKW, minimum=param_value['min_BHKW'], #[kW] maximum=param_value['max_BHKW'])) }, #[kW] conversion_factors={ b_el: param_value['cf_BHKW_el'], b_th: 0.85 - param_value['cf_BHKW_el'] })) # Transformer: Waermepumpe if param_value['max_Waermepumpe'] > 0: energysystem.add( solph.Transformer( label="Waermepumpe", inputs={b_el: solph.Flow()}, outputs={ b_th: solph.Flow(investment=solph.Investment( ep_costs=epc_heat_pump, minimum=param_value['min_Waermepumpe'], #[kW] maximum=param_value['max_Waermepumpe'])) }, #[kW] conversion_factors={b_th: param_value['COP_Waermepumpe']})) # Speicher: Stromspeicher if param_value['max_Stromspeicher'] > 0: Stromspeicher = solph.components.GenericStorage( label='Stromspeicher', inputs={b_el: solph.Flow()}, outputs={b_el: solph.Flow()}, loss_rate=param_value['lr_Stromspeicher'], initial_storage_level=param_value['isl_Stromspeicher'], inflow_conversion_factor=param_value['cf_Stromspeicher_ein'], outflow_conversion_factor=param_value['cf_Stromspeicher_aus'], investment=solph.Investment( ep_costs=epc_el_storage, minimum=param_value['min_Stromspeicher'], #[kWh] maximum=param_value['max_Stromspeicher'])) #[kWh] energysystem.add(Stromspeicher) # Speicher: Waermespeicher if param_value['max_Waermespeicher'] > 0: Waermespeicher = solph.components.GenericStorage( label='Waermespeicher', inputs={b_th: solph.Flow()}, outputs={b_th: solph.Flow()}, loss_rate=param_value['lr_Waermespeicher'], initial_storage_level=param_value['isl_Waermespeicher'], inflow_conversion_factor=param_value['cf_Waermespeicher_ein'], outflow_conversion_factor=param_value['cf_Waermespeicher_aus'], investment=solph.Investment( ep_costs=epc_th_storage, minimum=param_value['min_Waermespeicher'], #[kWh] maximum=param_value['max_Waermespeicher'])) #[kWh] energysystem.add(Waermespeicher) logging.info('Optimise the energy system') # Initialisierung des Modells model = solph.Model(energysystem) ########################################################################## # Constraint fuer Kollektorgesamtflaeche ########################################################################## PV_installed = energysystem.groups['PV'] Sol_installed = energysystem.groups['Solarthermie'] myconstrains = po.Block() model.add_component('MyBlock', myconstrains) myconstrains.collector_area = po.Constraint(expr=( (((model.InvestmentFlow.invest[PV_installed, b_el]) / (1 * param_value['cf_PV'])) + ((model.InvestmentFlow.invest[Sol_installed, b_th]) / (1 * param_value['cf_Sol']))) <= param_value['A_Kollektor_gesamt'])) ########################################################################## # Optimierung des Systems und Speichern des Ergebnisses ########################################################################## if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'model_team_{0}.lp'.format(team_number + 1)) logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info( 'Solve the optimization problem of team {0}'.format(team_number + 1)) model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') # add results to the energy system to make it possible to store them. energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) results = energysystem.results['main'] energysystem.dump(dpath=abs_path + "/results", filename="model_team_{0}.oemof".format(team_number + 1))
def optimise_storage_size(filename="storage_invest.csv", solvername='cbc', debug=True, number_timesteps=8760, tee_switch=True): logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/' + str(year), periods=number_timesteps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # Read data file full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") data_demand = data['demand_el'] / data['demand_el'].sum() ########################################################################## # Create oemof object ########################################################################## consumption = 5165 * 1e6 wind_installed = 1516 * 1e3 pv_installed = 1491 * 1e3 grid_share = 0.75 logging.info('Create oemof objects') # create gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") # create excess component for the electricity bus to allow overproduction solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) # Create commodity object for import electricity resource solph.Source(label='gridsource', outputs={ bel: solph.Flow(nominal_value=consumption * grid_share * number_timesteps / 8760, summed_max=1) }) # create fixed source object for wind solph.Source(label='wind', outputs={ bel: solph.Flow(actual_value=wind_feedin, nominal_value=wind_installed, fixed=True, fixed_costs=20) }) # create fixed source object for pv solph.Source(label='pv', outputs={ bel: solph.Flow(actual_value=pv_feedin, nominal_value=pv_installed, fixed=True, fixed_costs=15) }) # create simple sink object for demand solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=data_demand, fixed=True, nominal_value=consumption) }) # Calculate ep_costs from capex to compare with old solph capex = 1000 lifetime = 20 wacc = 0.05 epc = capex * (wacc * (1 + wacc)**lifetime) / ((1 + wacc)**lifetime - 1) # create storage transformer object for storage solph.Storage( label='storage', inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, capacity_loss=0.00, initial_capacity=0, nominal_input_capacity_ratio=1, nominal_output_capacity_ratio=1, inflow_conversion_factor=1, outflow_conversion_factor=0.8, fixed_costs=35, investment=solph.Investment(ep_costs=epc), ) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') om = solph.OperationalModel(energysystem) if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver=solvername, solve_kwargs={'tee': tee_switch}) return energysystem
def optimise_storage_size(filename="storage_investment.csv", solver='cbc', debug=True, number_timesteps=8760, tee_switch=True): logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2012', periods=number_timesteps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # Read data file full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') # create natural gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") # create excess component for the electricity bus to allow overproduction solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) # create source object representing the natural gas commodity (annual limit) solph.Source(label='rgas', outputs={ bgas: solph.Flow(nominal_value=194397000 * number_timesteps / 8760, summed_max=1) }) # create fixed source object representing wind power plants solph.Source(label='wind', outputs={ bel: solph.Flow(actual_value=data['wind'], nominal_value=1000000, fixed=True, fixed_costs=20) }) # create fixed source object representing pv power plants solph.Source(label='pv', outputs={ bel: solph.Flow(actual_value=data['pv'], nominal_value=582000, fixed=True, fixed_costs=15) }) # create simple sink object representing the electrical demand solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) # create simple transformer object representing a gas power plant solph.LinearTransformer( label="pp_gas", inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58}) # If the period is one year the equivalent periodical costs (epc) of an # investment are equal to the annuity. Use oemof's economic tools. epc = economics.annuity(capex=1000, n=20, wacc=0.05) # create storage object representing a battery solph.Storage( label='storage', inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, capacity_loss=0.00, initial_capacity=0, nominal_input_capacity_ratio=1 / 6, nominal_output_capacity_ratio=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, fixed_costs=35, investment=solph.Investment(ep_costs=epc), ) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') # initialise the operational model om = solph.OperationalModel(energysystem) # if debug is true an lp-file will be written if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') om.solve(solver=solver, solve_kwargs={'tee': tee_switch}) return energysystem
def define_logging(logpath=None, logfile='oemof.log', file_format=None, screen_format=None, file_datefmt=None, screen_datefmt=None, screen_level=logging.INFO, file_level=logging.DEBUG, log_version=True, log_path=True, timed_rotating=None): r"""Initialise customisable logger. Parameters ---------- logfile : str Name of the log file, default: oemof.log logpath : str The path for log files. By default a ".oemof' folder is created in your home directory with subfolder called 'log_files'. file_format : str Format of the file output. Default: "%(asctime)s - %(levelname)s - %(module)s - %(message)s" screen_format : str Format of the screen output. Default: "%(asctime)s-%(levelname)s-%(message)s" file_datefmt : str Format of the datetime in the file output. Default: None screen_datefmt : str Format of the datetime in the screen output. Default: "%H:%M:%S" screen_level : int Level of logging to stdout. Default: 20 (logging.INFO) file_level : int Level of logging to file. Default: 10 (logging.DEBUG) log_version : boolean If True the actual version or commit is logged while initialising the logger. log_path : boolean If True the used file path is logged while initialising the logger. timed_rotating : dict Option to pass parameters to the TimedRotatingFileHandler. Returns ------- str : Place where the log file is stored. Notes ----- By default the INFO level is printed on the screen and the DEBUG level in a file, but you can easily configure the logger. Every module that wants to create logging messages has to import the logging module. The oemof logger module has to be imported once to initialise it. Examples -------- To define the default logger you have to import the python logging library and this function. The first logging message should be the path where the log file is saved to. >>> import logging >>> from oemof.tools import logger >>> mypath = logger.define_logging( ... log_path=True, log_version=True, timed_rotating={'backupCount': 4}, ... screen_level=logging.ERROR, screen_datefmt = "no_date") >>> mypath[-9:] 'oemof.log' >>> logging.debug("Hallo") """ if logpath is None: logpath = helpers.extend_basic_path('log_files') file = os.path.join(logpath, logfile) log = logging.getLogger('') # Remove existing handlers to avoid interference. log.handlers = [] log.setLevel(logging.DEBUG) if file_format is None: file_format = ( "%(asctime)s - %(levelname)s - %(module)s - %(message)s") file_formatter = logging.Formatter(file_format, file_datefmt) if screen_format is None: screen_format = "%(asctime)s-%(levelname)s-%(message)s" if screen_datefmt is None: screen_datefmt = "%H:%M:%S" screen_formatter = logging.Formatter(screen_format, screen_datefmt) tmp_formatter = logging.Formatter("%(message)s") ch = logging.StreamHandler(sys.stdout) ch.setFormatter(screen_formatter) ch.setLevel(screen_level) log.addHandler(ch) timed_rotating_p = {'when': 'midnight', 'backupCount': 10} if timed_rotating is not None: timed_rotating_p.update(timed_rotating) fh = handlers.TimedRotatingFileHandler(file, **timed_rotating_p) fh.setFormatter(tmp_formatter) fh.setLevel(file_level) log.addHandler(fh) logging.debug("******************************************************") fh.setFormatter(file_formatter) if log_path: logging.info("Path for logging: {0}".format(file)) if log_version: logging.info("Used oemof version: {0}".format(get_version())) return file
def optimise_storage_size(filename="storage_invest.csv", solvername='cbc', debug=True, number_timesteps=8760, tee_switch=True): logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/' + str(year), periods=number_timesteps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # Read data file full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") data_demand = data['demand_el']/data['demand_el'].sum() ########################################################################## # Create oemof object ########################################################################## consumption = 2255 * 1e6 wind_installed = 1000 * 1e3 pv_installed = 582 * 1e3 grid_share = 0.05 logging.info('Create oemof objects') # create gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") # create excess component for the electricity bus to allow overproduction solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) # Create commodity object for import electricity resource solph.Source(label='gridsource', outputs={bel: solph.Flow( nominal_value=consumption * grid_share * number_timesteps / 8760, summed_max=1)}) # create fixed source object for wind solph.Source(label='wind', outputs={bel: solph.Flow( actual_value=wind_feedin, nominal_value=wind_installed, fixed=True, fixed_costs=20)}) # create fixed source object for pv solph.Source(label='pv', outputs={bel: solph.Flow( actual_value=pv_feedin, nominal_value=pv_installed, fixed=True, fixed_costs=15)}) # create simple sink object for demand solph.Sink(label='demand', inputs={bel: solph.Flow( actual_value=data_demand, fixed=True, nominal_value=consumption)}) # Calculate ep_costs from capex to compare with old solph capex = 1000 lifetime = 20 wacc = 0.05 epc = capex * (wacc * (1 + wacc) ** lifetime) / ((1 + wacc) ** lifetime - 1) # create storage transformer object for storage solph.Storage( label='storage', inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, capacity_loss=0.00, initial_capacity=0, nominal_input_capacity_ratio=1, nominal_output_capacity_ratio=1, inflow_conversion_factor=1, outflow_conversion_factor=0.8, fixed_costs=35, investment=solph.Investment(ep_costs=epc), ) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') om = solph.OperationalModel(energysystem) if debug: filename = os.path.join( helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver=solvername, solve_kwargs={'tee': tee_switch}) return energysystem