예제 #1
0
def source_dispatchable_fix(model, dict_asset, **kwargs):
    r"""
    Defines a dispatchable source with a fixed capacity.

    See :py:func:`~.source` for more information, including parameters.

    Notes
    -----
    Tested with:
    - test_source_dispatchable_fix_normalized_timeseries()
    - test_source_dispatchable_fix_timeseries_not_normalized_timeseries()

    Returns
    -------
    Indirectly updated `model` and dict of asset in `kwargs` with the source object.

    """
    if TIMESERIES_NORMALIZED in dict_asset:
        outputs = {
            kwargs[OEMOF_BUSSES][dict_asset[OUTFLOW_DIRECTION]]:
            solph.Flow(
                label=dict_asset[LABEL],
                max=dict_asset[TIMESERIES_NORMALIZED],
                existing=dict_asset[INSTALLED_CAP][VALUE],
                variable_costs=dict_asset[DISPATCH_PRICE][VALUE],
                # add emission_factor for emission contraint
                emission_factor=dict_asset[EMISSION_FACTOR][VALUE],
            )
        }
        source_dispatchable = solph.Source(
            label=dict_asset[LABEL],
            outputs=outputs,
        )
    else:
        if TIMESERIES in dict_asset:
            logging.info(
                f"Asset {dict_asset[LABEL]} is introduced as a dispatchable source with an availability schedule."
            )
            logging.debug(
                f"The availability schedule is solely introduced because the key {TIMESERIES_NORMALIZED} was not in the asset´s dictionary. \n"
                f"It should only be applied to DSO sources. "
                f"If the asset should not have this behaviour, please create an issue.",
            )
        outputs = {
            kwargs[OEMOF_BUSSES][dict_asset[OUTFLOW_DIRECTION]]:
            solph.Flow(
                label=dict_asset[LABEL],
                existing=dict_asset[INSTALLED_CAP][VALUE],
                variable_costs=dict_asset[DISPATCH_PRICE][VALUE],
            )
        }
        source_dispatchable = solph.Source(
            label=dict_asset[LABEL],
            outputs=outputs,
        )
    model.add(source_dispatchable)
    kwargs[OEMOF_SOURCE].update({dict_asset[LABEL]: source_dispatchable})
    logging.debug(
        f"Added: Dispatchable source {dict_asset[LABEL]} (fixed capacity) to bus {dict_asset[OUTFLOW_DIRECTION]}."
    )
예제 #2
0
def test_something_else():
    date_time_index = pd.date_range('1/1/2012', periods=5, freq='H')
    energysystem = solph.EnergySystem(timeindex=date_time_index)
    bel1 = solph.Bus(label='electricity1')
    bel2 = solph.Bus(label='electricity2')
    energysystem.add(bel1, bel2)
    energysystem.add(
        solph.Transformer(
            label='powerline_1_2',
            inputs={bel1: solph.Flow()},
            outputs={
                bel2: solph.Flow(investment=solph.Investment(ep_costs=20))
            }))
    energysystem.add(
        solph.Transformer(
            label='powerline_2_1',
            inputs={bel2: solph.Flow()},
            outputs={
                bel1: solph.Flow(investment=solph.Investment(ep_costs=20))
            }))
    om = solph.Model(energysystem)
    line12 = energysystem.groups['powerline_1_2']
    line21 = energysystem.groups['powerline_2_1']
    solph.constraints.equate_variables(om,
                                       om.InvestmentFlow.invest[line12, bel2],
                                       om.InvestmentFlow.invest[line21, bel1],
                                       name="my_name")
