Source code for oemof.solph.components.offset_transformer

# -*- coding: utf-8 -

"""
OffsetTransformer and associated individual constraints (blocks) and groupings.

SPDX-FileCopyrightText: Uwe Krien <krien@uni-bremen.de>
SPDX-FileCopyrightText: Simon Hilpert
SPDX-FileCopyrightText: Cord Kaldemeyer
SPDX-FileCopyrightText: Patrik Schönfeldt
SPDX-FileCopyrightText: FranziPl
SPDX-FileCopyrightText: jnnr
SPDX-FileCopyrightText: Stephan Günther
SPDX-FileCopyrightText: FabianTU
SPDX-FileCopyrightText: Johannes Röder

SPDX-License-Identifier: MIT

"""

from oemof.network import network
from pyomo.core.base.block import SimpleBlock
from pyomo.environ import Constraint
from pyomo.environ import Set

from oemof.solph.plumbing import sequence as solph_sequence


[docs]class OffsetTransformer(network.Transformer): """An object with one input and one output. Parameters ---------- coefficients : tuple Tuple containing the first two polynomial coefficients i.e. the y-intersection and slope of a linear equation. The tuple values can either be a scalar or a sequence with length of time horizon for simulation. Notes ----- The sets, variables, constraints and objective parts are created * :py:class:`~oemof.solph.components.offset_transformer.OffsetTransformerBlock` Examples -------- >>> from oemof import solph >>> bel = solph.Bus(label='bel') >>> bth = solph.Bus(label='bth') >>> ostf = solph.components.OffsetTransformer( ... label='ostf', ... inputs={bel: solph.Flow( ... nominal_value=60, min=0.5, max=1.0, ... nonconvex=solph.NonConvex())}, ... outputs={bth: solph.Flow()}, ... coefficients=(20, 0.5)) >>> type(ostf) <class 'oemof.solph.components.offset_transformer.OffsetTransformer'> """ # noqa: E501 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if kwargs.get("coefficients") is not None: self.coefficients = tuple( [solph_sequence(i) for i in kwargs.get("coefficients")] ) if len(self.coefficients) != 2: raise ValueError( "Two coefficients or coefficient series have to be given." ) if len(self.inputs) == 1: for k, v in self.inputs.items(): if not v.nonconvex: raise TypeError( "Input flows must be of type NonConvexFlow!" ) if len(self.inputs) > 1 or len(self.outputs) > 1: raise ValueError( "Component `OffsetTransformer` must not have " + "more than 1 input and 1 output!" )
[docs] def constraint_group(self): return OffsetTransformerBlock
[docs]class OffsetTransformerBlock(SimpleBlock): r"""Block for the relation of nodes with type :class:`~oemof.solph.components.offset_transformer.OffsetTransformer` **The following constraints are created:** .. _OffsetTransformer-equations: .. math:: & P_{out}(t) = C_1(t) \cdot P_{in}(t) + C_0(t) \cdot Y(t) \\ .. csv-table:: Variables (V) and Parameters (P) :header: "symbol", "attribute", "type", "explanation" :widths: 1, 1, 1, 1 ":math:`P_{out}(t)`", "`flow[n, o, t]`", "V", "Power of output" ":math:`P_{in}(t)`", "`flow[i, n, t]`", "V","Power of input" ":math:`Y(t)`", "`status[i, n, t]`", "V","binary status variable of nonconvex input flow " ":math:`C_1(t)`", "`coefficients[1][n, t]`", "P", "linear coefficient 1 (slope)" ":math:`C_0(t)`", "`coefficients[0][n, t]`", "P", "linear coefficient 0 (y-intersection)" """ CONSTRAINT_GROUP = True def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def _create(self, group=None): """Creates the relation for the class:`OffsetTransformer`. Parameters ---------- group : list List of oemof.solph.custom.OffsetTransformer objects for which the relation of inputs and outputs is created e.g. group = [ostf1, ostf2, ostf3, ...]. The components inside the list need to hold an attribute `coefficients` of type dict containing the conversion factors for all inputs to outputs. """ if group is None: return None m = self.parent_block() self.OFFSETTRANSFORMERS = Set(initialize=[n for n in group]) def _relation_rule(block, n, t): """Link binary input and output flow to component outflow.""" expr = 0 expr += -m.flow[n, list(n.outputs.keys())[0], t] expr += ( m.flow[list(n.inputs.keys())[0], n, t] * n.coefficients[1][t] ) expr += ( m.NonConvexFlow.status[list(n.inputs.keys())[0], n, t] * n.coefficients[0][t] ) return expr == 0 self.relation = Constraint( self.OFFSETTRANSFORMERS, m.TIMESTEPS, rule=_relation_rule )