Ejemplo n.º 1
0
def optimize(input_data_dir, results_data_dir, solver='cbc', debug=False):
    r"""
    Takes the specified datapackage, creates an energysystem and solves the
    optimization problem.
    """
    # create energy system object
    logging.info("Creating EnergySystem from datapackage")
    es = EnergySystem.from_datapackage(
        os.path.join(input_data_dir, "datapackage.json"),
        attributemap={},
        typemap=TYPEMAP,
    )

    # create model from energy system (this is just oemof.solph)
    logging.info("Creating the optimization model")
    m = Model(es)

    # if you want dual variables / shadow prices uncomment line below
    # m.receive_duals()

    # save lp file together with optimization results
    if debug:
        lp_file_dir = os.path.join(results_data_dir, 'model.lp')
        logging.info(f"Saving the lp-file to {lp_file_dir}")
        m.write(lp_file_dir, io_options={'symbolic_solver_labels': True})

    # select solver 'gurobi', 'cplex', 'glpk' etc
    logging.info(f'Solving the problem using {solver}')
    m.solve(solver=solver)

    # get the results from the the solved model(still oemof.solph)
    es.results = m.results()
    es.params = outputlib.processing.parameter_as_dict(es)

    # now we use the write results method to write the results in oemof-tabular
    # format
    logging.info(f'Writing the results to {results_data_dir}')
    es.dump(results_data_dir)
Ejemplo n.º 2
0
    def test_bus_to_sink_outputs_in_results_dataframe(self):
        bus = Bus(uid="bus")
        source = FS(
            label="source",
            outputs={bus: Flow(nominal_value=1, actual_value=0.5, fixed=True)})
        sink = Sink(label="sink", inputs={bus: Flow(nominal_value=1)})

        es = self.es
        om = OM(es)
        es.results = om.results()
        es.results[bus][sink] = [0.7]
        rdf = RDF(energy_system=es)
        try:
            eq_(
                rdf.loc[(slice(None), slice(None), slice(None),
                         "sink"), :].val[0], 0.7,
                "Output from bus to sink does not have the correct value.")
        except KeyError:
            self.failed = True
        if self.failed:
            ok_(
                False,
                "Output from bus to sink does not appear in results dataframe."
            )

        es.results[bus][bus] = [-1]
        rdf = RDF(energy_system=es)
        try:
            eq_(
                rdf.loc[(slice(None), slice(None), slice(None),
                         "sink"), :].val[0], 0.7,
                "Output from bus to sink does not have the correct value.")
        except KeyError:
            self.failed = True
        if self.failed:
            ok_(
                False, "Output from bus (with duals) to sink " +
                "does not appear in results dataframe.")
Ejemplo n.º 3
0
    def test_issue_74(self):
        Storage.optimization_options.update({'investment': True})
        bus = Bus(uid="bus")
        store = Storage(uid="store",
                        inputs=[bus],
                        outputs=[bus],
                        c_rate_out=0.1,
                        c_rate_in=0.1)
        sink = Sink(uid="sink", inputs=[bus], val=[1])

        es = self.es
        om = OM(es)
        om.objective.set_value(-1)
        es.results = om.results()

        try:
            es.dump()
        except AttributeError as ae:
            self.failed = ae
        if self.failed:
            ok_(
                False,
                "EnergySystem#dump should not raise `AttributeError`: \n" +
                " Error message: " + str(self.failed))
Ejemplo n.º 4
0
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])))
Ejemplo n.º 5
0
    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})

m.solve(solver="cbc", solve_kwargs={"tee": True, "keepfiles": False})


m.results()

graph = create_nx_graph(es)

draw_graph(
    graph,
    plot=True,
    layout="neato",
    node_size=3000,
    node_color={"b_0": "#cd3333", "b_1": "#7EC0EE", "b_2": "#eeac7e"},
)


results = processing.results(m)

print(views.node(results, "gen_0"))
Ejemplo n.º 6
0
import oemof.tabular.tools.postprocessing as pp

