From e27ebca3069de126ce36c254e4213f123352c987 Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Tue, 6 Feb 2018 16:43:04 +0100 Subject: [PATCH 1/8] Provide basic example --- .../oemof_0.2/gradients_and_runtimes/data.csv | 201 ++++++++++++++++++ .../gradients_and_runtimes.py | 85 ++++++++ 2 files changed, 286 insertions(+) create mode 100644 examples/oemof_0.2/gradients_and_runtimes/data.csv create mode 100644 examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py diff --git a/examples/oemof_0.2/gradients_and_runtimes/data.csv b/examples/oemof_0.2/gradients_and_runtimes/data.csv new file mode 100644 index 0000000..bcae776 --- /dev/null +++ b/examples/oemof_0.2/gradients_and_runtimes/data.csv @@ -0,0 +1,201 @@ +timestep,demand_th,price_el +1,0.01,50 +2,0.02,50 +3,0.03,50 +4,0.04,50 +5,0.05,50 +6,0.06,50 +7,0.07,50 +8,0.08,50 +9,0.09,50 +10,0.1,50 +11,0.11,50 +12,0.12,50 +13,0.13,50 +14,0.14,50 +15,0.15,50 +16,0.16,50 +17,0.17,50 +18,0.18,50 +19,0.19,50 +20,0.2,50 +21,0.21,50 +22,0.22,50 +23,0.23,50 +24,0.24,50 +25,0.25,50 +26,0.26,50 +27,0.27,50 +28,0.28,50 +29,0.29,50 +30,0.3,50 +31,0.31,50 +32,0.32,50 +33,0.33,50 +34,0.34,50 +35,0.35,50 +36,0.36,50 +37,0.37,50 +38,0.38,50 +39,0.39,50 +40,0.4,50 +41,0.41,50 +42,0.42,50 +43,0.43,50 +44,0.44,50 +45,0.45,50 +46,0.46,50 +47,0.47,50 +48,0.48,50 +49,0.49,50 +50,0.5,50 +51,0.51,50 +52,0.52,50 +53,0.53,50 +54,0.54,50 +55,0.55,50 +56,0.56,50 +57,0.57,50 +58,0.58,50 +59,0.59,50 +60,0.6,50 +61,0.61,50 +62,0.62,50 +63,0.63,50 +64,0.64,50 +65,0.65,50 +66,0.66,50 +67,0.67,50 +68,0.68,50 +69,0.69,50 +70,0.7,50 +71,0.71,50 +72,0.72,50 +73,0.73,50 +74,0.74,50 +75,0.75,50 +76,0.76,50 +77,0.77,50 +78,0.78,50 +79,0.79,50 +80,0.8,50 +81,0.81,50 +82,0.82,50 +83,0.83,50 +84,0.84,50 +85,0.85,50 +86,0.86,50 +87,0.87,50 +88,0.88,50 +89,0.89,50 +90,0.9,50 +91,0.91,50 +92,0.92,50 +93,0.93,50 +94,0.94,50 +95,0.95,50 +96,0.96,50 +97,0.97,50 +98,0.98,50 +99,0.99,50 +100,1,50 +101,0.01,-50 +102,0.02,-50 +103,0.03,-50 +104,0.04,-50 +105,0.05,-50 +106,0.06,-50 +107,0.07,-50 +108,0.08,-50 +109,0.09,-50 +110,0.1,-50 +111,0.11,-50 +112,0.12,-50 +113,0.13,-50 +114,0.14,-50 +115,0.15,-50 +116,0.16,-50 +117,0.17,-50 +118,0.18,-50 +119,0.19,-50 +120,0.2,-50 +121,0.21,-50 +122,0.22,-50 +123,0.23,-50 +124,0.24,-50 +125,0.25,-50 +126,0.26,-50 +127,0.27,-50 +128,0.28,-50 +129,0.29,-50 +130,0.3,-50 +131,0.31,-50 +132,0.32,-50 +133,0.33,-50 +134,0.34,-50 +135,0.35,-50 +136,0.36,-50 +137,0.37,-50 +138,0.38,-50 +139,0.39,-50 +140,0.4,-50 +141,0.41,-50 +142,0.42,-50 +143,0.43,-50 +144,0.44,-50 +145,0.45,-50 +146,0.46,-50 +147,0.47,-50 +148,0.48,-50 +149,0.49,-50 +150,0.5,-50 +151,0.51,-50 +152,0.52,-50 +153,0.53,-50 +154,0.54,-50 +155,0.55,-50 +156,0.56,-50 +157,0.57,-50 +158,0.58,-50 +159,0.59,-50 +160,0.6,-50 +161,0.61,-50 +162,0.62,-50 +163,0.63,-50 +164,0.64,-50 +165,0.65,-50 +166,0.66,-50 +167,0.67,-50 +168,0.68,-50 +169,0.69,-50 +170,0.7,-50 +171,0.71,-50 +172,0.72,-50 +173,0.73,-50 +174,0.74,-50 +175,0.75,-50 +176,0.76,-50 +177,0.77,-50 +178,0.78,-50 +179,0.79,-50 +180,0.8,-50 +181,0.81,-50 +182,0.82,-50 +183,0.83,-50 +184,0.84,-50 +185,0.85,-50 +186,0.86,-50 +187,0.87,-50 +188,0.88,-50 +189,0.89,-50 +190,0.9,-50 +191,0.91,-50 +192,0.92,-50 +193,0.93,-50 +194,0.94,-50 +195,0.95,-50 +196,0.96,-50 +197,0.97,-50 +198,0.98,-50 +199,0.99,-50 +200,1,-50 diff --git a/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py b/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py new file mode 100644 index 0000000..de3dc5f --- /dev/null +++ b/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +""" +General description +------------------- +Example that illustrates how to use custom component `GenericCHP` can be used. +In this case it is used to model a back pressure turbine. + +Installation requirements +------------------------- +This example requires the latest version of oemof. Install by: + + pip install oemof + +""" + +import pandas as pd +import oemof.solph as solph +from oemof.network import Node +from oemof.outputlib import processing, views +try: + import matplotlib.pyplot as plt +except ImportError: + plt = None + + +# read sequence data +file_name = 'data' +data = pd.read_csv(file_name + '.csv', sep=",") + +# select periods +periods = len(data)-1 + +# create an energy system +idx = pd.date_range('1/1/2017', periods=periods, freq='H') +es = solph.EnergySystem(timeindex=idx) +Node.registry = es + +# resources +bgas = solph.Bus(label='bgas') + +rgas = solph.Source(label='rgas', outputs={bgas: solph.Flow()}) + +# heat +bth = solph.Bus(label='bth') + +# dummy source at high costs that serves the residual load +source_th = solph.Source(label='source_th', + outputs={bth: solph.Flow(variable_costs=100)}) + +demand_th = solph.Sink(label='demand_th', inputs={bth: solph.Flow(fixed=True, + actual_value=data['demand_th'], nominal_value=200)}) + +# power +bel = solph.Bus(label='bel') + +demand_el = solph.Sink(label='demand_el', inputs={bel: solph.Flow( + variable_costs=data['price_el'])}) + +powerplant = solph.Transformer( + label='pp_gas', + inputs={bgas: solph.Flow()}, + outputs={bel: solph.Flow(nominal_value=100), + bth: solph.Flow(nominal_value=100)}, + conversion_factors={bel: 0.3, bth: 0.5}) + +# create an optimization problem and solve it +om = solph.Model(es) + +# debugging +# om.write('generic_chp.lp', io_options={'symbolic_solver_labels': True}) + +# solve model +om.solve(solver='cbc', solve_kwargs={'tee': True}) + +# create result object +results = processing.results(om) + +# plot data +if plt is not None: + # plot thermal bus + data = views.node(results, 'bth')['sequences'] + ax = data.plot(kind='line', drawstyle='steps-post', grid=True) + ax.set_xlabel('Time (h)') + ax.set_ylabel('Q (MW)') + plt.show() From e43d06dbf7b5606ecb07787ee25ed445e9b2537e Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Tue, 6 Feb 2018 17:06:59 +0100 Subject: [PATCH 2/8] Extend basic example --- .../oemof_0.2/gradients_and_runtimes/data.csv | 226 ++---------------- .../gradients_and_runtimes.py | 24 +- 2 files changed, 40 insertions(+), 210 deletions(-) diff --git a/examples/oemof_0.2/gradients_and_runtimes/data.csv b/examples/oemof_0.2/gradients_and_runtimes/data.csv index bcae776..039a144 100644 --- a/examples/oemof_0.2/gradients_and_runtimes/data.csv +++ b/examples/oemof_0.2/gradients_and_runtimes/data.csv @@ -1,201 +1,25 @@ -timestep,demand_th,price_el -1,0.01,50 -2,0.02,50 -3,0.03,50 -4,0.04,50 -5,0.05,50 -6,0.06,50 -7,0.07,50 -8,0.08,50 -9,0.09,50 -10,0.1,50 -11,0.11,50 -12,0.12,50 -13,0.13,50 -14,0.14,50 -15,0.15,50 -16,0.16,50 -17,0.17,50 -18,0.18,50 -19,0.19,50 -20,0.2,50 -21,0.21,50 -22,0.22,50 -23,0.23,50 -24,0.24,50 -25,0.25,50 -26,0.26,50 -27,0.27,50 -28,0.28,50 -29,0.29,50 -30,0.3,50 -31,0.31,50 -32,0.32,50 -33,0.33,50 -34,0.34,50 -35,0.35,50 -36,0.36,50 -37,0.37,50 -38,0.38,50 -39,0.39,50 -40,0.4,50 -41,0.41,50 -42,0.42,50 -43,0.43,50 -44,0.44,50 -45,0.45,50 -46,0.46,50 -47,0.47,50 -48,0.48,50 -49,0.49,50 -50,0.5,50 -51,0.51,50 -52,0.52,50 -53,0.53,50 -54,0.54,50 -55,0.55,50 -56,0.56,50 -57,0.57,50 -58,0.58,50 -59,0.59,50 -60,0.6,50 -61,0.61,50 -62,0.62,50 -63,0.63,50 -64,0.64,50 -65,0.65,50 -66,0.66,50 -67,0.67,50 -68,0.68,50 -69,0.69,50 -70,0.7,50 -71,0.71,50 -72,0.72,50 -73,0.73,50 -74,0.74,50 -75,0.75,50 -76,0.76,50 -77,0.77,50 -78,0.78,50 -79,0.79,50 -80,0.8,50 -81,0.81,50 -82,0.82,50 -83,0.83,50 -84,0.84,50 -85,0.85,50 -86,0.86,50 -87,0.87,50 -88,0.88,50 -89,0.89,50 -90,0.9,50 -91,0.91,50 -92,0.92,50 -93,0.93,50 -94,0.94,50 -95,0.95,50 -96,0.96,50 -97,0.97,50 -98,0.98,50 -99,0.99,50 -100,1,50 -101,0.01,-50 -102,0.02,-50 -103,0.03,-50 -104,0.04,-50 -105,0.05,-50 -106,0.06,-50 -107,0.07,-50 -108,0.08,-50 -109,0.09,-50 -110,0.1,-50 -111,0.11,-50 -112,0.12,-50 -113,0.13,-50 -114,0.14,-50 -115,0.15,-50 -116,0.16,-50 -117,0.17,-50 -118,0.18,-50 -119,0.19,-50 -120,0.2,-50 -121,0.21,-50 -122,0.22,-50 -123,0.23,-50 -124,0.24,-50 -125,0.25,-50 -126,0.26,-50 -127,0.27,-50 -128,0.28,-50 -129,0.29,-50 -130,0.3,-50 -131,0.31,-50 -132,0.32,-50 -133,0.33,-50 -134,0.34,-50 -135,0.35,-50 -136,0.36,-50 -137,0.37,-50 -138,0.38,-50 -139,0.39,-50 -140,0.4,-50 -141,0.41,-50 -142,0.42,-50 -143,0.43,-50 -144,0.44,-50 -145,0.45,-50 -146,0.46,-50 -147,0.47,-50 -148,0.48,-50 -149,0.49,-50 -150,0.5,-50 -151,0.51,-50 -152,0.52,-50 -153,0.53,-50 -154,0.54,-50 -155,0.55,-50 -156,0.56,-50 -157,0.57,-50 -158,0.58,-50 -159,0.59,-50 -160,0.6,-50 -161,0.61,-50 -162,0.62,-50 -163,0.63,-50 -164,0.64,-50 -165,0.65,-50 -166,0.66,-50 -167,0.67,-50 -168,0.68,-50 -169,0.69,-50 -170,0.7,-50 -171,0.71,-50 -172,0.72,-50 -173,0.73,-50 -174,0.74,-50 -175,0.75,-50 -176,0.76,-50 -177,0.77,-50 -178,0.78,-50 -179,0.79,-50 -180,0.8,-50 -181,0.81,-50 -182,0.82,-50 -183,0.83,-50 -184,0.84,-50 -185,0.85,-50 -186,0.86,-50 -187,0.87,-50 -188,0.88,-50 -189,0.89,-50 -190,0.9,-50 -191,0.91,-50 -192,0.92,-50 -193,0.93,-50 -194,0.94,-50 -195,0.95,-50 -196,0.96,-50 -197,0.97,-50 -198,0.98,-50 -199,0.99,-50 -200,1,-50 +timestep,demand_th +1,0 +2,0 +3,0 +4,0 +5,1 +6,1 +7,1 +8,1 +9,0 +10,0 +11,0 +12,0 +13,1 +14,1 +15,1 +16,1 +17,0 +18,0 +19,0 +20,0 +21,1 +22,1 +23,1 +24,1 diff --git a/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py b/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py index de3dc5f..605a181 100644 --- a/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py +++ b/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py @@ -45,23 +45,28 @@ # dummy source at high costs that serves the residual load source_th = solph.Source(label='source_th', - outputs={bth: solph.Flow(variable_costs=100)}) + outputs={bth: solph.Flow(variable_costs=10)}) demand_th = solph.Sink(label='demand_th', inputs={bth: solph.Flow(fixed=True, - actual_value=data['demand_th'], nominal_value=200)}) + actual_value=data['demand_th'], nominal_value=100)}) # power bel = solph.Bus(label='bel') -demand_el = solph.Sink(label='demand_el', inputs={bel: solph.Flow( - variable_costs=data['price_el'])}) +demand_el = solph.Sink(label='demand_el', inputs={bel: solph.Flow()}) powerplant = solph.Transformer( label='pp_gas', inputs={bgas: solph.Flow()}, - outputs={bel: solph.Flow(nominal_value=100), - bth: solph.Flow(nominal_value=100)}, - conversion_factors={bel: 0.3, bth: 0.5}) + outputs={ + bel: solph.Flow(nominal_value=50), + bth: solph.Flow( + nominal_value=50, + min=0, max=1.0, + startup_costs=1000, shutdown_costs=0, + nonconvex=solph.NonConvex() + )}, + conversion_factors={bel: 0.5, bth: 0.5}) # create an optimization problem and solve it om = solph.Model(es) @@ -79,7 +84,8 @@ if plt is not None: # plot thermal bus data = views.node(results, 'bth')['sequences'] - ax = data.plot(kind='line', drawstyle='steps-post', grid=True) - ax.set_xlabel('Time (h)') + data.index = data.index.map(lambda t: t.strftime('%H')) + ax = data.plot(kind='bar', grid=True, rot=0) + ax.set_xlabel('Hour') ax.set_ylabel('Q (MW)') plt.show() From 13319678035e197b1e96d2a0c45ef1d04c226599 Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Wed, 7 Feb 2018 11:16:42 +0100 Subject: [PATCH 3/8] Finish startup and shutdown example --- .../oemof_0.2/gradients_and_runtimes/data.csv | 26 +++--- .../gradients_and_runtimes.py | 91 ------------------- .../startup_shutdown.py | 89 ++++++++++++++++++ 3 files changed, 102 insertions(+), 104 deletions(-) delete mode 100644 examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py create mode 100644 examples/oemof_0.2/gradients_and_runtimes/startup_shutdown.py diff --git a/examples/oemof_0.2/gradients_and_runtimes/data.csv b/examples/oemof_0.2/gradients_and_runtimes/data.csv index 039a144..999c6e2 100644 --- a/examples/oemof_0.2/gradients_and_runtimes/data.csv +++ b/examples/oemof_0.2/gradients_and_runtimes/data.csv @@ -1,25 +1,25 @@ -timestep,demand_th +timestep,demand_el 1,0 2,0 3,0 -4,0 +4,1 5,1 6,1 -7,1 -8,1 -9,0 -10,0 -11,0 +7,0 +8,0 +9,1 +10,1 +11,1 12,0 -13,1 +13,0 14,1 15,1 16,1 17,0 18,0 -19,0 -20,0 +19,1 +20,1 21,1 -22,1 -23,1 -24,1 +22,0 +23,0 +24,0 diff --git a/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py b/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py deleted file mode 100644 index 605a181..0000000 --- a/examples/oemof_0.2/gradients_and_runtimes/gradients_and_runtimes.py +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: utf-8 -*- -""" -General description -------------------- -Example that illustrates how to use custom component `GenericCHP` can be used. -In this case it is used to model a back pressure turbine. - -Installation requirements -------------------------- -This example requires the latest version of oemof. Install by: - - pip install oemof - -""" - -import pandas as pd -import oemof.solph as solph -from oemof.network import Node -from oemof.outputlib import processing, views -try: - import matplotlib.pyplot as plt -except ImportError: - plt = None - - -# read sequence data -file_name = 'data' -data = pd.read_csv(file_name + '.csv', sep=",") - -# select periods -periods = len(data)-1 - -# create an energy system -idx = pd.date_range('1/1/2017', periods=periods, freq='H') -es = solph.EnergySystem(timeindex=idx) -Node.registry = es - -# resources -bgas = solph.Bus(label='bgas') - -rgas = solph.Source(label='rgas', outputs={bgas: solph.Flow()}) - -# heat -bth = solph.Bus(label='bth') - -# dummy source at high costs that serves the residual load -source_th = solph.Source(label='source_th', - outputs={bth: solph.Flow(variable_costs=10)}) - -demand_th = solph.Sink(label='demand_th', inputs={bth: solph.Flow(fixed=True, - actual_value=data['demand_th'], nominal_value=100)}) - -# power -bel = solph.Bus(label='bel') - -demand_el = solph.Sink(label='demand_el', inputs={bel: solph.Flow()}) - -powerplant = solph.Transformer( - label='pp_gas', - inputs={bgas: solph.Flow()}, - outputs={ - bel: solph.Flow(nominal_value=50), - bth: solph.Flow( - nominal_value=50, - min=0, max=1.0, - startup_costs=1000, shutdown_costs=0, - nonconvex=solph.NonConvex() - )}, - conversion_factors={bel: 0.5, bth: 0.5}) - -# create an optimization problem and solve it -om = solph.Model(es) - -# debugging -# om.write('generic_chp.lp', io_options={'symbolic_solver_labels': True}) - -# solve model -om.solve(solver='cbc', solve_kwargs={'tee': True}) - -# create result object -results = processing.results(om) - -# plot data -if plt is not None: - # plot thermal bus - data = views.node(results, 'bth')['sequences'] - data.index = data.index.map(lambda t: t.strftime('%H')) - ax = data.plot(kind='bar', grid=True, rot=0) - ax.set_xlabel('Hour') - ax.set_ylabel('Q (MW)') - plt.show() diff --git a/examples/oemof_0.2/gradients_and_runtimes/startup_shutdown.py b/examples/oemof_0.2/gradients_and_runtimes/startup_shutdown.py new file mode 100644 index 0000000..0e02f9a --- /dev/null +++ b/examples/oemof_0.2/gradients_and_runtimes/startup_shutdown.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +""" +General description +------------------- +Example that illustrates how to model startup and shutdown costs attributed +to a binary flow. + +Installation requirements +------------------------- +This example requires the latest version of oemof. Install by: + + pip install oemof + +""" + +import pandas as pd +import oemof.solph as solph +from oemof.network import Node +from oemof.outputlib import processing, views +try: + import matplotlib.pyplot as plt +except ImportError: + plt = None + + +# read sequence data +file_name = 'data' +data = pd.read_csv(file_name + '.csv', sep=",") + +# select periods +periods = len(data)-1 + +# create an energy system +idx = pd.date_range('1/1/2017', periods=periods, freq='H') +es = solph.EnergySystem(timeindex=idx) +Node.registry = es + +# power bus and components +bel = solph.Bus(label='bel') + +demand_el = solph.Sink( + label='demand_el', + inputs={bel: solph.Flow( + fixed=True, actual_value=data['demand_el'], nominal_value=10)}) + +# pp1 and pp2 are competing to serve overall 12 units load at lowest cost +# summed costs for pp1 = 12 * 10 * 10.25 = 1230 +# summed costs for pp2 = 4*5 + 4*5 + 12 * 10 * 10 = 1240 +# => pp1 serves the load despite of higher variable costs since +# the start and shutdown costs of pp2 change its marginal costs +pp1 = solph.Source( + label='power_plant1', + outputs={bel: solph.Flow(nominal_value=10, variable_costs=10.25)}) + +# shutdown costs only work in combination with a minimum load +# since otherwise the status variable is "allowed" to be active i.e. +# it permanently has a value of one which does not allow to set the shutdown +# variable which is set to one if the status variable changes from one to zero +pp2 = solph.Source( + label='power_plant2', + outputs={ + bel: solph.Flow( + nominal_value=10, min=0.5, max=1.0, variable_costs=10, + nonconvex=solph.NonConvex(startup_costs=5, shutdown_costs=5))}) + +# create an optimization problem and solve it +om = solph.Model(es) + +# debugging +#om.write('problem.lp', io_options={'symbolic_solver_labels': True}) + +# solve model +om.solve(solver='cbc', solve_kwargs={'tee': True}) + +# create result object +results = processing.results(om) + +# plot data +if plt is not None: + # plot electrical bus + data = views.node(results, 'bel')['sequences'] + data[(('bel', 'demand_el'), 'flow')] *= -1 + columns = [c for c in data.columns + if not any(s in c for s in ['status', 'startup', 'shutdown'])] + data = data[columns] + ax = data.plot(kind='line', drawstyle='steps-post', grid=True, rot=0) + ax.set_xlabel('Hour') + ax.set_ylabel('P (MW)') + plt.show() From 3702c7c5b35bb04bf9112ee8f2d006ffe0bfcdc8 Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Wed, 7 Feb 2018 11:19:52 +0100 Subject: [PATCH 4/8] Rename folder --- .../{gradients_and_runtimes => start_and_shutdown_costs}/data.csv | 0 .../startup_shutdown.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename examples/oemof_0.2/{gradients_and_runtimes => start_and_shutdown_costs}/data.csv (100%) rename examples/oemof_0.2/{gradients_and_runtimes => start_and_shutdown_costs}/startup_shutdown.py (100%) diff --git a/examples/oemof_0.2/gradients_and_runtimes/data.csv b/examples/oemof_0.2/start_and_shutdown_costs/data.csv similarity index 100% rename from examples/oemof_0.2/gradients_and_runtimes/data.csv rename to examples/oemof_0.2/start_and_shutdown_costs/data.csv diff --git a/examples/oemof_0.2/gradients_and_runtimes/startup_shutdown.py b/examples/oemof_0.2/start_and_shutdown_costs/startup_shutdown.py similarity index 100% rename from examples/oemof_0.2/gradients_and_runtimes/startup_shutdown.py rename to examples/oemof_0.2/start_and_shutdown_costs/startup_shutdown.py From 2eb4cdb543cf4fbb39c46e7cbfa1283dd9d97f36 Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Wed, 7 Feb 2018 12:25:28 +0100 Subject: [PATCH 5/8] Add basic min-max example --- examples/oemof_0.2/min_max_runtimes/data.csv | 25 ++++++ .../min_max_runtimes/min_max_runtimes.py | 79 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 examples/oemof_0.2/min_max_runtimes/data.csv create mode 100644 examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py diff --git a/examples/oemof_0.2/min_max_runtimes/data.csv b/examples/oemof_0.2/min_max_runtimes/data.csv new file mode 100644 index 0000000..e768006 --- /dev/null +++ b/examples/oemof_0.2/min_max_runtimes/data.csv @@ -0,0 +1,25 @@ +timestep,demand_el +1,0 +2,0 +3,0 +4,0 +5,1 +6,0 +7,0 +8,0 +9,0 +10,1 +11,0 +12,0 +13,0 +14,0 +15,1 +16,0 +17,0 +18,0 +19,0 +20,1 +21,0 +22,0 +23,0 +24,0 diff --git a/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py new file mode 100644 index 0000000..c04ca80 --- /dev/null +++ b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +""" +General description +------------------- +Example that illustrates how to model min and max runtimes. + +Installation requirements +------------------------- +This example requires the latest version of oemof. Install by: + + pip install oemof + +""" + +import pandas as pd +import oemof.solph as solph +from oemof.network import Node +from oemof.outputlib import processing, views +try: + import matplotlib.pyplot as plt +except ImportError: + plt = None + + +# read sequence data +file_name = 'data' +data = pd.read_csv(file_name + '.csv', sep=",") + +# select periods +periods = len(data)-1 + +# create an energy system +idx = pd.date_range('1/1/2017', periods=periods, freq='H') +es = solph.EnergySystem(timeindex=idx) +Node.registry = es + +# power bus and components +bel = solph.Bus(label='bel') + +demand_el = solph.Sink( + label='demand_el', + inputs={bel: solph.Flow( + fixed=True, actual_value=data['demand_el'], nominal_value=10)}) + +dummy_el = solph.Sink( + label='dummy_el', + inputs={bel: solph.Flow(variable_costs=10)}) + +pp = solph.Source( + label='power_plant', + outputs={ + bel: solph.Flow( + nominal_value=10, min=0.5, max=1.0, variable_costs=10, + nonconvex=solph.NonConvex(minimum_uptime=5, minimum_downtime=2))}) + +# create an optimization problem and solve it +om = solph.Model(es) + +# debugging +#om.write('problem.lp', io_options={'symbolic_solver_labels': True}) + +# solve model +om.solve(solver='cbc', solve_kwargs={'tee': True}) + +# create result object +results = processing.results(om) + +# plot data +if plt is not None: + # plot electrical bus + data = views.node(results, 'bel')['sequences'] + data[[(('bel', 'demand_el'), 'flow'), (('bel', 'dummy_el'), 'flow')]] *= -1 + columns = [c for c in data.columns + if not any(s in c for s in ['status'])] + data = data[columns] + ax = data.plot(kind='line', drawstyle='steps-post', grid=True, rot=0) + ax.set_xlabel('Hour') + ax.set_ylabel('P (MW)') + plt.show() From 5da936f50c2b4c3155cac9f2079b45a2f56a63ca Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Wed, 7 Feb 2018 15:13:08 +0100 Subject: [PATCH 6/8] Add min runtime example --- examples/oemof_0.2/min_max_runtimes/data.csv | 22 +++++++++++---- .../min_max_runtimes/min_max_runtimes.py | 28 +++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/examples/oemof_0.2/min_max_runtimes/data.csv b/examples/oemof_0.2/min_max_runtimes/data.csv index e768006..e1d475c 100644 --- a/examples/oemof_0.2/min_max_runtimes/data.csv +++ b/examples/oemof_0.2/min_max_runtimes/data.csv @@ -3,23 +3,35 @@ timestep,demand_el 2,0 3,0 4,0 -5,1 +5,0 6,0 7,0 8,0 -9,0 +9,1 10,1 11,0 12,0 13,0 14,0 15,1 -16,0 +16,1 17,0 18,0 19,0 20,1 -21,0 +21,1 22,0 23,0 -24,0 +24,1 +25,1 +26,0 +27,1 +28,1 +29,0 +30,0 +31,0 +32,0 +33,0 +34,0 +35,0 +36,0 diff --git a/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py index c04ca80..3506d8d 100644 --- a/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py +++ b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py @@ -46,12 +46,17 @@ label='dummy_el', inputs={bel: solph.Flow(variable_costs=10)}) -pp = solph.Source( - label='power_plant', +pp1 = solph.Source( + label='cheap_plant_min_max_constraints', outputs={ bel: solph.Flow( nominal_value=10, min=0.5, max=1.0, variable_costs=10, - nonconvex=solph.NonConvex(minimum_uptime=5, minimum_downtime=2))}) + nonconvex=solph.NonConvex( + minimum_uptime=6, initial_status=0))}) + +pp2 = solph.Source( + label='expensive_peak_power_plant', + outputs={bel: solph.Flow(nominal_value=10, variable_costs=20)}) # create an optimization problem and solve it om = solph.Model(es) @@ -71,9 +76,14 @@ data = views.node(results, 'bel')['sequences'] data[[(('bel', 'demand_el'), 'flow'), (('bel', 'dummy_el'), 'flow')]] *= -1 columns = [c for c in data.columns - if not any(s in c for s in ['status'])] - data = data[columns] - ax = data.plot(kind='line', drawstyle='steps-post', grid=True, rot=0) - ax.set_xlabel('Hour') - ax.set_ylabel('P (MW)') - plt.show() + if not any(s in c[0] or s in c[1] + for s in ['status', 'dummy_el', 'expensive_peak_power_plant'])] + #data = data[columns] + print(data[columns]) + + # data.reset_index(drop=True, inplace=True) + # #ax = data.plot(kind='line', drawstyle='steps-post', grid=True, rot=0) + # ax = data.plot(kind='bar', grid=True, rot=0) + # ax.set_xlabel('Hour') + # ax.set_ylabel('P (MW)') + # plt.show() From cb8bcfff71885b47c7ea80a0e7fc89d9869d8f08 Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Wed, 7 Feb 2018 15:57:59 +0100 Subject: [PATCH 7/8] Finish max runtime example --- examples/oemof_0.2/min_max_runtimes/data.csv | 26 +++++----------- .../min_max_runtimes/min_max_runtimes.py | 30 +++++++++---------- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/examples/oemof_0.2/min_max_runtimes/data.csv b/examples/oemof_0.2/min_max_runtimes/data.csv index e1d475c..b095163 100644 --- a/examples/oemof_0.2/min_max_runtimes/data.csv +++ b/examples/oemof_0.2/min_max_runtimes/data.csv @@ -3,35 +3,23 @@ timestep,demand_el 2,0 3,0 4,0 -5,0 +5,1 6,0 7,0 8,0 -9,1 -10,1 -11,0 +9,0 +10,0 +11,1 12,0 13,0 14,0 -15,1 +15,0 16,1 17,0 18,0 19,0 20,1 -21,1 +21,0 22,0 23,0 -24,1 -25,1 -26,0 -27,1 -28,1 -29,0 -30,0 -31,0 -32,0 -33,0 -34,0 -35,0 -36,0 +24,0 diff --git a/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py index 3506d8d..8a9f1fe 100644 --- a/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py +++ b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py @@ -47,16 +47,20 @@ inputs={bel: solph.Flow(variable_costs=10)}) pp1 = solph.Source( - label='cheap_plant_min_max_constraints', + label='cheap_plant_min_down_constraints', outputs={ bel: solph.Flow( nominal_value=10, min=0.5, max=1.0, variable_costs=10, nonconvex=solph.NonConvex( - minimum_uptime=6, initial_status=0))}) + minimum_downtime=4, initial_status=0))}) pp2 = solph.Source( - label='expensive_peak_power_plant', - outputs={bel: solph.Flow(nominal_value=10, variable_costs=20)}) + label='expensive_plant_min_up_constraints', + outputs={ + bel: solph.Flow( + nominal_value=10, min=0.5, max=1.0, variable_costs=10, + nonconvex=solph.NonConvex( + minimum_uptime=2, initial_status=1))}) # create an optimization problem and solve it om = solph.Model(es) @@ -75,15 +79,11 @@ # plot electrical bus data = views.node(results, 'bel')['sequences'] data[[(('bel', 'demand_el'), 'flow'), (('bel', 'dummy_el'), 'flow')]] *= -1 + exclude = ['dummy_el', 'status'] columns = [c for c in data.columns - if not any(s in c[0] or s in c[1] - for s in ['status', 'dummy_el', 'expensive_peak_power_plant'])] - #data = data[columns] - print(data[columns]) - - # data.reset_index(drop=True, inplace=True) - # #ax = data.plot(kind='line', drawstyle='steps-post', grid=True, rot=0) - # ax = data.plot(kind='bar', grid=True, rot=0) - # ax.set_xlabel('Hour') - # ax.set_ylabel('P (MW)') - # plt.show() + if not any(s in c[0] or s in c[1] for s in exclude)] + data = data[columns] + ax = data.plot(kind='line', drawstyle='steps-post', grid=True, rot=0) + ax.set_xlabel('Hour') + ax.set_ylabel('P (MW)') + plt.show() From c0433935a51510a2e17a4a51f4d47874f44c1c67 Mon Sep 17 00:00:00 2001 From: Cord Kaldemeyer Date: Mon, 12 Feb 2018 12:58:04 +0100 Subject: [PATCH 8/8] Adapt docstring to req. oemof version --- examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py | 4 ++-- .../oemof_0.2/start_and_shutdown_costs/startup_shutdown.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py index 8a9f1fe..ea279a2 100644 --- a/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py +++ b/examples/oemof_0.2/min_max_runtimes/min_max_runtimes.py @@ -6,9 +6,9 @@ Installation requirements ------------------------- -This example requires the latest version of oemof. Install by: +This example requires the version 0.2.1 of oemof. Install by: - pip install oemof + pip install 'oemof>=0.2.1,<0.3' """ diff --git a/examples/oemof_0.2/start_and_shutdown_costs/startup_shutdown.py b/examples/oemof_0.2/start_and_shutdown_costs/startup_shutdown.py index 0e02f9a..549999c 100644 --- a/examples/oemof_0.2/start_and_shutdown_costs/startup_shutdown.py +++ b/examples/oemof_0.2/start_and_shutdown_costs/startup_shutdown.py @@ -7,9 +7,9 @@ Installation requirements ------------------------- -This example requires the latest version of oemof. Install by: +This example requires the version 0.2.1 of oemof. Install by: - pip install oemof + pip install 'oemof>=0.2.1,<0.3' """