Пример #1
0
 def test_output_by_type_view(self):
     results = processing.results(self.om)
     transformer_output = views.node_output_by_type(results,
                                                    node_type=Transformer)
     compare = views.node(results, 'diesel',
                          multiindex=True)['sequences'][('diesel', 'b_el1',
                                                         'flow')]
     eq_(int(transformer_output.sum()), int(compare.sum()))
Пример #2
0
 def test_net_storage_flow(self):
     results = processing.results(self.om)
     storage_flow = views.net_storage_flow(results,
                                           node_type=GenericStorage)
     compare = views.node(results, 'storage', multiindex=True)['sequences']
     eq_(((compare[('storage', 'b_el2', 'flow')] -
           compare[('b_el1', 'storage',
                    'flow')]).to_frame() == storage_flow.values).all()[0],
         True)
    def simulating(dict_values, model, local_energy_system):
        """
        Initiates the oemof-solph simulation, accesses results and writes main results into dict

        Parameters
        ----------
        dict_values: dict
            All simulation inputs

        model: object
            oemof-solph object for energy system model

        local_energy_system: object
            pyomo object storing all constraints of the energy system model

        Returns
        -------
        Updated model with results, main results (flows, assets) and meta results (simulation)
        """
        logging.info("Starting simulation.")
        local_energy_system.solve(
            solver="cbc",
            solve_kwargs={
                "tee": False
            },  # if tee_switch is true solver messages will be displayed
            cmdline_options={"ratioGap": str(0.03)},
        )  # ratioGap allowedGap mipgap
        logging.info("Problem solved.")

        # add results to the energy system to make it possible to store them.
        results_main = processing.results(local_energy_system)
        results_meta = processing.meta_results(local_energy_system)

        model.results["main"] = results_main
        model.results["meta"] = results_meta

        dict_values.update({
            SIMULATION_RESULTS: {
                LABEL: SIMULATION_RESULTS,
                "objective_value": results_meta["objective"],
                "simulation_time": round(results_meta["solver"]["Time"], 2),
            }
        })
        logging.info(
            "Simulation time: %s minutes.",
            round(dict_values[SIMULATION_RESULTS]["simulation_time"] / 60, 2),
        )
        return model, results_main, results_main
Пример #4
0
def simulate(experiment, micro_grid_system, model, file_name):
    """
    Simulates the optimization problem using the given model and experiment's settings

    Parameters
    ----------
    experiment: dict
        Contains general settings for the experiment

    micro_grid_system: oemof.solph.network.EnergySystem
        Energy system for oemof optimization

    model: oemof.solph.models.Model
        Model used for the oemof optimization

    file_name: str
        Name used for saving the simulation's result

    Returns
    -------
    micro_grid_system: oemof.solph.network.EnergySystem
        Model for the optimization with integrated results

    """
    logging.info("Simulating...")
    model.solve(
        solver=experiment[SOLVER],
        solve_kwargs={
            "tee": experiment[SOLVER_VERBOSE]
        },  # if tee_switch is true solver messages will be displayed
        cmdline_options={
            experiment[CMDLINE_OPTION]: str(experiment[CMDLINE_OPTION_VALUE])
        },
    )  # ratioGap allowedGap mipgap
    logging.debug("Problem solved")

    if experiment["save_lp_file"] is True:
        logging.debug("Saving lp-file to folder.")
        model.write(
            experiment[OUTPUT_FOLDER] + "/lp_files/model_" + file_name + ".lp",
            io_options={SYMBOLIC_SOLVER_LABELS: True},
        )

    # add results to the energy system to make it possible to store them.
    micro_grid_system.results[MAIN] = processing.results(model)
    micro_grid_system.results[META] = processing.meta_results(model)
    return micro_grid_system
           inputs={
               bel:
               solph.Flow(my_keyword=True, fix=[0, 1, 1, 0], nominal_value=130)
           })

model = solph.Model(energy_system)

# only one of the two flows may be active at a time
solph.constraints.limit_active_flow_count_by_keyword(model,
                                                     "my_keyword",
                                                     lower_limit=0,
                                                     upper_limit=1)

model.solve()

results = processing.results(model)

if plt is not None:
    data = views.node(results, 'bel')['sequences']
    ax = data.plot(kind='line', grid=True)
    ax.set_xlabel('Time (h)')
    ax.set_ylabel('P (MW)')

    plt.figure()
    ax = plt.gca()
    plt.plot(results[('my_keyword', 'my_keyword')]['sequences'],
             label="my_keyword_count")
    ax.set_xlabel('Time (h)')
    ax.set_ylabel('Count (1)')
    plt.grid()
    plt.legend()
    efficiency=1,
    marginal_cost=0.0001)

energysystem.add(bus_heat, heat_source, shortage, excess, heat_demand,
                 thermal_storage)

# Create and solve the optimization model
optimization_model = Model(energysystem)
optimization_model.solve(solver=solver,
                         solve_kwargs={
                             'tee': False,
                             'keepfiles': False
                         })