# create  path for results (we use the datapackage_dir to store results)
results_path = 'results'
if not os.path.exists(results_path):
    os.makedirs(results_path)

# create energy system object
es = EnergySystem.from_datapackage(
    os.path.join("./datapackage", "datapackage.json"),
    attributemap={},
    typemap=TYPEMAP,
)

# create model from energy system (this is just oemof.solph)
m = Model(es)

# if you want dual variables / shadow prices uncomment line below
# m.receive_duals()

# select solver 'gurobi', 'cplex', 'glpk' etc
m.solve("glpk")

# get the results from the the solved model(still oemof.solph)
m.results = m.results()

# now we use the write results method to write the results in oemof-tabular
# format
pp.write_results(m, results_path)
print("process completed")
Ejemplo n.º 7
0
                }))

# ################################ optimization ###########################

# create optimization model based on energy_system
optimization_model = Model(energysystem=energysystem)

# solve problem
optimization_model.solve(solver=solver,
                         solve_kwargs={
                             'tee': True,
                             'keepfiles': False
                         })

# write back results from optimization object to energysystem
optimization_model.results()

# ################################ results ################################

# 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(optimization_model.results(), 'bel')
data['sequences'].info()
print('Optimization successful. Showing some results:')

# see: https://pandas.pydata.org/pandas-docs/stable/visualization.html
node_results_bel = views.node(optimization_model.results(), 'bel')
node_results_flows = node_results_bel['sequences']
Ejemplo n.º 8
0
    ))

# ################################ optimization ###########################

# create optimization model based on energy_system
optimization_model = Model(energysystem=energysystem)

# solve problem
optimization_model.solve(solver=solver,
                         solve_kwargs={
                             "tee": True,
                             "keepfiles": False
                         })

# write back results from optimization object to energysystem
optimization_model.results()

# ################################ results ################################

# 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(optimization_model.results(), "bel")
data["sequences"].info()
print("Optimization successful. Showing some results:")

# see: https://pandas.pydata.org/pandas-docs/stable/visualization.html
node_results_bel = views.node(optimization_model.results(), "bel")
node_results_flows = node_results_bel["sequences"]
Ejemplo n.º 9
0
            "oemof.tabular",
            "examples/datapackages/{}/datapackage.json".format(example),
        ),
        attributemap={},
        typemap=TYPEMAP,
    )

    es.timeindex = es.timeindex[0:5]

    m = Model(es)

    m.solve(solver="cbc")

    # skip foreignkeys example as not all buses are present
    if example != "foreignkeys":
        br = pp.bus_results(es, m.results(), select="scalars")

        if example == "investment":
            br["bus0"].xs([es.groups["bus0"], "invest"], level=[1, 2])

        pp.supply_results(results=m.results(), es=es, bus=["heat-bus"])

        pp.supply_results(results=m.results(), es=es, bus=["bus0", "bus1"])

        pp.demand_results(results=m.results(), es=es, bus=["bus0", "bus1"])

        pp.component_results(results=m.results(), es=es, select="sequences")

        pp.component_results(results=m.results(), es=es, select="scalars")

        views.node_input_by_type(
Ejemplo n.º 10
0
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])))
Ejemplo n.º 11
0
here = os.path.abspath(os.path.dirname(__file__))

name = 'simple_model'

preprocessed = sys.argv[1]

optimized = sys.argv[2]

if not os.path.exists(optimized):
    os.mkdir(optimized)

es = EnergySystem.from_datapackage(
    os.path.join(preprocessed, "datapackage.json"),
    attributemap={},
    typemap=TYPEMAP,
)

# create model from energy system (this is just oemof.solph)
m = Model(es)

# select solver 'gurobi', 'cplex', 'glpk' etc
m.solve(solver='cbc')

# get the results from the the solved model(still oemof.solph)
es.results = m.results()