예제 #3
0
    def add_to_oemof_model(self, busses, model):
        """Creates an oemof Transformer component from the information given in the
        Electrolyzer class, to be used in the oemof model

        :param busses: virtual buses used in the energy system
        :type busses: dict
        :param model: current oemof model
        :type model: oemof model
        :return: oemof component
        """
        # Get the non-linear behaviour.
        self.update_nonlinear_behaviour()

        # Create the non-linear oemof component.
        electrolyzer = solph.custom.PiecewiseLinearTransformer(
            label=self.name,
            inputs={
                busses[self.bus_el]:
                solph.Flow(nominal_value=self.energy_max, variable_costs=0)
            },
            outputs={busses[self.bus_h2]: solph.Flow()},
            in_breakpoints=self.supporting_points['energy'],
            conversion_function=self.conversion_fun_ely,
            pw_repn='CC')

        model.add(electrolyzer)
        return electrolyzer
예제 #4
0
    def test_fixed_source_invest_sink(self):
        """ Wrong constraints for fixed source + invest sink w. `summed_max`.
        """

        bel = solph.Bus(label='electricityBus')

        solph.Source(label='wind',
                     outputs={
                         bel:
                         solph.Flow(actual_value=[12, 16, 14],
                                    nominal_value=1000000,
                                    fixed=True)
                     })

        solph.Sink(label='excess',
                   inputs={
                       bel:
                       solph.Flow(summed_max=2.3,
                                  variable_costs=25,
                                  max=0.8,
                                  investment=solph.Investment(ep_costs=500,
                                                              maximum=10e5,
                                                              existing=50))
                   })

        self.compare_lp_files('fixed_source_invest_sink.lp')
예제 #5
0
    def test_linear_transformer_chp_invest(self):
        """Constraint test of a Transformer with Investment (two outputs).
        """

        bgas = solph.Bus(label='gasBus')
        bheat = solph.Bus(label='heatBus')
        bel = solph.Bus(label='electricityBus')

        solph.Transformer(label='chp_powerplant_gas',
                          inputs={
                              bgas:
                              solph.Flow(variable_costs=50,
                                         investment=solph.Investment(
                                             maximum=1000, ep_costs=20))
                          },
                          outputs={
                              bel: solph.Flow(),
                              bheat: solph.Flow()
                          },
                          conversion_factors={
                              bel: 0.4,
                              bheat: 0.5
                          })

        self.compare_lp_files('linear_transformer_chp_invest.lp')
예제 #6
0
    def test_transformer(self):
        """Constraint test of a LinearN1Transformer without Investment.
        """
        bgas = solph.Bus(label='gasBus')
        bbms = solph.Bus(label='biomassBus')
        bel = solph.Bus(label='electricityBus')
        bth = solph.Bus(label='thermalBus')

        solph.Transformer(label='powerplantGasCoal',
                          inputs={
                              bbms: solph.Flow(),
                              bgas: solph.Flow()
                          },
                          outputs={
                              bel:
                              solph.Flow(variable_costs=50),
                              bth:
                              solph.Flow(nominal_value=5e10, variable_costs=20)
                          },
                          conversion_factors={
                              bgas: 0.4,
                              bbms: 0.1,
                              bel: 0.3,
                              bth: 0.5
                          })

        self.compare_lp_files('transformer.lp')
예제 #7
0
    def test_transformer_invest_with_existing(self):
        """Constraint test of a LinearN1Transformer with Investment.
        """

        bgas = solph.Bus(label='gasBus')
        bcoal = solph.Bus(label='coalBus')
        bel = solph.Bus(label='electricityBus')
        bth = solph.Bus(label='thermalBus')

        solph.Transformer(label='powerplant_gas_coal',
                          inputs={
                              bgas: solph.Flow(),
                              bcoal: solph.Flow()
                          },
                          outputs={
                              bel:
                              solph.Flow(variable_costs=50,
                                         investment=solph.Investment(
                                             maximum=1000,
                                             ep_costs=20,
                                             existing=200)),
                              bth:
                              solph.Flow(variable_costs=20)
                          },
                          conversion_factors={
                              bgas: 0.58,
                              bcoal: 0.2,
                              bel: 0.3,
                              bth: 0.5
                          })

        self.compare_lp_files('transformer_invest_with_existing.lp')