# Get results
results = processing.results(optimization_model)
string_results = processing.convert_keys_to_strings(results)
sequences = {k: v['sequences'] for k, v in string_results.items()}
df = pd.concat(sequences, axis=1)

# Print storage sizing
built_storage_capacity = results[thermal_storage, None]['scalars']['invest']
initial_storage_capacity = results[thermal_storage,
                                   None]['scalars']['init_content']
maximum_heat_flow_charging = results[bus_heat,
                                     thermal_storage]['scalars']['invest']

dash = '-' * 50
print(dash)
print('{:>32s}{:>15.3f}'.format('Invested capacity [MW]',
                                maximum_heat_flow_charging))
Пример #7
0
def run_model_electric(config_path, var_number):

    with open(config_path, 'r') as ymlfile:
        cfg = yaml.load(ymlfile, Loader=yaml.FullLoader)

    if cfg['debug']:
        number_of_time_steps = 3
    else:
        number_of_time_steps = cfg['number_timesteps']

    solver = cfg['solver']
    debug = cfg['debug']
    solver_verbose = cfg['solver_verbose']  # show/hide solver output

    # ## Read data and parameters ## #

    # Define the used directories
    abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..')))
    results_path = abs_path + '/results'
    data_ts_path = abs_path + '/data/data_confidential/'
    data_param_path = abs_path + '/data/data_public/'

    # Read parameter values from parameter file
    if type(cfg['parameters_variation']) == list:
        file_path_param_01 = data_param_path + cfg['parameters_system']
        file_path_param_02 = data_param_path + cfg['parameters_variation'][
            var_number]
    elif type(cfg['parameters_system']) == list:
        file_path_param_01 = data_param_path + cfg['parameters_system'][
            var_number]
        file_path_param_02 = data_param_path + cfg['parameters_variation']
    else:
        file_path_param_01 = data_param_path + cfg['parameters_system']
        file_path_param_02 = data_param_path + cfg['parameters_variation']
    param_df_01 = pd.read_csv(file_path_param_01, index_col=1)
    param_df_02 = pd.read_csv(file_path_param_02, index_col=1)
    param_df = pd.concat([param_df_01, param_df_02], sort=True)
    param_value = param_df['value']

    # Import PV and demand data
    data = pd.read_csv((data_ts_path + cfg['time_series_file_name']))

    # Redefine ep_costs_function:
    def ep_costs_f(capex, n, opex):
        return ep_costs_func(capex, n, opex, param_value['wacc'])

    # Initiate the logger
    logger.define_logging(logfile='electric_model_{0}_{1}.log'.format(
        cfg['exp_number'], var_number),
                          logpath=results_path + '/logs',
                          screen_level=logging.INFO,
                          file_level=logging.DEBUG)

    date_time_index = pd.date_range('1/1/2017',
                                    periods=number_of_time_steps,
                                    freq='H')

    # Initialise the energysystem
    logging.info('Initialize the energy system')

    energysystem = solph.EnergySystem(timeindex=date_time_index)

    #######################
    # Build up the system #
    #######################

    # Busses

    bco = solph.Bus(label="cool")
    bwh = solph.Bus(label="waste")
    bel = solph.Bus(label="electricity")
    bam = solph.Bus(label="ambient")

    energysystem.add(bco, bwh, bel, bam)

    # Sinks and sources

    ambience = solph.Sink(label='ambience', inputs={bam: solph.Flow()})

    grid_el = solph.Source(
        label='grid_el',
        outputs={
            bel:
            solph.Flow(
                variable_costs=(param_value['price_electr'] *
                                float(param_value['price_electr_variation'])))
        })

    pv = solph.Source(
        label='pv',
        outputs={
            bel:
            solph.Flow(
                fix=data['pv_normiert'],
                investment=solph.Investment(ep_costs=ep_costs_f(
                    param_value['invest_costs_pv_output_el_09708'],
                    param_value['lifetime_pv'], param_value['opex_pv'])))
        })  # Einheit: 0,9708 kWpeak

    demand = solph.Sink(
        label='demand',
        inputs={bco: solph.Flow(fix=data['Cooling load kW'], nominal_value=1)})

    excess_el = solph.Sink(label='excess_el', inputs={bel: solph.Flow()})

    energysystem.add(ambience, grid_el, pv, demand, excess_el)

    # Transformers

    chil = solph.Transformer(
        label='compression_chiller',
        inputs={bel: solph.Flow()},
        outputs={
            bco:
            solph.Flow(investment=solph.Investment(ep_costs=ep_costs_f(
                param_value['invest_costs_compression_output_cool'],
                param_value['lifetime_compression'],
                param_value['opex_compression']))),
            bwh:
            solph.Flow()
        },
        conversion_factors={
            bco: param_value['conv_factor_compression_output_cool'],
            bwh: param_value['conv_factor_compression_output_waste']
        })

    towe = solph.Transformer(
        label='cooling_tower',
        inputs={
            bwh:
            solph.Flow(investment=solph.Investment(ep_costs=ep_costs_f(
                param_value['invest_costs_tower_input_th'],
                param_value['lifetime_tower'], param_value['opex_tower']))),
            bel:
            solph.Flow()
        },
        outputs={bam: solph.Flow()},
        conversion_factors={
            bwh: param_value['conv_factor_tower_input_waste'],
            bel: param_value['conv_factor_tower_input_el']
        })

    energysystem.add(chil, towe)

    # Storages

    if param_value['nominal_capacitiy_stor_cool'] == 0:
        stor_co = solph.components.GenericStorage(
            label='storage_cool',
            inputs={bco: solph.Flow()},
            outputs={bco: solph.Flow()},
            loss_rate=param_value['capac_loss_stor_cool'],
            # invest_relation_input_capacity=1 / 6,
            # invest_relation_output_capacity=1 / 6,
            inflow_conversion_factor=param_value[
                'conv_factor_stor_cool_input'],
            outflow_conversion_factor=param_value[
                'conv_factor_stor_cool_output'],
            investment=solph.Investment(ep_costs=ep_costs_f(
                param_value['invest_costs_stor_cool_capacity'],
                param_value['lifetime_stor_cool'],
                param_value['opex_stor_cool'])))
    else:
        stor_co = solph.components.GenericStorage(
            label='storage_cool',
            inputs={bco: solph.Flow()},
            outputs={bco: solph.Flow()},
            loss_rate=param_value['capac_loss_stor_cool'],
            inflow_conversion_factor=param_value[
                'conv_factor_stor_cool_input'],
            outflow_conversion_factor=param_value[
                'conv_factor_stor_cool_output'],
            nominal_capacity=param_value['nominal_capacitiy_stor_cool'])

    if param_value['nominal_capacitiy_stor_el'] == 0:
        stor_el = solph.components.GenericStorage(
            label='storage_electricity',
            inputs={bel: solph.Flow()},
            outputs={bel: solph.Flow()},
            loss_rate=param_value['capac_loss_stor_el'],
            inflow_conversion_factor=param_value['conv_factor_stor_el_input'],
            outflow_conversion_factor=param_value[
                'conv_factor_stor_el_output'],
            investment=solph.Investment(ep_costs=ep_costs_f((
                param_value['invest_costs_stor_el_capacity'] *
                float(param_value['capex_stor_el_variation'])
            ), param_value['lifetime_stor_el'], param_value['opex_stor_el'])))

    else:
        stor_el = solph.components.GenericStorage(
            label='storage_electricity',
            inputs={bel: solph.Flow()},
            outputs={bel: solph.Flow()},
            loss_rate=param_value['capac_loss_stor_el'],
            inflow_conversion_factor=param_value['conv_factor_stor_el_input'],
            outflow_conversion_factor=param_value[
                'conv_factor_stor_el_output'],
            nominal_capacity=param_value['nominal_capacitiy_stor_el'])

    energysystem.add(stor_co, stor_el)

    ########################################
    # Create a model and solve the problem #
    ########################################

    # Initialise the operational model (create the problem) with constrains
    model = solph.Model(energysystem)

    # ## Add own constrains ## #
    # Create a block and add it to the system
    myconstrains = po.Block()
    model.add_component('MyBlock', myconstrains)
    demand_sum = sum(data['Cooling load kW'])
    myconstrains.solar_constr = po.Constraint(
        expr=((sum(model.flow[grid_el, bel, t] for t in model.TIMESTEPS)) <= (
            demand_sum / param_value['conv_factor_compression_output_cool'] *
            param_value['sol_fraction_el'] *
            float(param_value['sol_fraction_el_variation']))))

    logging.info('Solve the optimization problem')
    model.solve(solver=solver, solve_kwargs={'tee': solver_verbose})

    if debug:
        filename = (
            results_path + '/lp_files/' +
            'electric_model_{0}_{1}.lp'.format(cfg['exp_number'], var_number))
        logging.info('Store lp-file in {0}.'.format(filename))
        model.write(filename, io_options={'symbolic_solver_labels': True})

    logging.info('Store the energy system with the results.')

    energysystem.results['main'] = processing.results(model)
    energysystem.results['meta'] = processing.meta_results(model)
    energysystem.results['param'] = (processing.parameter_as_dict(model))

    energysystem.dump(dpath=(results_path + '/dumps'),
                      filename='electric_model_{0}_{1}.oemof'.format(
                          cfg['exp_number'], var_number))
    def simulating(dict_values, model, local_energy_system):
        """
        Initiates the oemof-solph simulation, accesses results and writes main results into dict

        If an error is encountered in the oemof solver, mvs should not be allowed to continue,
        otherwise other errors related to the uncomplete simulation result might occur and it will
        be more obscure to the endusers what went wrong.

        A MVS error is raised if the omoef solver warning states explicitely that
        "termination condition infeasible", otherwise the oemof solver warning is re-raised as
        an error.


        Parameters
        ----------
        dict_values: dict
            All simulation inputs

        model: object
            oemof-solph object for energy system model

        local_energy_system: object
            pyomo object storing all constraints of the energy system model

        Returns
        -------
        Updated model with results, main results (flows, assets) and meta results (simulation)
        """

        logging.info("Starting simulation.")
        # turn warnings into errors
        warnings.filterwarnings("error")
        try:
            local_energy_system.solve(
                solver="cbc",
                solve_kwargs={
                    "tee": False
                },  # if tee_switch is true solver messages will be displayed
                cmdline_options={"ratioGap": str(0.03)},
            )  # ratioGap allowedGap mipgap
        except UserWarning as e:
            error_message = str(e)
            compare_message = "termination condition infeasible"
            if compare_message in error_message:
                error_message = (
                    f"The following error occurred during the mvs solver: {error_message}\n\n "
                    f"There are several reasons why this could have happened."
                    "\n\t- the energy system is not properly connected. "
                    "\n\t- the capacity of some assets might not have been optimized. "
                    "\n\t- the demands might not be supplied with the installed capacities in "
                    "current energy system. Check your maximum power demand and if your energy "
                    "production assets and/or energy conversion assets have enough capacity to "
                    "meet the total demand")
                logging.error(error_message)
                raise MVSOemofError(error_message) from None
            else:
                raise e
        # stop turning warnings into errors
        warnings.resetwarnings()

        # add results to the energy system to make it possible to store them.
        results_main = processing.results(local_energy_system)
        results_meta = processing.meta_results(local_energy_system)

        model.results["main"] = results_main
        model.results["meta"] = results_meta

        dict_values.update({
            SIMULATION_RESULTS: {
                LABEL: SIMULATION_RESULTS,
                OBJECTIVE_VALUE: results_meta["objective"],
                SIMULTATION_TIME: round(results_meta["solver"]["Time"], 2),
            }
        })
        logging.info(
            "Simulation time: %s minutes.",
            round(dict_values[SIMULATION_RESULTS][SIMULTATION_TIME] / 60, 2),
        )
        return model, results_main, results_main
