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
예제 #2
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
예제 #3
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
예제 #5
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)
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()
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)