예제 #8
0
    def add_to_oemof_model(self, busses, model):
        """Creates an oemof Transformer component using the information given in
        the CompressorH2 class, to be used in the oemof model

        :param busses: virtual buses used in the energy system
        :type busses: dict
        :param model: current oemof model
        :type model: oemof model
        :return: oemof component
        """
        compressor = solph.Transformer(
            label=self.name,
            inputs={
                busses[self.bus_h2_in]:
                solph.Flow(nominal_value=self.m_flow_max *
                           self.sim_params.interval_time / 60),
                busses[self.bus_el]:
                solph.Flow()
            },
            outputs={busses[self.bus_h2_out]: solph.Flow()},
            conversion_factors={
                busses[self.bus_h2_in]: 1,
                busses[self.bus_el]: self.spec_compression_energy,
                busses[self.bus_h2_out]: 1
            })

        model.add(compressor)
        return compressor
예제 #9
0
    def test_investment_flow_grouping(self):
        """ Flows of investment sink should be grouped.

        The constraint tests uncovered a spurious error where the flows of an
        investment `Sink` where not put into the `InvestmentFlow` group,
        although the corresponding grouping was present in the energy system.
        The error occured in the case where the investment `Sink` was not
        instantiated directly after the `Bus` it is connected to.

        This test recreates this error scenario and makes sure that the
        `InvestmentFlow` group is not empty.
        """

        b = solph.Bus(label='Bus')

        solph.Source(label='Source', outputs={b: solph.Flow(
            actual_value=[12, 16, 14], nominal_value=1000000,
            fixed=True)})

        solph.Sink(label='Sink', inputs={b: solph.Flow(
            summed_max=2.3, variable_costs=25, max=0.8,
            investment=Investment(ep_costs=500, maximum=10e5))})

        ok_(self.es.groups.get(IF),
            ("Expected InvestmentFlow group to be nonempty.\n" +
             "Got: {}").format(self.es.groups.get(IF)))
예제 #10
0
    def add_to_oemof_model(self, busses, model):
        """Creates an oemof Generic Storage component from the information given in
        the StorageH2 class, to be used in the oemof model.

        :param busses: virtual buses used in the energy system
        :type busses: dict
        :param model: current oemof model
        :type model: oemof model
        :return: oemof component
        """
        storage = solph.components.GenericStorage(
            label=self.name,
            outputs={
                busses[self.bus_out]:
                solph.Flow(nominal_value=self.delta_max,
                           variable_costs=self.current_vac[1])
            },
            inputs={
                busses[self.bus_in]:
                solph.Flow(nominal_value=self.delta_max,
                           variable_costs=self.current_vac[0])
            },
            initial_storage_level=self.storage_level / self.storage_capacity,
            nominal_storage_capacity=self.storage_capacity,
            min_storage_level=self.storage_level_min / self.storage_capacity,
            balanced=False)

        model.add(storage)
        return storage
예제 #11
0
    def add_to_oemof_model(self, busses, model):
        """Creates an oemof Generic Storage component from the information given in
        the Battery class, to be used in the oemof model.

        :param busses: virtual buses used in the energy system
        :type busses: dict
        :param model: current oemof model
        :type model: oemof model
        :return: oemof component
        """
        battery = solph.components.GenericStorage(
            label=self.name,
            inputs={
                busses[self.bus_in_and_out]:
                solph.Flow(nominal_value=self.p_in_max,
                           variable_costs=self.current_vac[0])
            },
            outputs={
                busses[self.bus_in_and_out]:
                solph.Flow(nominal_value=self.p_out_max,
                           variable_costs=self.current_vac[1])
            },
            loss_rate=self.loss_rate,
            initial_storage_level=self.soc,
            nominal_storage_capacity=self.battery_capacity,
            min_storage_level=self.soc_min,
            inflow_conversion_factor=self.efficiency_charge,
            outflow_conversion_factor=self.efficiency_discharge,
            balanced=False,
        )
        model.add(battery)
        return battery