Пример #9
0
def test_lopf(solver="cbc"):
    logging.info("Initialize the energy system")

    # create time index for 192 hours in May.
    date_time_index = pd.date_range("5/5/2012", periods=1, freq="H")
    es = EnergySystem(timeindex=date_time_index)

    ##########################################################################
    # Create oemof.solph objects
    ##########################################################################

    logging.info("Create oemof.solph objects")

    b_el0 = custom.ElectricalBus(label="b_0", v_min=-1, v_max=1)

    b_el1 = custom.ElectricalBus(label="b_1", v_min=-1, v_max=1)

    b_el2 = custom.ElectricalBus(label="b_2", v_min=-1, v_max=1)

    es.add(b_el0, b_el1, b_el2)

    es.add(
        custom.ElectricalLine(
            input=b_el0,
            output=b_el1,
            reactance=0.0001,
            investment=Investment(ep_costs=10),
            min=-1,
            max=1,
        ))

    es.add(
        custom.ElectricalLine(
            input=b_el1,
            output=b_el2,
            reactance=0.0001,
            nominal_value=60,
            min=-1,
            max=1,
        ))

    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)},
    ))

    ##########################################################################
    # Optimise the energy system and plot the results
    ##########################################################################

    logging.info("Creating optimisation model")
    om = Model(es)

    logging.info("Running lopf on 3-Node exmaple system")
    om.solve(solver=solver)

    results = processing.results(om)

    generators = views.node_output_by_type(results, Source)

    generators_test_results = {
        (es.groups["gen_0"], es.groups["b_0"], "flow"): 20,
        (es.groups["gen_1"], es.groups["b_1"], "flow"): 80,
    }

    for key in generators_test_results.keys():
        logging.debug("Test genertor production of {0}".format(key))
        eq_(
            int(round(generators[key])),
            int(round(generators_test_results[key])),
        )

    eq_(
        results[es.groups["b_2"], es.groups["b_0"]]["sequences"]["flow"][0],
        -40,
    )

    eq_(results[es.groups["b_1"], es.groups["b_2"]]["sequences"]["flow"][0],
        60)

    eq_(
        results[es.groups["b_0"], es.groups["b_1"]]["sequences"]["flow"][0],
        -20,
    )

    # objective function
    eq_(round(processing.meta_results(om)["objective"]), 3200)
