Source code for tespy.components.nodes.node

# -*- coding: utf-8

"""Module of class Node.


This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted
by the contributors recorded in the version control history of the file,
available from its original location tespy/components/nodes/node.py

SPDX-License-Identifier: MIT
"""

from tespy.components.component import component_registry
from tespy.components.nodes.merge import Merge
from tespy.components.nodes.splitter import Splitter
from tespy.tools.data_containers import ComponentMandatoryConstraints as dc_cmc
from tespy.tools.data_containers import SimpleDataContainer as dc_simple


[docs] @component_registry class Node(Splitter, Merge): r""" Class for combined merge and splitting points with multiple inflows and outflows. **Mandatory Equations** - :py:meth:`tespy.components.nodes.base.NodeBase.mass_flow_func` - :py:meth:`tespy.components.nodes.base.NodeBase.pressure_structure_matrix` - :py:meth:`tespy.components.nodes.node.Node.enthalpy_structure_matrix` - :py:meth:`tespy.components.nodes.node.Node.fluid_structure_matrix` - :py:meth:`tespy.components.nodes.merge.Merge.fluid_func` - :py:meth:`tespy.components.nodes.merge.Merge.energy_balance_func` Inlets/Outlets - specify number of inlets with :code:`num_in` (default value: 2) - specify number of outlets with :code:`num_in` (default value: 2) Image .. image:: /api/_images/Node.svg :alt: flowsheet of the node :align: center :class: only-light .. image:: /api/_images/Node_darkmode.svg :alt: flowsheet of the node :align: center :class: only-dark Parameters ---------- label : str The label of the component. design : list List containing design parameters (stated as String). offdesign : list List containing offdesign parameters (stated as String). design_path : str Path to the components design case. local_offdesign : boolean Treat this component in offdesign mode in a design calculation. local_design : boolean Treat this component in design mode in an offdesign calculation. char_warnings : boolean Ignore warnings on default characteristics usage for this component. printout : boolean Include this component in the network's results printout. num_in : float Number of inlets for this component, default value: 2. num_out : float Number of outlets for this component, default value: 2. Example ------- The :code:`Node` serves as a splitter and a merger at the same time. For example, you can use it to represent a preheating vessel, which produces saturated liquid water by mixing pumped condensate and a steam stream. The saturated liquid is then split into a specified amount of outlet streams. In this example it will be just two. >>> from tespy.components import Source, Sink, Node >>> from tespy.connections import Connection >>> from tespy.networks import Network >>> nw = Network(iterinfo=False) >>> nw.units.set_defaults(**{ ... "pressure": "bar", "temperature": "degC" ... }) >>> so1 = Source("source1") >>> so2 = Source("source2") >>> si1 = Sink("sink1") >>> si2 = Sink("sink2") >>> node = Node("node") >>> node.set_attr(num_in=2, num_out=2) >>> c1 = Connection(so1, "out1", node, "in1", label="pumped condensate") >>> c2 = Connection(so2, "out1", node, "in2", label="extraction steam") >>> c3 = Connection(node, "out1", si1, "in1", label="outlet 1") >>> c4 = Connection(node, "out2", si2, "in1", label="outlet 2") >>> nw.add_conns(c1, c2, c3, c4) We can parametrize the system, for example, to preheat 50 kg/s of water. The system will then identify, what amout of extraction steam is required to preheat the water to the saturated liquid state. Apart from the inlet states we have to add one mass flow specification to define the split ratio between the two outlets. .. note:: The enthalpy of the fluid will be identical at all exits. If you want to have separation of phasey, you have to use a `DropletSeparator` downstream of this component. >>> c1.set_attr(fluid={"water": 1}, m=50, p=3, T=50) >>> c2.set_attr(fluid={"water": 1}, T=200) >>> c3.set_attr(x=0) >>> c4.set_attr(m=1) >>> nw.solve("design") """
[docs] @staticmethod def get_parameters(): return { 'num_out': dc_simple(description="number of outlets"), 'num_in': dc_simple(description="number of inlets") }
[docs] def get_mandatory_constraints(self): return { 'mass_flow_constraints': dc_cmc(**{ 'func': self.mass_flow_func, 'dependents': self.mass_flow_dependents, 'num_eq_sets': 1, 'description': 'mass balance constraint' }), 'pressure_constraints': dc_cmc(**{ 'structure_matrix': self.pressure_structure_matrix, 'num_eq_sets': self.num_i + self.num_o - 1, 'description': 'pressure equality constraints' }), 'outlet_enthalpy_constraints': dc_cmc(**{ 'structure_matrix': self.enthalpy_structure_matrix, 'num_eq_sets': self.num_o - 1, 'description': 'equal enthalpy at all outlets constraint(s)' }), 'outlet_fluid_constraints': dc_cmc(**{ 'structure_matrix': self.fluid_structure_matrix, 'num_eq_sets': self.num_o - 1, 'description': 'equal fluid at all outlets constraint(s)' }), 'fluid_constraints': dc_cmc(**{ 'num_eq_sets': 1, 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'dependents': self.fluid_dependents, 'description': 'fluid mass fraction constraints' }), 'energy_balance_constraints': dc_cmc(**{ 'num_eq_sets': 1, 'func': self.energy_balance_func, 'dependents': self.energy_balance_dependents, 'description': 'energy balance constraint' }) }
[docs] def inlets(self): if self.num_in.is_set: return [f'in{i + 1}' for i in range(self.num_in.val)] else: self.set_attr(num_in=2) return self.inlets()
[docs] def outlets(self): if self.num_out.is_set: return [f'out{i + 1}' for i in range(self.num_out.val)] else: self.set_attr(num_out=2) return self.outlets()
[docs] def enthalpy_structure_matrix(self, k): r""" Set up the structure matrix for the outlet enthalpy constraints: All outlet enthalpy values must be identical. """ for eq, conn in enumerate(self.outl[1:]): self._structure_matrix[k + eq, self.outl[0].h.sm_col] = 1 self._structure_matrix[k + eq, conn.h.sm_col] = -1
[docs] def fluid_structure_matrix(self, k): r""" Set up the structure matrix for the outlet fluid constraints: All outlet fluid compositions must be identical. """ for eq, conn in enumerate(self.outl[1:]): self._structure_matrix[k + eq, self.outl[0].fluid.sm_col] = 1 self._structure_matrix[k + eq, conn.fluid.sm_col] = -1