예제 #12
0
    def test_shared_limit(self):
        """
        """
        b1 = solph.Bus(label='bus')

        storage1 = solph.components.GenericStorage(label="storage1",
                                                   nominal_storage_capacity=5,
                                                   inputs={b1: solph.Flow()},
                                                   outputs={b1: solph.Flow()})
        storage2 = solph.components.GenericStorage(label="storage2",
                                                   nominal_storage_capacity=5,
                                                   inputs={b1: solph.Flow()},
                                                   outputs={b1: solph.Flow()})

        model = self.get_om()

        components = [storage1, storage2]

        solph.constraints.shared_limit(
            model,
            model.GenericStorageBlock.storage_content,
            "limit_storage",
            components, [0.5, 1.25],
            upper_limit=7)

        self.compare_lp_files('shared_limit.lp', my_om=model)
예제 #13
0
    def test_nonconvex_investment_storage_with_offset(self):
        """All invest variables are coupled. The invest variables of the Flows
        will be created during the initialisation of the storage e.g. battery
        """
        bel = solph.Bus(label='electricityBus')

        solph.components.GenericStorage(
            label='storagenon_convex',
            inputs={bel: solph.Flow(variable_costs=56)},
            outputs={bel: solph.Flow(variable_costs=24)},
            nominal_storage_capacity=None,
            loss_rate=0.13,
            max_storage_level=0.9,
            min_storage_level=0.1,
            invest_relation_input_capacity=1 / 6,
            invest_relation_output_capacity=1 / 6,
            inflow_conversion_factor=0.97,
            outflow_conversion_factor=0.86,
            investment=solph.Investment(ep_costs=145,
                                        minimum=19,
                                        offset=5,
                                        nonconvex=True,
                                        maximum=1454))

        self.compare_lp_files('storage_invest_with_offset.lp')
예제 #14
0
    def test_nonconvex_invest_storage_all_nonconvex(self):
        """All invest variables are free and nonconvex."""
        b1 = solph.Bus(label='bus1')

        solph.components.GenericStorage(
            label='storage_all_nonconvex',
            inputs={
                b1:
                solph.Flow(investment=solph.Investment(nonconvex=True,
                                                       minimum=5,
                                                       offset=10,
                                                       maximum=30,
                                                       ep_costs=10))
            },
            outputs={
                b1:
                solph.Flow(investment=solph.Investment(nonconvex=True,
                                                       minimum=8,
                                                       offset=15,
                                                       ep_costs=10,
                                                       maximum=20))
            },
            investment=solph.Investment(nonconvex=True,
                                        ep_costs=20,
                                        offset=30,
                                        minimum=20,
                                        maximum=100))

        self.compare_lp_files('storage_invest_all_nonconvex.lp')
예제 #15
0
    def test_generic_invest_limit(self):
        """
        """
        bus = solph.Bus(label='bus_1')

        solph.Source(
            label='source_0',
            outputs={
                bus:
                solph.Flow(investment=solph.Investment(ep_costs=50, space=4))
            })

        solph.Source(
            label='source_1',
            outputs={
                bus:
                solph.Flow(investment=solph.Investment(ep_costs=100, space=1))
            })

        solph.Source(label='source_2',
                     outputs={
                         bus:
                         solph.Flow(investment=solph.Investment(ep_costs=75))
                     })

        om = self.get_om()

        om = solph.constraints.additional_investment_flow_limit(om,
                                                                "space",
                                                                limit=20)

        self.compare_lp_files('generic_invest_limit.lp', my_om=om)