Пример #10
0
 def setup(self):
     self.results = processing.results(optimization_model)
     self.param_results = processing.parameter_as_dict(optimization_model)
Пример #11
0
def test_dispatch_fix_example(solver='cbc', periods=10):
    """Invest in a flow with a `fix` sequence containing values > 1."""
    Node.registry = None

    filename = os.path.join(os.path.dirname(__file__), 'input_data.csv')
    data = pd.read_csv(filename, sep=",")

    # ######################### create energysystem components ################

    # electricity and heat
    bel = Bus(label='b_el')

    # 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_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))
                })

    # demands (electricity/heat)
    demand_el = Sink(
        label='demand_elec',
        inputs={bel: Flow(nominal_value=85, fix=data['demand_el'])})

    datetimeindex = pd.date_range('1/1/2012', periods=periods, freq='H')

    energysystem = EnergySystem(timeindex=datetimeindex)

    energysystem.add(bel, excess_el, pv, demand_el)

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

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

    # solve problem
    optimization_model.solve(solver=solver)

    # ################################ 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

    assert comp_results[(('pv', 'b_el'), 'flow')] > 0
Пример #12
0
def test_connect_invest():
    date_time_index = pd.date_range('1/1/2012', periods=24 * 7, freq='H')

    energysystem = EnergySystem(timeindex=date_time_index)
    network.Node.registry = energysystem

    # Read data file
    full_filename = os.path.join(os.path.dirname(__file__),
                                 'connect_invest.csv')
    data = pd.read_csv(full_filename, sep=",")

    logging.info('Create oemof objects')

    # create electricity bus
    bel1 = Bus(label="electricity1")
    bel2 = Bus(label="electricity2")

    # create excess component for the electricity bus to allow overproduction
    Sink(label='excess_bel', inputs={bel2: Flow()})
    Source(label='shortage', outputs={bel2: Flow(variable_costs=50000)})

    # create fixed source object representing wind power plants
    Source(label='wind',
           outputs={bel1: Flow(fix=data['wind'], nominal_value=1000000)})

    # create simple sink object representing the electrical demand
    Sink(label='demand',
         inputs={bel1: Flow(fix=data['demand_el'], nominal_value=1)})

    storage = components.GenericStorage(
        label='storage',
        inputs={bel1: Flow(variable_costs=10e10)},
        outputs={bel1: Flow(variable_costs=10e10)},
        loss_rate=0.00,
        initial_storage_level=0,
        invest_relation_input_capacity=1 / 6,
        invest_relation_output_capacity=1 / 6,
        inflow_conversion_factor=1,
        outflow_conversion_factor=0.8,
        investment=Investment(ep_costs=0.2),
    )

    line12 = Transformer(
        label="line12",
        inputs={bel1: Flow()},
        outputs={bel2: Flow(investment=Investment(ep_costs=20))})

    line21 = Transformer(
        label="line21",
        inputs={bel2: Flow()},
        outputs={bel1: Flow(investment=Investment(ep_costs=20))})

    om = Model(energysystem)

    constraints.equate_variables(om, om.InvestmentFlow.invest[line12, bel2],
                                 om.InvestmentFlow.invest[line21, bel1], 2)
    constraints.equate_variables(
        om, om.InvestmentFlow.invest[line12, bel2],
        om.GenericInvestmentStorageBlock.invest[storage])

    # if tee_switch is true solver messages will be displayed
    logging.info('Solve the optimization problem')
    om.solve(solver='cbc')

    # check if the new result object is working for custom components
    results = processing.results(om)

    my_results = dict()
    my_results['line12'] = float(views.node(results, 'line12')['scalars'])
    my_results['line21'] = float(views.node(results, 'line21')['scalars'])
    stor_res = views.node(results, 'storage')['scalars']
    my_results['storage_in'] = stor_res[(('electricity1', 'storage'),
                                         'invest')]
    my_results['storage'] = stor_res[(('storage', 'None'), 'invest')]
    my_results['storage_out'] = stor_res[(('storage', 'electricity1'),
                                          'invest')]

    connect_invest_dict = {
        'line12': 814705,
        'line21': 1629410,
        'storage': 814705,
        'storage_in': 135784,
        'storage_out': 135784
    }

    for key in connect_invest_dict.keys():
        eq_(int(round(my_results[key])), int(round(connect_invest_dict[key])))