# now we use the write results method to write the results in oemoftabular
# format
es.dump(optimized)
Ejemplo n.º 12
0
            "oemof.tabular",
            "examples/datapackages/{}/datapackage.json".format(example),
        ),
        attributemap={},
        typemap=TYPEMAP,
    )

    es.timeindex = es.timeindex[0:5]

    m = Model(es)

    m.solve(solver="cbc")

    # skip foreignkeys example as not all buses are present
    if example != "foreignkeys":
        br = pp.bus_results(es, m.results(), select="scalars")

        if example == "investment":
            br["bus0"].xs([es.groups["bus0"], "invest"], level=[1, 2])

        pp.supply_results(results=m.results(), es=es, bus=["heat-bus"])

        pp.supply_results(results=m.results(), es=es, bus=["bus0", "bus1"])

        pp.demand_results(results=m.results(), es=es, bus=["bus0", "bus1"])

        pp.component_results(results=m.results(), es=es, select="sequences")

        pp.component_results(results=m.results(), es=es, select="scalars")

        views.node_input_by_type(m.results(),
Ejemplo n.º 13
0
demand_el = Sink(label='electricity_demand',
                 inputs={bus_el: Flow(nominal_value=2,
                                      fixed=True,
                                      actual_value=demand_ts)})

curtailment = Sink(label='curtailment',
                   inputs={bus_el: Flow(nominal_value=5,
                                        max=pv_ts)})

es.add(bus_el, bus_gas, source_gas, gas_pp, pv, demand_el, curtailment)

optimodel = Model(es)

optimodel.solve()

results = optimodel.results()

string_results = outputlib.processing.convert_keys_to_strings(results)

# collect all timeseries in a DataFrame
sequences = {k: v['sequences'] for k, v in string_results.items()}

sequences = pd.concat(sequences, axis=1)

print(sequences)

# plot
idx = pd.IndexSlice
fig, ax = plt.subplots()
sequences.loc[:,idx[:,'electricity_bus',:]].plot.area(ax=ax, stacked=True)
sequences.loc[:,idx[:,'electricity_demand',:]].plot(ax=ax, c='r')
Ejemplo n.º 14
0
            variable_costs=10
        )
    }
)

es.add(el_bus, demand, pp1, pp2)

om = Model(es)

lp_file_dir = 'dispatch.lp'

om.write(lp_file_dir, io_options={'symbolic_solver_labels': True})

om.solve()

results = om.results()

string_results = outputlib.processing.convert_keys_to_strings(results)

string_results = outputlib.processing.convert_keys_to_strings(results)

# collect all timeseries in a DataFrame
sequences = {k: v['sequences'] for k, v in string_results.items()}
sequences = pd.concat(sequences, axis=1)

print(sequences)

