def initialize_basic_energysystem(): # initialize and provide data datetimeindex = pd.date_range('1/1/2016', periods=24, freq='H') filename = 'input_data.csv' data = pd.read_csv(filename, sep=",") energysystem = EnergySystem(timeindex=datetimeindex) # buses bcoal = Bus(label='coal', balanced=False) bgas = Bus(label='gas', balanced=False) bel = Bus(label='electricity') energysystem.add(bcoal, bgas, bel) # sources energysystem.add( Source(label='wind', outputs={ bel: Flow(actual_value=data['wind'], nominal_value=66.3, fixed=True) })) energysystem.add( Source(label='pv', outputs={ bel: Flow(actual_value=data['pv'], nominal_value=65.3, fixed=True) })) # excess and shortage to avoid infeasibilies energysystem.add(Sink(label='excess_el', inputs={bel: Flow()})) energysystem.add( Source(label='shortage_el', outputs={bel: Flow(variable_costs=200)})) # demands (electricity/heat) energysystem.add( Sink(label='demand_el', inputs={ bel: Flow(nominal_value=85, actual_value=data['demand_el'], fixed=True) })) return bcoal, bgas, bel, energysystem
def test_fixed_source_invest_sink(self): """ Wrong constraints for fixed source + invest sink w. `summed_max`. """ bel = Bus(label='electricityBus') Source(label='wind', outputs={ bel: Flow(actual_value=[12, 16, 14], nominal_value=1000000, fixed=True, fixed_costs=20) }) Sink(label='excess', inputs={ bel: Flow(summed_max=2.3, variable_costs=25, max=0.8, investment=Investment(ep_costs=500, maximum=10e5)) }) self.compare_lp_files('fixed_source_invest_sink.lp')
def build_solph_components(self): """ """ if self.expandable: raise NotImplementedError( "Investment for reservoir class is not implemented.") inflow = Source( label=self.label + "-inflow", outputs={ self: Flow(nominal_value=self.aperture_area, max=self.collectors_heat) }, ) self.conversion_factors.update({ self.electrical_bus: sequence(self.electrical_consumption * (1 - self.additional_losses)), self.heat_bus: sequence(1 - self.additional_losses), inflow: sequence(1) }) self.inputs.update({self.electrical_bus: Flow()}) self.outputs.update({self.heat_bus: Flow()}) self.subnodes = (inflow, )
def build_solph_components(self): """ """ if self.expandable: raise NotImplementedError( "Investment for solar thermal collector facade has not been implemented yet." ) inflow = Source( label=self.label + "-inflow", outputs={ self: Flow(nominal_value=self.aperture_area, max=self.collectors_heat) }, ) self.conversion_factors.update({ self.electricity_in_bus: sequence(self.electrical_consumption * (1 - self.peripheral_losses)), self.heat_out_bus: sequence(1 - self.peripheral_losses), inflow: sequence(1) }) self.inputs.update({self.electricity_in_bus: Flow()}) self.outputs.update({self.heat_out_bus: Flow()}) self.subnodes = (inflow, )
def add_shortage_excess(nodes): bus_keys = [key for key in nodes.keys() if "bus" in key.cat] for key in bus_keys: excess_label = Label("excess", key.tag, key.subtag, key.region) nodes[excess_label] = Sink(label=excess_label, inputs={nodes[key]: Flow()}) shortage_label = Label("shortage", key.tag, key.subtag, key.region) nodes[shortage_label] = Source( label=shortage_label, outputs={nodes[key]: Flow(variable_costs=900)}, )
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs, _facade_requires_=['bus', 'inflow', 'efficiency']) self.storage_capacity = kwargs.get('storage_capacity') self.capacity = kwargs.get('capacity') self.efficiency = kwargs.get('efficiency') self.nominal_capacity = self.storage_capacity self.capacity_cost = kwargs.get('capacity_cost') self.storage_capacity_cost = kwargs.get('storage_capacity_cost') self.spillage = kwargs.get('spillage', True) self.input_edge_parameters = kwargs.get('input_edge_parameters', {}) self.output_edge_parameters = kwargs.get('output_edge_parameters', {}) investment = self._investment() reservoir_bus = Bus(label="reservoir-bus-" + self.label) inflow = Source(label="inflow" + self.label, outputs={ reservoir_bus: Flow(nominal_value=1, actual_value=self.inflow, fixed=True) }) if self.spillage: f = Flow() else: f = Flow(actual_value=0, fixed=True) spillage = Sink(label="spillage" + self.label, inputs={reservoir_bus: f}) self.inputs.update({reservoir_bus: Flow(**self.input_edge_parameters)}) self.outputs.update({ self.bus: Flow(investment=investment, **self.output_edge_parameters) }) self.subnodes = (reservoir_bus, inflow, spillage)
def test_max_source_min_sink(self): """ """ bel = Bus(label='electricityBus') Source(label='wind', outputs={bel: Flow(nominal_value=54, max=(.85, .95, .61))}) Sink(label='minDemand', inputs={ bel: Flow(nominal_value=54, min=(.84, .94, .59), variable_costs=14) }) self.compare_lp_files('max_source_min_sink.lp')
def test_fixed_source_variable_sink(self): """Constraint test with a fixed source and a variable sink. """ bel = Bus(label='electricityBus') Source(label='wind', outputs={ bel: Flow(actual_value=[.43, .72, .29], nominal_value=10e5, fixed=True, fixed_costs=20) }) Sink(label='excess', inputs={bel: Flow(variable_costs=40)}) self.compare_lp_files('fixed_source_variable_sink.lp')
def add_volatile_sources(table_collection, nodes): """ Parameters ---------- table_collection nodes Returns ------- """ logging.debug("Add volatile sources to nodes dictionary.") vs = table_collection["volatile_source"] for region in vs.columns.get_level_values(0).unique(): for vs_type in vs[region].columns: vs_label = Label("source", "ee", vs_type, region) capacity = vs.loc["capacity", (region, vs_type)] try: feedin = table_collection["volatile_series"][region, vs_type] except KeyError: if capacity > 0: msg = "Missing time series for {0} (capacity: {1}) in {2}." raise ValueError(msg.format(vs_type, capacity, region)) feedin = [0] bus_label = Label("bus", "electricity", "all", region) if bus_label not in nodes: nodes[bus_label] = Bus(label=bus_label) if capacity * sum(feedin) > 0: nodes[vs_label] = Source( label=vs_label, outputs={ nodes[bus_label]: Flow( actual_value=feedin, nominal_value=capacity, fixed=True, emission=0, ) }, )
def create_fuel_bus_with_source(nodes, fuel, region, data): bus_label = Label("bus", "commodity", fuel.replace(" ", "_"), region) if bus_label not in nodes: nodes[bus_label] = Bus(label=bus_label) cs_label = Label("source", "commodity", fuel.replace(" ", "_"), region) if cs_label not in nodes: nodes[cs_label] = Source( label=cs_label, outputs={ nodes[bus_label]: Flow( variable_costs=data.loc["costs", fuel.replace("_", " ")], emission=data.loc["emission", fuel.replace("_", " ")], ) }, )
def build_solph_components(self): """ """ self.nominal_storage_capacity = self.storage_capacity self.outflow_conversion_factor = sequence(self.efficiency) if self.expandable: raise NotImplementedError( "Investment for reservoir class is not implemented.") inflow = Source( label=self.label + "-inflow", outputs={ self: Flow(nominal_value=1, max=self.profile, fixed=False) }, ) self.outputs.update({ self.bus: Flow(nominal_value=self.capacity, **self.output_parameters) }) self.subnodes = (inflow, )
def test_invest_source_fixed_sink(self): """Constraint test with a fixed sink and a dispatch invest source. """ bel = Bus(label='electricityBus') Source(label='pv', outputs={ bel: Flow(max=[45, 83, 65], fixed_costs=20, variable_costs=13, investment=Investment(ep_costs=123)) }) Sink(label='excess', inputs={ bel: Flow(actual_value=[.5, .8, .3], nominal_value=10e4, fixed=True) }) self.compare_lp_files('invest_source_fixed_sink.lp')
# Set up an energy system model solver = 'cbc' periods = 100 datetimeindex = pd.date_range('1/1/2019', periods=periods, freq='H') demand_timeseries = np.zeros(periods) demand_timeseries[-5:] = 1 heat_feedin_timeseries = np.zeros(periods) heat_feedin_timeseries[:10] = 1 energysystem = EnergySystem(timeindex=datetimeindex) bus_heat = Bus(label='bus_heat') heat_source = Source( label='heat_source', outputs={bus_heat: Flow(nominal_value=1, fix=heat_feedin_timeseries)}) shortage = Source(label='shortage', outputs={bus_heat: Flow(variable_costs=1e6)}) excess = Sink(label='excess', inputs={bus_heat: Flow()}) heat_demand = Sink( label='heat_demand', inputs={bus_heat: Flow(nominal_value=1, fix=demand_timeseries)}) thermal_storage = facades.StratifiedThermalStorage( label='thermal_storage', bus=bus_heat, diameter=input_data[
from oemof.solph import ( EnergySystem, Sink, Source, Transformer, Bus, Flow, GenericStorage, ) from oemof_visio import ESGraphRenderer es = EnergySystem() bus_ac = Bus(label="AC") bus_dc = Bus(label="DC") wind = Source(label="wind", outputs={bus_ac: Flow()}) pv = Source(label="pv", outputs={bus_dc: Flow()}) demand_el = Sink(label="demand_el", inputs={bus_ac: Flow()}) storage_el = GenericStorage( label="storage_el", inputs={bus_ac: Flow()}, outputs={bus_ac: Flow()}, ) pv_converter = Transformer(label="chp_gas", inputs={bus_dc: Flow()}, outputs={bus_ac: Flow()}) excess_el = Sink(label="excess_el", inputs={bus_ac: Flow()}) es.add(bus_ac, bus_dc, wind, pv, demand_el, storage_el, excess_el, pv_converter) gr = ESGraphRenderer(energy_system=es, filepath="energy_system",
def simulate(folder, **kwargs): # This is how you get a scenario object from the database. # Since the iD editor prefixes element ids with their type ('r' for # relation, 'w' for way and 'n' for node), we have to strip a leading # character from the scenario id string before converting it to int. # This is what the [1:] is for. engine = db.engine(osm.configsection) Session = sessionmaker(bind=engine) session = Session() scenario = session.query( osm.Relation).filter_by(id=int(kwargs['scenario'][1:])).first() #id = 1).first() # Delete the scenario id from `kwargs` so that is doesn't show up in the # response later. del kwargs['scenario'] # Now you can access the nodes, ways and relations this scenario contains # and build oemof objects from them. I'll only show you how to access the # contents here. # These are lists with Node, Way and Relation objects. # See the .schemas.osm module for the API. elements = scenario.elements nodes = [n for n in elements if isinstance(n, osm.Node)] ways = [w for w in elements if isinstance(w, osm.Way)] relations = [r for r in elements if isinstance(r, osm.Relation)] # emission factor (hardcoded for now....) t/MWh emission_factors = { 'gas': 0.2, 'coal': 0.34, 'oil': 0.27, 'lignite': 0.4, 'waste': 0.3, 'biomass': 0, 'wind': 0, 'solar': 0 } ######################################################################### # OEMOF SOLPH ######################################################################### # We need a datetimeindex for the optimization problem / energysystem first = pd.to_datetime(scenario.tags.get('scenario_year' + '0101', '2016')) start = first + pd.DateOffset( hours=int(scenario.tags.get('start_timestep', 1)) - 1) end = first + pd.DateOffset( hours=int(scenario.tags.get('end_timestep', 8760)) - 1) datetimeindex = pd.date_range(start=start, end=end, freq='H') energy_system = EnergySystem(groupings=GROUPINGS, timeindex=datetimeindex) ## CREATE BUSES FROM RELATIONS OF TYPE "HUB RELATION" buses = {} for r in relations: if r.tags.get('type') is not None: if r.tags['type'] == 'hub_relation': name = r.tags.get('name') buses[name] = Bus(label=str(name)) buses[name].energy_sector = r.tags['energy_sector'] else: raise ValueError('Missing tag type of component with ' + 'name {0}.'.format(r.tags['name'])) ## GLOBAL FUEL BUSES FOR TRANSFORMER INPUTS (THAT ARE NOT IN RELATIONS) global_buses = {} for n in nodes: if n.tags.get('oemof_class') == 'linear_transformer': # Only create global bus if not already exist if global_buses.get(n.tags['fuel_type']) is None: global_buses[n.tags['fuel_type']] = Bus( label=n.tags['fuel_type'], balanced=False) ## Create Nodes (added automatically to energysystem) for n in nodes: # GET RELATIONS 'HUB ASSIGNMENT' FOR NODE node_bus = [ r.tags['name'] for r in n.referencing_relations if r.tags['name'] in list(buses.keys()) ] # create the variable cost timeseries if specified, otherwise use # variable costs key from tags if n.tags.get('variable_costs', 0) == 'timeseries': variable_costs = n.timeseries.get('variable_costs') if variable_costs is None: raise ValueError('No timeseries `variable cost` found for ' + 'node {0}.'.format(n.tags.get('name'))) else: variable_costs = _float(n, 'variable_costs') # CREATE SINK OBJECTS if n.tags.get('oemof_class') == 'sink': if n.tags.get('energy_amount') is None: nominal_value = None if n.timeseries.get('load_profile') is not None: raise ValueError('No enery amount has been specified' + ' but the load_profile has been set!') else: nominal_value = _float(n, 'energy_amount') # calculate actual value if n.timeseries.get('load_profile') is None: actual_value = None else: try: actual_value = [ i / sum(n.timeseries.get('load_profile')) for i in n.timeseries.get('load_profile') ] except Exception: actual_value = None s = Sink(label=n.tags['name'], inputs={ buses[node_bus[0]]: Flow(nominal_value=nominal_value, actual_value=actual_value, variable_costs=variable_costs, fixed=True) }) s.type = n.tags['type'] # CREATE SOURCE OBJECTS if n.tags.get('oemof_class') == 'source': s = Source(label=n.tags['name'], outputs={ buses[node_bus[0]]: Flow(nominal_value=_float(n, 'installed_power'), actual_value=n.timeseries['load_profile'], variable_costs=variable_costs, fixed=True) }) s.fuel_type = n.tags['fuel_type'] s.type = n.tags['type'] # CREATE TRANSFORMER OBJECTS if n.tags.get('oemof_class') == 'linear_transformer': # CREATE LINEAR TRANSFORMER if n.tags.get('type') == 'flexible_generator': ins = global_buses[n.tags['fuel_type']] outs = buses[node_bus[0]] t = LinearTransformer( label=n.tags['name'], inputs={ins: Flow(variable_costs=variable_costs)}, outputs={ outs: Flow(nominal_value=_float(n, 'installed_power')) }, conversion_factors={outs: _float(n, 'efficiency')}) # store fuel_type as attribute for identification t.fuel_type = n.tags['fuel_type'] t.type = n.tags['type'] # CREATE COMBINED HEAT AND POWER AS LINEAR TRANSFORMER if n.tags.get('type') == 'combined_flexible_generator': ins = global_buses[n.tags['fuel_type']] heat_out = [ buses[k] for k in node_bus if buses[k].energy_sector == 'heat' ][0] power_out = [ buses[k] for k in node_bus if buses[k].energy_sector == 'electricity' ][0] t = LinearTransformer( label=n.tags['name'], inputs={ins: Flow(variable_costs=variable_costs)}, outputs={ power_out: Flow(nominal_value=_float(n, 'installed_power')), heat_out: Flow() }, conversion_factors={ heat_out: _float(n, 'thermal_efficiency'), power_out: _float(n, 'electrical_efficiency') }) t.fuel_type = n.tags['fuel_type'] t.type = n.tags['type'] # CRAETE STORAGE OBJECTS if n.tags.get('oemof_class') == 'storage': # Oemof solph does not provide direct way to set power in/out of # storage hence, we need to caculate the needed ratios upfront nicr = (_float(n, 'installed_power') / _float(n, 'installed_energy')) nocr = (_float(n, 'installed_power') / _float(n, 'installed_energy')) s = Storage(label=n.tags['name'], inputs={ buses[node_bus[0]]: Flow(variable_costs=variable_costs) }, outputs={ buses[node_bus[0]]: Flow(variable_costs=variable_costs) }, nominal_capacity=_float(n, 'installed_energy'), nominal_input_capacity_ratio=nicr, nominal_output_capacity_ration=nocr) s.energy_sector = n.tags['energy_sector'] s.type = n.tags['type'] # loop over all ways to create transmission objects for w in ways: way_bus = [ r.tags['name'] for r in w.referencing_relations if r.tags['name'] in list(buses.keys()) ] if w.tags.get('oemof_class') == 'linear_transformer': # CREATE TWO TRANSFORMER OBJECTS WITH DIFFERENT DIRECTIONS IN/OUTS if w.tags.get('type') == 'transmission': # transmission lines are modelled as two transformers with # the same technical parameters ins = buses[way_bus[0]] outs = buses[way_bus[1]] # 1st transformer t1 = LinearTransformer( label=w.tags['name'] + '_1', inputs={outs: Flow()}, outputs={ ins: Flow(nominal_value=_float(w, 'installed_power')) }, conversion_factors={ins: _float(w, 'efficiency')}) t1.type = w.tags.get('type') # 2nd transformer t2 = LinearTransformer( label=w.tags['name'] + '_2', inputs={ins: Flow()}, outputs={ outs: Flow(nominal_value=_float(w, 'installed_power')) }, conversion_factors={outs: _float(w, 'efficiency')}) t2.type = w.tags.get('type') # Create optimization model, solve it, wrtie back results om = OperationalModel(es=energy_system) solver = scenario.tags.get('solver') if solver is None: solver = 'glpk' om.solve(solver=solver, solve_kwargs={'tee': True, 'keepfiles': False}) om.results() # create results dataframe based on oemof's outputlib (multiindex) esplot = output.DataFramePlot(energy_system=energy_system) # select subsets of data frame (full hub balances) and write to temp-csv csv_links = {} for b in buses.values(): subset = esplot.slice_by(bus_label=b.label, type='to_bus').unstack([0, 1, 2]) fd, temp_path = mkstemp(dir=folder, suffix='.csv') file = open(temp_path, 'w') file.write(subset.to_csv()) file.close() os.close(fd) head, tail = os.path.split(temp_path) link = "/static/" + tail # storage csv-file links in dictionary for html result page csv_links[b.label] = link ####################### CALCULATIONS FOR OUTPUT ########################### # get electical hubs production el_buses = [ b.label for b in buses.values() if b.energy_sector == 'electricity' ] components = [n for n in energy_system.nodes if not isinstance(n, Bus)] #plot_nodes = [c.label for c in components if c.type != 'transmission'] renewables = [c for c in components if isinstance(c, Source)] wind = [c.label for c in renewables if c.fuel_type == 'wind'] solar = [c.label for c in renewables if c.fuel_type == 'solar'] wind_production = esplot.slice_by(bus_label=el_buses, obj_label=wind, type='to_bus').unstack(2).sum(axis=1) wind_production.index = wind_production.index.droplevel(1) wind_production = wind_production.unstack(0) #pdb.set_trace() if not wind_production.empty: wind_production.columns = ['wind'] solar_production = esplot.slice_by(bus_label=el_buses, obj_label=solar, type='to_bus').unstack(2).sum(axis=1) solar_production.index = solar_production.index.droplevel(1) solar_production = solar_production.unstack(0) if not solar_production.empty: solar_production.columns = ['solar'] # slice fuel types, unstack components and sum components by fuel type fossil_production = esplot.slice_by(bus_label=global_buses.keys(), type='from_bus').unstack(2).sum(axis=1) # drop level 'from_bus' that all rows have anyway fossil_production.index = fossil_production.index.droplevel(1) # turn index with fuel type to columns fossil_production = fossil_production.unstack(0) all_production = pd.concat( [fossil_production, wind_production, solar_production], axis=1) all_production = all_production.resample('1D', how='sum') fossil_emissions = fossil_production.copy() #pdb.set_trace() for col in fossil_production: fossil_emissions[col] = fossil_production[col] * emission_factors[col] # sum total emissions emission = fossil_emissions.sum(axis=1) emission = emission.resample('1D', how='sum') # helpers for generating python-html ouput help_fill = ['tozeroy'] + ['tonexty'] * (len(all_production.columns) - 1) fill_dict = dict(zip(all_production.columns, help_fill)) colors = { 'gas': '#9bc8c8', 'coal': '#9b9499', 'oil': '#2e1629', 'lignite': '#c89b9b', 'waste': '#8b862a', 'biomass': '#187c66', 'wind': '#2b99ff', 'solar': '#ffc125' } p = Bar(all_production.sum() / 1e3, legend=False, title="Summend energy production", xlabel="Type", ylabel="Energy Production in GWh", width=400, height=300, palette=[colors[col] for col in all_production]) output_file(os.path.join(folder, 'all_production.html')) #show(p) e = Bar(fossil_emissions.sum(), legend=False, title="Summend CO2-emissions of production", xlabel="Type", ylabel="Energy Production in tons", width=400, height=300, palette=[colors[col] for col in all_production]) output_file(os.path.join(folder, 'emissions.html')) #show(e) plots = {'production': p, 'emissions': e} script, div = bokeh_components(plots) ########## RENDER PLOTS ################ # Define our html template for out plots template = Template('''<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>openmod.sh Scenario Results</title> {{ js_resources }} {{ css_resources }} <script src='https://cdn.plot.ly/plotly-latest.min.js'></script> </head> <body> <table> <tr> <td> <h3> Total CO2 - Emission </h3> {{ plot_div.emissions }} </td> <td> </td> <td> <h3> Total energy production </h3> {{ plot_div.production }} </td> </tr> </table> {{ plot_script }} <h3> Daily production and emissions </h3> {{ timeplot }} <h3> Download your results </h3> {{ download }} </body> </html> ''') timeplot = ( "<div id='myDiv' style='width: 800px; height: 500px;'></div>" + "<script>" + "var traces = [" + ", ".join([ "{{x: {0}, y: {1}, fill: '{fillarg}', name: '{name}'}}".format( list(range(len(all_production.index.values))), list(all_production[col].values), name=col, fillarg=fill_dict[col]) for col in all_production ]) + "];" + "function stackedArea(traces) {" + "for(var i=1; i<traces.length; i++) {" + "for(var j=0; j<(Math.min(traces[i]['y'].length, traces[i-1]['y'].length)); j++) {" + "traces[i]['y'][j] += traces[i-1]['y'][j];}}" + "return traces;}" + "var layout = {title: 'Total electricity production on all hubs'," + "xaxis: {title: 'Day of the year'}," + "yaxis : {title: 'Energy in MWh'}," + "yaxis2: {title: 'CO2-emissions in tons', " + "range: [0, {0}],".format(emission.max() * 1.1) + #"titlefont: {color: 'rgb(148, 103, 189)'}, " + #"tickfont: {color: 'rgb(148, 103, 189)'}," + "overlaying: 'y', side: 'right'}," + "legend: {x: 0, y: 1,}};" + #"var data = " + "["+",".join(["{0}".format(col) for col in subset]) + "];" "var emission = {{x: {0}, y: {1}, type: 'scatter', yaxis: 'y2', name: 'CO2-Emissions'}};" .format(list(range(len(emission.index.values))), list(emission.values)) + "data = stackedArea(traces);" + "data.push(emission);" + "Plotly.newPlot('myDiv', data, layout);" + "</script>") download = ( "<br />You can download your results below:<br /> Hub: " + "<br /> Hub: ".join( ["<a href='{1}'>{0}</a>".format(*x) for x in csv_links.items()])) resources = INLINE js_resources = resources.render_js() css_resources = resources.render_css() html = template.render(js_resources=js_resources, css_resources=css_resources, plot_script=script, plot_div=div, download=download, timeplot=timeplot) #filename = 'embed_multiple_responsive.html' #with open(filename, 'w') as f: # f.write(html) #pdb.set_trace() response = (html) return response
) es.add( custom.ElectricalLine( input=b_el2, output=b_el0, reactance=0.0001, nominal_value=60, min=-1, max=1, ) ) es.add( Source( label="gen_0", outputs={b_el0: Flow(nominal_value=100, variable_costs=50)}, ) ) es.add( Source( label="gen_1", outputs={b_el1: Flow(nominal_value=100, variable_costs=25)}, ) ) es.add(Sink(label="load", inputs={b_el2: Flow(nominal_value=100, fix=[1, 1])})) m = Model(energysystem=es) # m.write('lopf.lp', io_options={'symbolic_solver_labels': True})
data = pd.read_csv(filename, sep=";", decimal=',') data = data.dropna(axis=1) print(data.head()) # ## Create Buses # resource buses bus_gas = Bus(label='gas') bus_coal = Bus(label='coal') # electricity and heat buses bus_el = Bus(label='electricity') bus_th = Bus(label='heat') # ## Create components source_gas = Source(label='source_gas', outputs={bus_gas: Flow(variable_costs=30)}) source_coal = Source(label='source_coal', outputs={bus_coal: Flow(variable_costs=30)}) # Renewable feedin wind = Source(label='wind', outputs={ bus_el: Flow(actual_value=data['wind'], nominal_value=66.3, fixed=True) }) pv = Source(label='pv', outputs={ bus_el:
# Creating the necessary buses elbus = Bus(label='electricity') thbus = Bus(label='thermal') logging.info('Necessary buses for the system created') # Now creating the necessary components for the system epc_pv = economics.annuity(capex=1000, n=20, wacc=0.05) epc_storage = economics.annuity(capex=100, n=5, wacc=0.05) pv = Source(label='pv', outputs={ elbus: Flow(actual_value=data['pv'], nominal_value=None, fixed=True, investment=Investment(ep_costs=epc_pv, maximum=30)) }) demand_el = Sink(label='demand_el', inputs={ elbus: Flow(nominal_value=1, actual_value=data['demand_el'], fixed=True) }) demand_th = Sink(label='demand_th', inputs={ thbus: Flow(nominal_value=1,
full_filename = os.path.join(os.path.dirname(__file__), 'data.csv') data = pd.read_csv(full_filename, sep=";") # select total_time_steps total_time_steps = 24 * 7 # create an energy system idx = pd.date_range('1/1/2017', periods=total_time_steps, freq='H') start = time() es = EnergySystem(timeindex=idx) Node.registry = es # resources bgas = Bus(label='bgas') rgas = Source(label='rgas', outputs={bgas: Flow()}) # heat bth = Bus(label='bth') # dummy source at high costs that serves the residual load source_th = Source(label='source_th', outputs={bth: Flow(variable_costs=1000)}) demand_th = Sink(label='demand_th', inputs={ bth: Flow(fixed=True, actual_value=data['demand_th'], nominal_value=200) })
energysystem = EnergySystem(timeindex=datetimeindex) # load data filename = '' data = pd.read_csv(filename, sep=';', decimal=',') print(data.head()) # create buses bus_coal = Bus(label='coal', balanced=False) bus_gas = Bus(label='gas', balanced=False) bus_el = Bus(label='electricity') # create sources wind = Source(label='wind', outputs={ bus_el: Flow(actual_value=data['wind'], nominal_value=1, fixed=True) }) pv = Source(label='pv', outputs={ bus_el: Flow(actual_value=data['pv'], nominal_value=1, fixed=True) }) # create excess and shortage to avoid infeasibilies excess = Sink(label='excess_el', inputs={bus_el: Flow()}) shortage = Source(label='shortage_el', outputs={bus_el: Flow(variable_costs=1e12)})
'epc': economics.annuity(capex=1500, n=10, wacc=0.05), 'var': 0 } } ################################################################# # Create oemof object ################################################################# bel = Bus(label='micro_grid') Sink(label='excess', inputs={bel: Flow(variable_costs=10e3)}) Source(label='pp_wind', outputs={ bel: Flow(nominal_value=None, fixed=True, actual_value=timeseries['wind'], investment=Investment(ep_costs=costs['pp_wind']['epc'])) }) Source(label='pp_pv', outputs={ bel: Flow(nominal_value=None, fixed=True, actual_value=timeseries['pv'], investment=Investment(ep_costs=costs['pp_wind']['epc'])) }) Source(label='pp_diesel', outputs={
filename = 'data_timeseries.csv' data = pd.read_csv(filename, sep=",") logging.info('Energy system created and initialized') # Creating the necessary buses elbus = Bus(label='electricity') gasbus = Bus(label='gas') thbus = Bus(label='heat') logging.info('Necessary buses for the system created') # Now creating the necessary components for the system gas = Source(label='gas_com', outputs={gasbus: Flow()}) pv = Source(label='pv', outputs={elbus: Flow(nominal_value=65, fixed=True, actual_value=data['pv'])}) chp_gas = Transformer(label='chp_gas', inputs={gasbus: Flow()}, outputs={elbus: Flow(nominal_value=55), thbus: Flow(nominal_value=55)}, conversion_factors={elbus: 0.3, thbus: 0.4}) el_storage = GenericStorage(label='el_storage', nominal_storage_capacity=1000, inputs={elbus: Flow(nominal_value=9)}, outputs={elbus: Flow(nominal_value=9)}, loss_rate=0.01, initial_storage_level=0, max_storage_level=0.9,
def diesel_only(mode, feedin, initial_batt_cap, cost, iterstatus=None, PV_source=True, storage_source=True, logger=False): if logger == 1: logger.define_logging() ##################################### Initialize the energy system################################################## # times = pd.DatetimeIndex(start='04/01/2017', periods=10, freq='H') times = feedin.index energysystem = EnergySystem(timeindex=times) # switch on automatic registration of entities of EnergySystem-object=energysystem Node.registry = energysystem # add components b_el = Bus(label='electricity') b_dc = Bus(label='electricity_dc') b_oil = Bus(label='diesel_source') demand_feedin = feedin['demand_el'] Sink(label='demand', inputs={ b_el: Flow(actual_value=demand_feedin, nominal_value=1, fixed=True) }) Sink(label='excess', inputs={b_el: Flow()}) Source(label='diesel', outputs={b_oil: Flow()}) generator1 = custom.DieselGenerator( label='pp_oil_1', fuel_input={b_oil: Flow(variable_costs=cost['pp_oil_1']['var'])}, electrical_output={ b_el: Flow(nominal_value=186, min=0.3, max=1, nonconvex=NonConvex(om_costs=cost['pp_oil_1']['o&m']), fixed_costs=cost['pp_oil_1']['fix']) }, fuel_curve={ '1': 42, '0.75': 33, '0.5': 22, '0.25': 16 }) generator2 = custom.DieselGenerator( label='pp_oil_2', fuel_input={b_oil: Flow(variable_costs=cost['pp_oil_2']['var'])}, electrical_output={ b_el: Flow(nominal_value=186, min=0.3, max=1, nonconvex=NonConvex(om_costs=cost['pp_oil_2']['o&m']), fixed_costs=cost['pp_oil_2']['fix'], variable_costs=0) }, fuel_curve={ '1': 42, '0.75': 33, '0.5': 22, '0.25': 16 }) generator3 = custom.DieselGenerator( label='pp_oil_3', fuel_input={b_oil: Flow(variable_costs=cost['pp_oil_3']['var'])}, electrical_output={ b_el: Flow(nominal_value=320, min=0.3, max=1, nonconvex=NonConvex(om_costs=cost['pp_oil_3']['o&m']), fixed_costs=cost['pp_oil_3']['fix'], variable_costs=0) }, fuel_curve={ '1': 73, '0.75': 57, '0.5': 38, '0.25': 27 }) # List all generators in a list called gen_set gen_set = [generator1, generator2, generator3] sim_params = get_sim_params(cost) if mode == 'simulation': nominal_cap_pv = sim_params['pv']['nominal_capacity'] inv_pv = None nominal_cap_batt = sim_params['storage']['nominal_capacity'] inv_batt = None elif mode == 'investment': nominal_cap_pv = None inv_pv = sim_params['pv']['investment'] nominal_cap_batt = None inv_batt = sim_params['storage']['investment'] else: raise ( UserWarning, 'Energysystem cant be build. Check if mode is spelled correctely. ' 'It can be either [simulation] or [investment]') if PV_source == 1: PV = Source(label='PV', outputs={ b_dc: Flow(nominal_value=nominal_cap_pv, fixed_costs=cost['pv']['fix'], actual_value=feedin['PV'], fixed=True, investment=inv_pv) }) else: PV = None if storage_source == 1: storage = components.GenericStorage( label='storage', inputs={b_dc: Flow()}, outputs={ b_dc: Flow(variable_costs=cost['storage']['var'], fixed_costs=cost['storage']['fix']) }, nominal_capacity=nominal_cap_batt, capacity_loss=0.00, initial_capacity=initial_batt_cap, nominal_input_capacity_ratio=0.546, nominal_output_capacity_ratio=0.546, inflow_conversion_factor=0.92, outflow_conversion_factor=0.92, capacity_min=0.5, capacity_max=1, investment=inv_batt, initial_iteration=iterstatus) else: storage = None if storage_source == 1 or PV_source == 1: inverter1 = add_inverter(b_dc, b_el, 'Inv_pv') ################################# optimization ############################ # create Optimization model based on energy_system logging.info("Create optimization problem") m = Model(energysystem) ################################# constraints ############################ sr_requirement = 0.2 sr_limit = demand_feedin * sr_requirement rm_requirement = 0.4 rm_limit = demand_feedin * rm_requirement constraints.spinning_reserve_constraint(m, sr_limit, groups=gen_set, storage=storage) # constraints.n1_constraint(m, demand_feedin, groups=gen_set) constraints.gen_order_constraint(m, groups=gen_set) constraints.rotating_mass_constraint(m, rm_limit, groups=gen_set, storage=storage) return [m, gen_set]
# electricity and heat bel = Bus(label='bel') bth = Bus(label='bth') energysystem.add(bcoal, bgas, boil, blig, bel, bth) # an excess and a shortage variable can help to avoid infeasible problems energysystem.add(Sink(label='excess_el', inputs={bel: Flow()})) # shortage_el = Source(label='shortage_el', # outputs={bel: Flow(variable_costs=200)}) # sources energysystem.add( Source(label='wind', outputs={ bel: Flow(actual_value=data['wind'], nominal_value=66.3, fixed=True) })) energysystem.add( Source(label='pv', outputs={ bel: Flow(actual_value=data['pv'], nominal_value=65.3, fixed=True) })) # demands (electricity/heat) energysystem.add( Sink(label='demand_el', inputs={
def simulate(energysystem, filename=None, solver='cbc', tee_switch=True, keep=True): """ """ if filename is None: filename = os.path.join(os.path.dirname(__file__), 'input_data.csv') logging.info("Creating objects") data = pd.read_csv(filename, sep=",") # resource buses bcoal = Bus(label="coal", balanced=False) bgas = Bus(label="gas", balanced=False) boil = Bus(label="oil", balanced=False) blig = Bus(label="lignite", balanced=False) # electricity and heat b_el = Bus(label="b_el") b_th = Bus(label="b_th") # adding an excess variable can help to avoid infeasible problems Sink(label="excess", inputs={b_el: Flow()}) # adding an excess variable can help to avoid infeasible problems # Source(label="shortage", outputs={b_el: Flow(variable_costs=200)}) # Sources Source(label="wind", outputs={ b_el: Flow(actual_value=data['wind'], nominal_value=66.3, fixed=True) }) Source(label="pv", outputs={ b_el: Flow(actual_value=data['pv'], nominal_value=65.3, fixed=True) }) # Demands (electricity/heat) Sink(label="demand_el", inputs={ b_el: Flow(nominal_value=85, actual_value=data['demand_el'], fixed=True) }) Sink(label="demand_th", inputs={ b_th: Flow(nominal_value=40, actual_value=data['demand_th'], fixed=True) }) # Power plants LinearTransformer( label='pp_coal', inputs={bcoal: Flow()}, outputs={b_el: Flow(nominal_value=20.2, variable_costs=25)}, conversion_factors={b_el: 0.39}) LinearTransformer( label='pp_lig', inputs={blig: Flow()}, outputs={b_el: Flow(nominal_value=11.8, variable_costs=19)}, conversion_factors={b_el: 0.41}) LinearTransformer( label='pp_gas', inputs={bgas: Flow()}, outputs={b_el: Flow(nominal_value=41, variable_costs=40)}, conversion_factors={b_el: 0.50}) LinearTransformer(label='pp_oil', inputs={boil: Flow()}, outputs={b_el: Flow(nominal_value=5, variable_costs=50)}, conversion_factors={b_el: 0.28}) # CHP LinearTransformer(label='pp_chp', inputs={bgas: Flow()}, outputs={ b_el: Flow(nominal_value=30, variable_costs=42), b_th: Flow(nominal_value=40) }, conversion_factors={ b_el: 0.3, b_th: 0.4 }) # Heatpump with a coefficient of performance (COP) of 3 b_heat_source = Bus(label="b_heat_source") Source(label="heat_source", outputs={b_heat_source: Flow()}) cop = 3 LinearN1Transformer(label='heat_pump', inputs={ b_el: Flow(), b_heat_source: Flow() }, outputs={b_th: Flow(nominal_value=10)}, conversion_factors={ b_el: cop, b_heat_source: cop / (cop - 1) }) # ################################ optimization ############################### # create Optimization model based on energy_system logging.info("Create optimization problem") om = OperationalModel(es=energysystem) # solve with specific optimization options (passed to pyomo) logging.info("Solve optimization problem") om.solve(solver=solver, solve_kwargs={ 'tee': tee_switch, 'keepfiles': keep }) # write back results from optimization object to energysystem om.results() return om
def test_dispatch_one_time_step(solver='cbc', periods=1): """Create an energy system and optimize the dispatch at least costs.""" # ######################### create energysystem components ################ Node.registry = None # resource buses bgas = Bus(label='gas', balanced=False) # electricity and heat bel = Bus(label='b_el') bth = Bus(label='b_th') # an excess and a shortage variable can help to avoid infeasible problems excess_el = Sink(label='excess_el', inputs={bel: Flow()}) # sources wind = Source( label='wind', outputs={bel: Flow(actual_value=0.5, nominal_value=66.3, fixed=True)}) # demands (electricity/heat) demand_el = Sink( label='demand_elec', inputs={bel: Flow(nominal_value=85, actual_value=0.3, fixed=True)}) demand_th = Sink( label='demand_therm', inputs={bth: Flow(nominal_value=40, actual_value=0.2, fixed=True)}) # combined heat and power plant (chp) pp_chp = Transformer(label='pp_chp', inputs={bgas: Flow()}, outputs={ bel: Flow(nominal_value=30, variable_costs=42), bth: Flow(nominal_value=40) }, conversion_factors={ bel: 0.3, bth: 0.4 }) # heatpump with a coefficient of performance (COP) of 3 b_heat_source = Bus(label='b_heat_source') heat_source = Source(label='heat_source', outputs={b_heat_source: Flow()}) cop = 3 heat_pump = Transformer(label='heat_pump', inputs={ bel: Flow(), b_heat_source: Flow() }, outputs={bth: Flow(nominal_value=10)}, conversion_factors={ bel: 1 / 3, b_heat_source: (cop - 1) / cop }) energysystem = EnergySystem(timeindex=[1]) energysystem.add(bgas, bel, bth, excess_el, wind, demand_el, demand_th, pp_chp, b_heat_source, heat_source, heat_pump) # ################################ optimization ########################### # create optimization model based on energy_system optimization_model = Model(energysystem=energysystem, timeincrement=1) # solve problem optimization_model.solve(solver=solver) # write back results from optimization object to energysystem optimization_model.results() # ################################ results ################################ data = views.node(processing.results(om=optimization_model), 'b_el') # generate results to be evaluated in tests results = data['sequences'].sum(axis=0).to_dict() test_results = { (('wind', 'b_el'), 'flow'): 33, (('b_el', 'demand_elec'), 'flow'): 26, (('b_el', 'excess_el'), 'flow'): 5, (('b_el', 'heat_pump'), 'flow'): 3, } for key in test_results.keys(): eq_(int(round(results[key])), int(round(test_results[key])))
def test_dispatch_example(solver='cbc', periods=24*5): """Create an energy system and optimize the dispatch at least costs.""" Node.registry = None filename = os.path.join(os.path.dirname(__file__), 'input_data.csv') data = pd.read_csv(filename, sep=",") # ######################### create energysystem components ################ # resource buses bcoal = Bus(label='coal', balanced=False) bgas = Bus(label='gas', balanced=False) boil = Bus(label='oil', balanced=False) blig = Bus(label='lignite', balanced=False) # electricity and heat bel = Bus(label='b_el') bth = Bus(label='b_th') # an excess and a shortage variable can help to avoid infeasible problems excess_el = Sink(label='excess_el', inputs={bel: Flow()}) # shortage_el = Source(label='shortage_el', # outputs={bel: Flow(variable_costs=200)}) # sources ep_wind = economics.annuity(capex=1000, n=20, wacc=0.05) wind = Source(label='wind', outputs={bel: Flow( fix=data['wind'], investment=Investment(ep_costs=ep_wind, existing=100))}) ep_pv = economics.annuity(capex=1500, n=20, wacc=0.05) pv = Source(label='pv', outputs={bel: Flow( fix=data['pv'], investment=Investment(ep_costs=ep_pv, existing=80))}) # demands (electricity/heat) demand_el = Sink(label='demand_elec', inputs={bel: Flow(nominal_value=85, fix=data['demand_el'])}) demand_th = Sink(label='demand_therm', inputs={bth: Flow(nominal_value=40, fix=data['demand_th'])}) # power plants pp_coal = Transformer(label='pp_coal', inputs={bcoal: Flow()}, outputs={bel: Flow(nominal_value=20.2, variable_costs=25)}, conversion_factors={bel: 0.39}) pp_lig = Transformer(label='pp_lig', inputs={blig: Flow()}, outputs={bel: Flow(nominal_value=11.8, variable_costs=19)}, conversion_factors={bel: 0.41}) pp_gas = Transformer(label='pp_gas', inputs={bgas: Flow()}, outputs={bel: Flow(nominal_value=41, variable_costs=40)}, conversion_factors={bel: 0.50}) pp_oil = Transformer(label='pp_oil', inputs={boil: Flow()}, outputs={bel: Flow(nominal_value=5, variable_costs=50)}, conversion_factors={bel: 0.28}) # combined heat and power plant (chp) pp_chp = Transformer(label='pp_chp', inputs={bgas: Flow()}, outputs={bel: Flow(nominal_value=30, variable_costs=42), bth: Flow(nominal_value=40)}, conversion_factors={bel: 0.3, bth: 0.4}) # heatpump with a coefficient of performance (COP) of 3 b_heat_source = Bus(label='b_heat_source') heat_source = Source(label='heat_source', outputs={b_heat_source: Flow()}) cop = 3 heat_pump = Transformer(label='el_heat_pump', inputs={bel: Flow(), b_heat_source: Flow()}, outputs={bth: Flow(nominal_value=10)}, conversion_factors={ bel: 1/3, b_heat_source: (cop-1)/cop}) datetimeindex = pd.date_range('1/1/2012', periods=periods, freq='H') energysystem = EnergySystem(timeindex=datetimeindex) energysystem.add(bcoal, bgas, boil, bel, bth, blig, excess_el, wind, pv, demand_el, demand_th, pp_coal, pp_lig, pp_oil, pp_gas, pp_chp, b_heat_source, heat_source, heat_pump) # ################################ optimization ########################### # create optimization model based on energy_system optimization_model = Model(energysystem=energysystem) # solve problem optimization_model.solve(solver=solver) # write back results from optimization object to energysystem optimization_model.results() # ################################ results ################################ # generic result object results = processing.results(om=optimization_model) # subset of results that includes all flows into and from electrical bus # sequences are stored within a pandas.DataFrames and scalars e.g. # investment values within a pandas.Series object. # in this case the entry data['scalars'] does not exist since no investment # variables are used data = views.node(results, 'b_el') # generate results to be evaluated in tests comp_results = data['sequences'].sum(axis=0).to_dict() comp_results['pv_capacity'] = results[(pv, bel)]['scalars'].invest comp_results['wind_capacity'] = results[(wind, bel)]['scalars'].invest test_results = { (('wind', 'b_el'), 'flow'): 9239, (('pv', 'b_el'), 'flow'): 1147, (('b_el', 'demand_elec'), 'flow'): 7440, (('b_el', 'excess_el'), 'flow'): 6261, (('pp_chp', 'b_el'), 'flow'): 477, (('pp_lig', 'b_el'), 'flow'): 850, (('pp_gas', 'b_el'), 'flow'): 934, (('pp_coal', 'b_el'), 'flow'): 1256, (('pp_oil', 'b_el'), 'flow'): 0, (('b_el', 'el_heat_pump'), 'flow'): 202, 'pv_capacity': 44, 'wind_capacity': 246, } for key in test_results.keys(): eq_(int(round(comp_results[key])), int(round(test_results[key])))
b_1 = Bus(label='b_1') es.add(b_0, b_1) es.add(custom.Link(label="line_0", inputs={ b_0: Flow(), b_1: Flow()}, outputs={ b_1: Flow(investment=Investment()), b_0: Flow(investment=Investment())}, conversion_factors={ (b_0, b_1): 0.95, (b_1, b_0): 0.9})) es.add(Source(label="gen_0", outputs={ b_0: Flow(nominal_value=100, variable_costs=50)})) es.add(Source(label="gen_1", outputs={ b_1: Flow(nominal_value=100, variable_costs=50)})) es.add(Sink(label="load_0", inputs={ b_0: Flow(nominal_value=150, actual_value=[0, 1], fixed=True)})) es.add(Sink(label="load_1", inputs={ b_1: Flow(nominal_value=150, actual_value=[1, 0], fixed=True)}))
solver = 'cbc' # set timeindex and create data periods = 20 datetimeindex = pd.date_range('1/1/2019', periods=periods, freq='H') step = 5 demand = np.arange(0, step * periods, step) # set up EnergySystem energysystem = EnergySystem(timeindex=datetimeindex) b_gas = Bus(label='gas', balanced=False) b_el = Bus(label='electricity') energysystem.add(b_gas, b_el) energysystem.add( Source(label='shortage', outputs={b_el: Flow(variable_costs=1e6)})) energysystem.add( Sink(label='demand', inputs={b_el: Flow(nominal_value=1, actual_value=demand, fixed=True)})) conv_func = lambda x: 0.01 * x**2 in_breakpoints = np.arange(0, 110, 25) pwltf = solph.custom.PiecewiseLinearTransformer( label='pwltf', inputs={b_gas: solph.Flow(nominal_value=100, variable_costs=1)}, outputs={b_el: solph.Flow()}, in_breakpoints=in_breakpoints, conversion_function=conv_func, pw_repn='CC') # 'CC', 'DCC', 'INC', 'MC'
# ######################### create energysystem components ################ # resource buses bcoal = Bus(label="coal", balanced=False) bgas = Bus(label="gas", balanced=False) boil = Bus(label="oil", balanced=False) # electricity and heat bel = Bus(label="bel") energysystem.add(bcoal, bgas, boil, bel) # an excess and a shortage variable can help to avoid infeasible problems energysystem.add(Sink(label="excess_el", inputs={bel: Flow()})) shortage_el = Source(label='shortage_el', outputs={bel: Flow(variable_costs=20000)}, conversion_factors={bel: 0.33}) energysystem.add(shortage_el) # sources energysystem.add( Source(label="pv", outputs={bel: Flow(fix=data["pv"], nominal_value=256e3)})) # demands (electricity/heat) energysystem.add( Sink( label="demand_el", inputs={bel: Flow(nominal_value=1e3, fix=data["demand_el"])}, ))