def test_optimise_storage_size(filename="storage_investment.csv",
                               solver='cbc'):
    global PP_GAS

    logging.info('Initialize the energy system')
    date_time_index = pd.date_range('1/1/2012', periods=400, freq='H')

    energysystem = solph.EnergySystem(timeindex=date_time_index)
    Node.registry = energysystem

    full_filename = os.path.join(os.path.dirname(__file__), filename)
    data = pd.read_csv(full_filename, sep=",")

    # Buses
    bgas = solph.Bus(label="natural_gas")
    bel = solph.Bus(label="electricity")

    # Sinks
    solph.Sink(label='excess_bel', inputs={bel: solph.Flow()})

    solph.Sink(
        label='demand',
        inputs={bel: solph.Flow(fix=data['demand_el'], nominal_value=1)})

    # Sources
    solph.Source(label='rgas',
                 outputs={
                     bgas:
                     solph.Flow(nominal_value=194397000 * 400 / 8760,
                                summed_max=1)
                 })

    solph.Source(
        label='wind',
        outputs={bel: solph.Flow(fix=data['wind'], nominal_value=1000000)})

    solph.Source(
        label='pv',
        outputs={bel: solph.Flow(fix=data['pv'], nominal_value=582000)})

    # Transformer
    PP_GAS = solph.Transformer(
        label='pp_gas',
        inputs={bgas: solph.Flow()},
        outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)},
        conversion_factors={bel: 0.58})

    # Investment storage
    epc = economics.annuity(capex=1000, n=20, wacc=0.05)
    solph.components.GenericStorage(
        label='storage',
        inputs={bel: solph.Flow(variable_costs=10e10)},
        outputs={bel: solph.Flow(variable_costs=10e10)},
        loss_rate=0.00,
        initial_storage_level=0,
        invest_relation_input_capacity=1 / 6,
        invest_relation_output_capacity=1 / 6,
        inflow_conversion_factor=1,
        outflow_conversion_factor=0.8,
        investment=solph.Investment(ep_costs=epc, existing=6851),
    )

    # Solve model
    om = solph.Model(energysystem)
    om.receive_duals()
    om.solve(solver=solver)
    energysystem.results['main'] = processing.results(om)
    energysystem.results['meta'] = processing.meta_results(om)

    # Check dump and restore
    energysystem.dump()