# plot
idx = pd.IndexSlice
fig, ax = plt.subplots()
sequences.loc[:,idx[:,'el_bus',:]].plot.area(ax=ax, stacked=True)
Ejemplo n.º 15
0
def compute(datapackage, solver="gurobi"):
    """
    """
    config = Scenario.from_path(
        os.path.join("scenarios", datapackage + ".toml")
    )
    emission_limit = config["scenario"].get("co2_limit")

    temporal_resolution = config.get("model", {}).get("temporal_resolution", 1)

    datapackage_dir = os.path.join("datapackages", datapackage)

    # create results path
    scenario_path = os.path.join("results", datapackage)
    if not os.path.exists(scenario_path):
        os.makedirs(scenario_path)
    output_path = os.path.join(scenario_path, "output")

    if not os.path.exists(output_path):
        os.makedirs(output_path)

    # copy package either aggregated or the original one (only data!)
    if temporal_resolution > 1:
        logging.info("Aggregating for temporal aggregation ... ")
        path = aggregation.temporal_skip(
            os.path.join(datapackage_dir, "datapackage.json"),
            temporal_resolution,
            path=scenario_path,
            name="input",
        )
    else:
        path = processing.copy_datapackage(
            os.path.join(datapackage_dir, "datapackage.json"),
            os.path.abspath(os.path.join(scenario_path, "input")),
            subset="data",
        )

    es = EnergySystem.from_datapackage(
        os.path.join(path, "datapackage.json"),
        attributemap={},
        typemap=facades.TYPEMAP,
    )

    m = Model(es)

    if emission_limit is not None:
        constraints.emission_limit(m, limit=emission_limit)

    flows = {}
    for (i, o) in m.flows:
        if hasattr(m.flows[i, o], "emission_factor"):
            flows[(i, o)] = m.flows[i, o]

    # add emission as expression to model
    BUSES = [b for b in es.nodes if isinstance(b, Bus)]

    def emission_rule(m, b, t):
        expr = sum(
            m.flow[inflow, outflow, t]
            * m.timeincrement[t]
            * getattr(flows[inflow, outflow], "emission_factor", 0)
            for (inflow, outflow) in flows
            if outflow is b
        )
        return expr

    m.emissions = Expression(BUSES, m.TIMESTEPS, rule=emission_rule)

    m.receive_duals()

    m.solve(solver)

    m.results = m.results()

    pp.write_results(m, output_path)

    modelstats = outputlib.processing.meta_results(m)
    modelstats.pop("solver")
    modelstats["problem"].pop("Sense")
    # TODO: This is not model stats -> move somewhere else!
    modelstats["temporal_resolution"] = temporal_resolution
    modelstats["emission_limit"] = emission_limit

    with open(os.path.join(scenario_path, "modelstats.json"), "w") as outfile:
        json.dump(modelstats, outfile, indent=4)

    supply_sum = (
        pp.supply_results(
            results=m.results,
            es=m.es,
            bus=[b.label for b in es.nodes if isinstance(b, Bus)],
            types=[
                "dispatchable",
                "volatile",
                "conversion",
                "backpressure",
                "extraction",
                #    "storage",
                "reservoir",
            ],
        )
        # .clip(0)
        .sum().reset_index()
    )
    supply_sum["from"] = supply_sum.apply(
        lambda x: "-".join(x["from"].label.split("-")[1::]), axis=1
    )
    supply_sum.drop("type", axis=1, inplace=True)
    supply_sum = (
        supply_sum.set_index(["from", "to"]).unstack("from")
        / 1e6
        * temporal_resolution
    )
    supply_sum.columns = supply_sum.columns.droplevel(0)
    summary = supply_sum  # pd.concat([supply_sum, excess_share], axis=1)
    ## grid
    imports = pd.DataFrame()
    link_results = pp.component_results(m.es, m.results).get("link")
    link_results.to_csv(
        os.path.join(scenario_path, "output", "transmission.csv")
    )

    for b in [b.label for b in es.nodes if isinstance(b, Bus)]:
        if link_results is not None and m.es.groups[b] in list(
            link_results.columns.levels[0]
        ):
            ex = link_results.loc[
                :, (m.es.groups[b], slice(None), "flow")
            ].sum(axis=1)
            im = link_results.loc[
                :, (slice(None), m.es.groups[b], "flow")
            ].sum(axis=1)

            net_import = im - ex
            net_import.name = m.es.groups[b]
            imports = pd.concat([imports, net_import], axis=1)

    summary["total_supply"] = summary.sum(axis=1)
    summary["RE-supply"] = (
        summary["wind-onshore"]
        + summary["wind-offshore"]
        + summary["biomass-st"]
        + summary["hydro-ror"]
        + summary["hydro-reservoir"]
        + summary["solar-pv"]
    )
    if "other-res" in summary:
        summary["RE-supply"] += summary["other-res"]

    summary["RE-share"] = summary["RE-supply"] / summary["total_supply"]

    summary["import"] = imports[imports > 0].sum() / 1e6 * temporal_resolution
    summary["export"] = imports[imports < 0].sum() / 1e6 * temporal_resolution
    summary.to_csv(os.path.join(scenario_path, "summary.csv"))

    emissions = (
        pd.Series({key: value() for key, value in m.emissions.items()})
        .unstack()
        .T
    )
    emissions.to_csv(os.path.join(scenario_path, "emissions.csv"))