예제 #16
0
def check_oemof_installation(silent=False):
    date_time_index = pd.date_range('1/1/2012', periods=5, freq='H')

    energysystem = solph.EnergySystem(timeindex=date_time_index)

    bgas = solph.Bus(label="natural_gas")
    bel = solph.Bus(label="electricity")
    solph.Sink(label='excess_bel', inputs={bel: solph.Flow()})
    solph.Source(label='rgas', outputs={bgas: solph.Flow()})
    solph.Sink(label='demand', inputs={bel: solph.Flow(
        actual_value=[10, 20, 30, 40, 50], fixed=True, nominal_value=1)})
    solph.Transformer(
        label="pp_gas",
        inputs={bgas: solph.Flow()},
        outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)},
        conversion_factors={bel: 0.58})
    om = solph.Model(energysystem)

    # check solvers
    solver = dict()
    for s in ['cbc', 'glpk', 'gurobi', 'cplex']:
        try:
            om.solve(solver=s)
            solver[s] = "working"
        except Exception:
            solver[s] = "not working"

    if not silent:
        print("*********")
        print('Solver installed with oemof:')
        for s, t in solver.items():
            print("{0}: {1}".format(s, t))
        print("*********")
        print("oemof successfully installed.")
예제 #17
0
def auxiliary_transformer(label, input_bus, output_bus):
    r"""
    Get auxiliary transformer for Generic Model energy system.

    Parameters
    ----------
    label : str
        Spezific label to reference transformer.

    input_bus : solph.Bus
        Spezific input bus to reference transformer.

    output_bus : solph.Bus
        Spezific output bus to reference transformer.

    Note
    ----
    Auxiliary transformers are used to represent more complex networks. In
    solph individual busses have to be connected by a componente, in this case
    by 'auxiliary transformer'. In the Generic Model, these are used for the
    solar thermal and storage strand.

    The flow is not transformed, but transferred in an auxiliary way to make
    the calculation feasible.
    """
    auxiliary_transformer = solph.Transformer(
        label=label,
        inputs={input_bus: solph.Flow()},
        outputs={output_bus: solph.Flow(nominal_value=1, max=inf, min=0.0)},
        conversion_factors={output_bus: 1})
    return auxiliary_transformer
예제 #18
0
def add_electricity_storages(table_collection, nodes):
    """

    Parameters
    ----------
    table_collection
    nodes

    Returns
    -------

    """
    for idx, params in table_collection["electricity storages"].iterrows():
        region = idx[0]
        name = idx[1]
        storage_label = Label("storage", "electricity", name, region)
        bus_label = Label("bus", "electricity", "all", region)
        nodes[storage_label] = solph.components.GenericStorage(
            label=storage_label,
            inputs={
                nodes[bus_label]: solph.Flow(
                    nominal_value=params["charge capacity"]
                )
            },
            outputs={
                nodes[bus_label]: solph.Flow(
                    nominal_value=params["discharge capacity"]
                )
            },
            nominal_storage_capacity=params["energy content"],
            loss_rate=params["loss rate"],
            initial_storage_level=None,
            inflow_conversion_factor=params["charge efficiency"],
            outflow_conversion_factor=params["discharge efficiency"],
        )
예제 #19
0
    def test_equate_variables_constraint(self):
        """Testing the equate_variables function in the constraint module."""
        bus1 = solph.Bus(label='Bus1')
        storage = solph.components.GenericStorage(
            label='storage_constraint',
            invest_relation_input_capacity=0.2,
            invest_relation_output_capacity=0.2,
            inputs={bus1: solph.Flow()},
            outputs={bus1: solph.Flow()},
            investment=solph.Investment(ep_costs=145))
        sink = solph.Sink(
            label='Sink',
            inputs={
                bus1: solph.Flow(investment=solph.Investment(ep_costs=500))
            })
        source = solph.Source(
            label='Source',
            outputs={
                bus1: solph.Flow(investment=solph.Investment(ep_costs=123))
            })
        om = self.get_om()
        solph.constraints.equate_variables(
            om, om.InvestmentFlow.invest[source, bus1],
            om.InvestmentFlow.invest[bus1, sink], 2)
        solph.constraints.equate_variables(
            om, om.InvestmentFlow.invest[source, bus1],
            om.GenericInvestmentStorageBlock.invest[storage])

        self.compare_lp_files('connect_investment.lp', my_om=om)