Пример #14
0
def test_gen_caes():
    # read sequence data
    full_filename = os.path.join(os.path.dirname(__file__), 'generic_caes.csv')
    data = pd.read_csv(full_filename)

    # select periods
    periods = len(data)-1

    # create an energy system
    idx = pd.date_range('1/1/2017', periods=periods, freq='H')
    es = EnergySystem(timeindex=idx)
    Node.registry = es

    # resources
    bgas = Bus(label='bgas')

    Source(label='rgas', outputs={
        bgas: Flow(variable_costs=20)})

    # power
    bel_source = Bus(label='bel_source')
    Source(label='source_el', outputs={
        bel_source: Flow(variable_costs=data['price_el_source'])})

    bel_sink = Bus(label='bel_sink')
    Sink(label='sink_el', inputs={
        bel_sink: Flow(variable_costs=data['price_el_sink'])})

    # dictionary with parameters for a specific CAES plant
    # based on thermal modelling and linearization techniques
    concept = {
        'cav_e_in_b': 0,
        'cav_e_in_m': 0.6457267578,
        'cav_e_out_b': 0,
        'cav_e_out_m': 0.3739636077,
        'cav_eta_temp': 1.0,
        'cav_level_max': 211.11,
        'cmp_p_max_b': 86.0918959849,
        'cmp_p_max_m': 0.0679999932,
        'cmp_p_min': 1,
        'cmp_q_out_b': -19.3996965679,
        'cmp_q_out_m': 1.1066036114,
        'cmp_q_tes_share': 0,
        'exp_p_max_b': 46.1294016678,
        'exp_p_max_m': 0.2528340303,
        'exp_p_min': 1,
        'exp_q_in_b': -2.2073411014,
        'exp_q_in_m': 1.129249765,
        'exp_q_tes_share': 0,
        'tes_eta_temp': 1.0,
        'tes_level_max': 0.0
    }

    # generic compressed air energy storage (caes) plant
    custom.GenericCAES(
        label='caes',
        electrical_input={bel_source: Flow()},
        fuel_input={bgas: Flow()},
        electrical_output={bel_sink: Flow()},
        params=concept, fixed_costs=0)

    # create an optimization problem and solve it
    om = Model(es)

    # solve model
    om.solve(solver='cbc')

    # create result object
    results = processing.results(om)

    data = views.node(
        results, 'caes', keep_none_type=True
    )['sequences'].sum(axis=0).to_dict()

    test_dict = {
        (('caes', None), 'cav_level'): 25658.82964382,
        (('caes', None), 'exp_p'): 5020.801997000007,
        (('caes', None), 'exp_q_fuel_in'): 5170.880360999999,
        (('caes', None), 'tes_e_out'): 0.0,
        (('caes', None), 'exp_st'): 226.0,
        (('bgas', 'caes'), 'flow'): 5170.880360999999,
        (('caes', None), 'cav_e_out'): 1877.5972265299995,
        (('caes', None), 'exp_p_max'): 17512.352336,
        (('caes', None), 'cmp_q_waste'): 2499.9125993000007,
        (('caes', None), 'cmp_p'): 2907.7271520000004,
        (('caes', None), 'exp_q_add_in'): 0.0,
        (('caes', None), 'cmp_st'): 37.0,
        (('caes', None), 'cmp_q_out_sum'): 2499.9125993000007,
        (('caes', None), 'tes_level'): 0.0,
        (('caes', None), 'tes_e_in'): 0.0,
        (('caes', None), 'exp_q_in_sum'): 5170.880360999999,
        (('caes', None), 'cmp_p_max'): 22320.76334300001,
        (('caes', 'bel_sink'), 'flow'): 5020.801997000007,
        (('bel_source', 'caes'), 'flow'): 2907.7271520000004,
        (('caes', None), 'cav_e_in'): 1877.597226}

    for key in test_dict.keys():
        eq_(int(round(data[key])), int(round(test_dict[key])))