예제 #20
0
def add_storage(it, labels, nodes, busd):
    """Adds oemof.solph.GenericStorage objects to the list of components.

    If attribute `invest` is *True*, the investment version of the Storage is created.

    Parameters
    ----------
    it : pd.DataFrame
        Table of storage attributes of the producers / consumers.
    labels : dict
        Dictonary containing specifications for label-tuple.
    nodes : list
        All oemof.solph components are added to the list.
    busd : dict
        All oemof.solph.Bus objects are given by this dictionary.

    Returns
    -------
    list : Updated list of nodes.
    """

    for _, s in it.iterrows():

        label_storage = oh.Label(labels['l_1'], s['bus'], s['label'], labels['l_4'])
        label_bus = busd[(labels['l_1'], s['bus'], 'bus', labels['l_4'])]

        if s['invest']:

            epc_s = s['capex']

            nodes.append(
                solph.components.GenericStorage(
                    label=label_storage,
                    inputs={label_bus: solph.Flow()},
                    outputs={label_bus: solph.Flow()},
                    loss_rate=s['capacity_loss'],
                    fixed_losses_relative=s['fixed_losses_relative'],
                    invest_relation_input_capacity=s[
                        'invest_relation_input_capacity'],
                    invest_relation_output_capacity=s[
                        'invest_relation_output_capacity'],
                    inflow_conversion_factor=s['inflow_conversion_factor'],
                    outflow_conversion_factor=s[
                        'outflow_conversion_factor'],
                    investment=solph.Investment(ep_costs=epc_s)))

        else:
            nodes.append(
                solph.components.GenericStorage(
                    label=label_storage,
                    inputs={label_bus: solph.Flow()},
                    outputs={label_bus: solph.Flow()},
                    loss_rate=s['capacity_loss'],
                    fixed_losses_relative=s['fixed_losses_relative'],
                    nominal_storage_capacity=s['capacity'],
                    inflow_conversion_factor=s['inflow_conversion_factor'],
                    outflow_conversion_factor=s[
                        'outflow_conversion_factor']))

    return nodes
예제 #21
0
def add_transmission_lines_between_electricity_nodes(table_collection, nodes):
    """

    Parameters
    ----------
    table_collection
    nodes

    Returns
    -------

    """
    logging.debug("Add transmission lines to nodes dictionary.")
    power_lines = table_collection["power lines"]
    for idx, values in power_lines.iterrows():
        b1, b2 = idx.split("-")
        lines = [(b1, b2), (b2, b1)]
        for line in lines:
            line_label = Label("line", "electricity", line[0], line[1])
            bus_label_in = Label("bus", "electricity", "all", line[0])
            bus_label_out = Label("bus", "electricity", "all", line[1])
            if bus_label_in not in nodes:
                raise ValueError(
                    "Bus {0} missing for power line from {0} to {1}".format(
                        bus_label_in, bus_label_out
                    )
                )
            if bus_label_out not in nodes:
                raise ValueError(
                    "Bus {0} missing for power line from {0} to {1}".format(
                        bus_label_out, bus_label_in
                    )
                )
            if values.capacity != float("inf"):
                logging.debug(
                    "Line %s has a capacity of %s", line_label, values.capacity
                )
                nodes[line_label] = solph.Transformer(
                    label=line_label,
                    inputs={nodes[bus_label_in]: solph.Flow()},
                    outputs={
                        nodes[bus_label_out]: solph.Flow(
                            nominal_value=values.capacity
                        )
                    },
                    conversion_factors={
                        nodes[bus_label_out]: values.efficiency
                    },
                )
            else:
                logging.debug("Line %s has no capacity limit", line_label)
                nodes[line_label] = solph.Transformer(
                    label=line_label,
                    inputs={nodes[bus_label_in]: solph.Flow()},
                    outputs={nodes[bus_label_out]: solph.Flow()},
                    conversion_factors={
                        nodes[bus_label_out]: values.efficiency
                    },
                )
예제 #22
0
 def define_emission_limit():
     bel = solph.Bus(label='electricityBus')
     solph.Source(label='source1', outputs={bel: solph.Flow(
         nominal_value=100, emission=0.8)})
     solph.Source(label='source2', outputs={bel: solph.Flow(
         nominal_value=100)})
     om = self.get_om()
     solph.constraints.emission_limit(om, om.flows, limit=777)
def test_min_max_values_for_bidirectional_flow():
    a = solph.Flow(bidirectional=True)  # use default values
    b = solph.Flow(bidirectional=True, min=-0.9, max=0.9)
    assert a.bidirectional
    assert a.max[0] == 1
    assert a.min[0] == -1
    assert b.max[0] == 0.9
    assert b.min[0] == -0.9
예제 #24
0
def add_heatpipes(it, labels, gd, q, b_in, b_out, nodes):
    """
    Adds *HeatPipeline* objects with *Investment* attribute to the list of oemof.solph components.

    Parameters
    ----------
    it : pd.DataFrame
        Table of *Heatpipeline* attributes of the district heating grid
    labels : dict
        Dictonary containing specifications for label-tuple
    gd : dict
        Settings of the investment optimisation of the ThermalNetwork
    q : pd.Series
        Specific *Pipe* of ThermalNetwork
    b_in : oemof.solph.Bus
        Bus of Inflow
    b_out : oemof.solph.Bus
        Bus of Outflow
    nodes : list
        All oemof.solph components are added to the list

    Returns
    -------
    list : Updated list of nodes.
    """

    for _, t in it.iterrows():

        # definition of tag3 of label -> type of pipe
        labels['l_3'] = t['label_3']

        epc_p = t['capex_pipes'] * q['length']
        epc_fix = t['fix_costs'] * q['length']

        # Heatpipe with binary variable
        nc = bool(t['nonconvex'])

        # bidirectional heatpipelines yes or no
        flow_bi_args = {
            'bidirectional': True, 'min': -1}\
            if gd['bidirectional_pipes'] else {}

        nodes.append(oh.HeatPipeline(
            label=oh.Label(labels['l_1'], labels['l_2'],
                           labels['l_3'], labels['l_4']),
            inputs={b_in: solph.Flow(**flow_bi_args)},
            outputs={b_out: solph.Flow(
                nominal_value=None,
                **flow_bi_args,
                investment=solph.Investment(
                    ep_costs=epc_p, maximum=t['cap_max'],
                    minimum=t['cap_min'], nonconvex=nc, offset=epc_fix,
                ))},
            heat_loss_factor=t['l_factor'] * q['length'],
            heat_loss_factor_fix=t['l_factor_fix'] * q['length'],
        ))

    return nodes
예제 #25
0
def add_power_plants(table_collection, nodes):
    """

    Parameters
    ----------
    table_collection
    nodes

    Returns
    -------

    """
    pp = table_collection["power plants"]

    check_in_out_buses(nodes, pp, table_collection)

    for idx, params in pp.iterrows():
        region = idx[0]

        # Create label for in and out bus:
        fuel_bus = Label(
            "bus", "commodity", params.fuel, params["source region"]
        )
        bus_elec = Label("bus", "electricity", "all", region)

        # Create power plants as 1x1 Transformer if capacity > 0
        if params.capacity > 0:
            # if downtime_factor is in the parameters, use it
            if hasattr(params, "downtime_factor"):
                params.capacity *= 1 - params["downtime_factor"]

            # Define output flow with or without summed_max attribute
            if params.get("annual_limit_electricity", float("inf")) == float(
                "inf"
            ):
                outflow = solph.Flow(nominal_value=params.capacity)
            else:
                smax = params.annual_limit_electricity / params.capacity
                outflow = solph.Flow(
                    nominal_value=params.capacity, summed_max=smax
                )

            # if variable costs are defined add them to the outflow
            if hasattr(params, "variable_costs"):
                vc = params.variable_costs
                outflow.variable_costs = solph.sequence(vc)

            plant_name = idx[1].replace(" - ", "_").replace(".", "")

            trsf_label = Label("trsf", "pp", plant_name, region)

            nodes[trsf_label] = solph.Transformer(
                label=trsf_label,
                inputs={nodes[fuel_bus]: solph.Flow()},
                outputs={nodes[bus_elec]: outflow},
                conversion_factors={nodes[bus_elec]: params.efficiency},
            )