Пример #15
0
 def test_net_storage_flow_empty(self):
     results = processing.results(self.om)
     view = views.net_storage_flow(results, node_type=Sink)
     ok_(view is None)
     view2 = views.net_storage_flow(results, node_type=Flow)
     ok_(view2 is None)
Пример #16
0
 def test_node_weight_by_type_empty(self):
     results = processing.results(self.om)
     view = views.node_weight_by_type(results, node_type=Flow)
     ok_(view is None)
Пример #17
0
 def test_multiindex_sequences(self):
     results = processing.results(self.om)
     bel1 = views.node(results, 'b_el1', multiindex=True)
     eq_(int(bel1['sequences'][('diesel', 'b_el1', 'flow')].sum()), 2875)
def test_dispatch_one_time_step(solver='cbc'):
    """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(fix=0.5, nominal_value=66.3)})

    # demands (electricity/heat)
    demand_el = Sink(label='demand_elec',
                     inputs={bel: Flow(nominal_value=85, fix=0.3)})

    demand_th = Sink(label='demand_therm',
                     inputs={bth: Flow(nominal_value=40, fix=0.2)})

    # 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])))
Пример #19
0
 def test_error_from_nan_values(self):
     trsf = self.es.groups['diesel']
     bus = self.es.groups['b_el1']
     self.mod.flow[trsf, bus, 5] = float('nan')
     with assert_raises(ValueError):
         processing.results(self.mod)
Пример #20
0
def test_gen_chp():
    # read sequence data
    full_filename = os.path.join(os.path.dirname(__file__), 'ccet.csv')
    data = pd.read_csv(full_filename)

    # 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')

    solph.Source(label='rgas', outputs={bgas: solph.Flow()})

    # heat
    bth = solph.Bus(label='bth')

    solph.Source(label='source_th',
                 outputs={bth: solph.Flow(variable_costs=1000)})

    solph.Sink(
        label='demand_th',
        inputs={bth: solph.Flow(fix=data['demand_th'], nominal_value=200)})

    # power
    bel = solph.Bus(label='bel')

    solph.Sink(label='demand_el',
               inputs={bel: solph.Flow(variable_costs=data['price_el'])})

    # generic chp
    # (for back pressure characteristics Q_CW_min=0 and back_pressure=True)
    solph.components.GenericCHP(
        label='combined_cycle_extraction_turbine',
        fuel_input={
            bgas: solph.Flow(H_L_FG_share_max=data['H_L_FG_share_max'])
        },
        electrical_output={
            bel:
            solph.Flow(P_max_woDH=data['P_max_woDH'],
                       P_min_woDH=data['P_min_woDH'],
                       Eta_el_max_woDH=data['Eta_el_max_woDH'],
                       Eta_el_min_woDH=data['Eta_el_min_woDH'])
        },
        heat_output={bth: solph.Flow(Q_CW_min=data['Q_CW_min'])},
        Beta=data['Beta'],
        back_pressure=False)

    # create an optimization problem and solve it
    om = solph.Model(es)

    # solve model
    om.solve(solver='cbc')

    # create result object
    results = processing.results(om)

    data = views.node(results, 'bth')['sequences'].sum(axis=0).to_dict()

    test_dict = {
        (('bth', 'demand_th'), 'flow'): 20000.0,
        (('combined_cycle_extraction_turbine', 'bth'), 'flow'): 14070.15215799,
        (('source_th', 'bth'), 'flow'): 5929.8478649200015
    }

    for key in test_dict.keys():
        eq_(int(round(data[key])), int(round(test_dict[key])))
Пример #21
0
 def test_duals(self):
     results = processing.results(self.om)
     bel = views.node(results, 'b_el1', multiindex=True)
     eq_(int(bel['sequences']['b_el1', 'None', 'duals'].sum()), 48)
Пример #22
0
 def results(self):
     """ Returns a nested dictionary of the results of this optimization
     """
     return processing.results(self)
Пример #23
0
 def test_node_weight_by_type(self):
     results = processing.results(self.om)
     storage_content = views.node_weight_by_type(results,
                                                 node_type=GenericStorage)
     eq_(round(float(storage_content.sum()), 6), 1437.500003)
Пример #24
0
    )
)

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"))
print(views.node(results, "gen_1"))
print(views.node(results, "line_1"))
Пример #25
0
 def test_input_by_type_view(self):
     results = processing.results(self.om)
     sink_input = views.node_input_by_type(results, node_type=Sink)
     compare = views.node(results, 'demand_el', multiindex=True)
     eq_(int(sink_input.sum()),
         int(compare['sequences'][('b_el2', 'demand_el', 'flow')].sum()))
Пример #26
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])))
def test_tuples_as_labels_example(filename="storage_investment.csv",
                                  solver='cbc'):

    logging.info('Initialize the energy system')
    date_time_index = pd.date_range('1/1/2012', periods=40, freq='H')

    energysystem = solph.EnergySystem(timeindex=date_time_index)
    Node.registry = energysystem

    full_filename = os.path.join(os.path.dirname(__file__), filename)
    data = pd.read_csv(full_filename, sep=",")

    # Buses
    bgas = solph.Bus(label=Label('bus', 'natural_gas', None))
    bel = solph.Bus(label=Label('bus', 'electricity', ''))

    # Sinks
    solph.Sink(label=Label('sink', 'electricity', 'excess'),
               inputs={bel: solph.Flow()})

    solph.Sink(
        label=Label('sink', 'electricity', 'demand'),
        inputs={bel: solph.Flow(fix=data['demand_el'], nominal_value=1)})

    # Sources
    solph.Source(label=Label('source', 'natural_gas', 'commodity'),
                 outputs={
                     bgas:
                     solph.Flow(nominal_value=194397000 * 400 / 8760,
                                summed_max=1)
                 })

    solph.Source(
        label=Label('renewable', 'electricity', 'wind'),
        outputs={bel: solph.Flow(fix=data['wind'], nominal_value=1000000)})

    solph.Source(
        label=Label('renewable', 'electricity', 'pv'),
        outputs={bel: solph.Flow(
            fix=data['pv'],
            nominal_value=582000,
        )})

    # Transformer
    solph.Transformer(
        label=Label('pp', 'electricity', 'natural_gas'),
        inputs={bgas: solph.Flow()},
        outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)},
        conversion_factors={bel: 0.58})

    # Investment storage
    solph.components.GenericStorage(
        label=Label('storage', 'electricity', 'battery'),
        nominal_storage_capacity=204685,
        inputs={bel: solph.Flow(variable_costs=10e10)},
        outputs={bel: solph.Flow(variable_costs=10e10)},
        loss_rate=0.00,
        initial_storage_level=0,
        invest_relation_input_capacity=1 / 6,
        invest_relation_output_capacity=1 / 6,
        inflow_conversion_factor=1,
        outflow_conversion_factor=0.8,
    )

    # Solve model
    om = solph.Model(energysystem)
    om.solve(solver=solver)
    energysystem.results['main'] = processing.results(om)
    energysystem.results['meta'] = processing.meta_results(om)

    # Check dump and restore
    energysystem.dump()
    es = solph.EnergySystem()
    es.restore()

    # Results
    results = es.results['main']
    meta = es.results['meta']

    electricity_bus = views.node(results, 'bus_electricity_')
    my_results = electricity_bus['sequences'].sum(axis=0).to_dict()
    storage = es.groups['storage_electricity_battery']
    storage_node = views.node(results, storage)
    my_results['max_load'] = storage_node['sequences'].max()[((
        storage, None), 'storage_content')]
    commodity_bus = views.node(results, 'bus_natural_gas_None')

    gas_usage = commodity_bus['sequences'][(('source_natural_gas_commodity',
                                             'bus_natural_gas_None'), 'flow')]

    my_results['gas_usage'] = gas_usage.sum()

    stor_invest_dict = {
        'gas_usage': 1304112,
        'max_load': 0,
        (('bus_electricity_', 'sink_electricity_demand'), 'flow'): 8239764,
        (('bus_electricity_', 'sink_electricity_excess'), 'flow'): 22036732,
        (('bus_electricity_', 'storage_electricity_battery'), 'flow'): 0,
        (('pp_electricity_natural_gas', 'bus_electricity_'), 'flow'): 756385,
        (('renewable_electricity_pv', 'bus_electricity_'), 'flow'): 744132,
        (('renewable_electricity_wind', 'bus_electricity_'), 'flow'): 28775978,
        ((
            'storage_electricity_battery',
            'bus_electricity_',
        ), 'flow'): 0
    }

    for key in stor_invest_dict.keys():
        eq_(int(round(my_results[key])), int(round(stor_invest_dict[key])))

    # Solver results
    eq_(str(meta['solver']['Termination condition']), 'optimal')
    eq_(meta['solver']['Error rc'], 0)
    eq_(str(meta['solver']['Status']), 'ok')

    # Problem results
    eq_(int(meta['problem']['Lower bound']), 37819254)
    eq_(int(meta['problem']['Upper bound']), 37819254)
    eq_(meta['problem']['Number of variables'], 281)
    eq_(meta['problem']['Number of constraints'], 163)
    eq_(meta['problem']['Number of nonzeros'], 116)
    eq_(meta['problem']['Number of objectives'], 1)
    eq_(str(meta['problem']['Sense']), 'minimize')

    # Objective function
    eq_(round(meta['objective']), 37819254)