예제 #26
0
def test_flow_classes():
    with assert_raises(ValueError):
        solph.Flow(fixed=True)
    with assert_raises(ValueError):
        solph.Flow(investment=solph.Investment(), nominal_value=4)
    with assert_raises(ValueError):
        solph.Flow(investment=solph.Investment(), nonconvex=solph.NonConvex())
    with assert_raises(AttributeError):
        solph.Flow(fixed_costs=34)
예제 #27
0
 def test_flow_without_emission_for_emission_constraint_no_error(self):
     """
     """
     bel = solph.Bus(label='electricityBus')
     solph.Source(label='source1', outputs={bel: solph.Flow(
         nominal_value=100, emission=0.8)})
     solph.Source(label='source2', outputs={bel: solph.Flow(
         nominal_value=100)})
     om = self.get_om()
     solph.constraints.emission_limit(om, limit=777)
예제 #28
0
def test_generic_storage_3():
    """Nominal value defined with investment model."""
    bel = solph.Bus()
    solph.components.GenericStorage(
        label='storage4',
        nominal_storage_capacity=45,
        inputs={bel: solph.Flow(nominal_value=23, variable_costs=10e10)},
        outputs={bel: solph.Flow(nominal_value=7.5, variable_costs=10e10)},
        loss_rate=0.00, initial_storage_level=0,
        inflow_conversion_factor=1, outflow_conversion_factor=0.8)
예제 #29
0
def add_heatpipes_exist(pipes, labels, gd, q, b_in, b_out, nodes):
    """
    Adds *HeatPipeline* objects with fix capacity for existing pipes
    to the list of oemof.solph components.

    Parameters
    ----------
    pipes
    labels : dict
        Dictonary containing specifications for label-tuple.
    gd : dict
        Settings of the investment optimisation of the ThermalNetwork
    q : pd.Series
        Specific *Pipe* of ThermalNetwork
    b_in : oemof.solph.Bus
        Bus of Inflow
    b_out : oemof.solph.Bus
        Bus of Outflow
    nodes : list
        All oemof.solph components are added to the list

    Returns
    -------
    list : Updated list of nodes.
    """

    # get index of existing pipe label of pipe data
    ind_pipe = pipes[pipes['label_3'] == q['hp_type']].index[0]
    t = pipes.loc[ind_pipe]
    # get label of pipe
    labels['l_3'] = t['label_3']

    hlf = t['l_factor'] * q['length']
    hlff = t['l_factor_fix'] * q['length']

    flow_bi_args = {
        'bidirectional': True, 'min': -1} \
        if gd['bidirectional_pipes'] else {}

    outflow_args = {'nonconvex': solph.NonConvex()} if t['nonconvex'] else {}

    nodes.append(oh.HeatPipeline(
        label=oh.Label(labels['l_1'], labels['l_2'],
                       labels['l_3'], labels['l_4']),
        inputs={b_in: solph.Flow(**flow_bi_args)},
        outputs={b_out: solph.Flow(
            nominal_value=q['capacity'],
            **flow_bi_args,
            **outflow_args,
        )},
        heat_loss_factor=hlf,
        heat_loss_factor_fix=hlff,
    ))

    return nodes
예제 #30
0
    def test_storage_invest_4(self):
        """Only the storage capacity can be extended.
        """
        bel = solph.Bus(label='electricityBus')

        solph.components.GenericStorage(
            label='storage4',
            inputs={bel: solph.Flow(nominal_value=80)},
            outputs={bel: solph.Flow(nominal_value=100)},
            investment=solph.Investment(ep_costs=145, maximum=500))
        self.compare_lp_files('storage_invest_4.lp')