From b5206a890c4b92a8a5c8acece7a4a18d18d9ac38 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 14:11:10 +0100 Subject: [PATCH] constraints are now inherited and deleted if necessary. Added SplitterWithPressureLoss example --- .../newComponentsTests/SplitterWithDeltaP.py | 57 +++++ .../simple_heatex_for_jorrit.py | 4 +- src/tespy/components/newcomponents.py | 242 ++++-------------- 3 files changed, 104 insertions(+), 199 deletions(-) create mode 100644 intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py diff --git a/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py new file mode 100644 index 000000000..582b88c91 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py @@ -0,0 +1,57 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitterWithPressureLoss + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +se = SplitterWithPressureLoss("Splitter",num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c2.set_attr(m=0.6) + +c2.set_attr(p=1.1) +c3.set_attr(p=1.0) + +# add some guess values +#c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) +#c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +# use delta P +c2.set_attr(p=None) +c3.set_attr(p=None) +se.set_attr(deltaP=0.25) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) diff --git a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py index 04a42c857..548c57893 100644 --- a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py +++ b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py @@ -20,7 +20,7 @@ nw.add_conns(c1, c2) # set some conditions on connections -c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 0.9, "T66": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) c2.set_attr(T=50) # set some conditions on component @@ -52,7 +52,7 @@ nw.add_conns(c1, c2) # set some conditions on connections -c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 1}) c2.set_attr(T=50) # set some conditions on component diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 7c1a3c4e1..ae1464e1b 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -268,35 +268,10 @@ def get_parameters(self): ) return variables - def get_mandatory_constraints(self): - - - variable_fluids = set( - [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] - ) - num_fluid_eq = len(variable_fluids) - - if num_fluid_eq == 0: - num_fluid_eq = len(self.inl[0].fluid.val) - num_m_eq = 0 - else: - num_m_eq = 1 - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': num_m_eq}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': 1} - } + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + return constraints def deltaP_func(self): r""" @@ -331,6 +306,14 @@ def calc_parameters(self): class SplitterWithPressureLoss(Splitter): + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + super().__init__(label, **kwargs) + @staticmethod def component(): return 'Splitter with pressure losses' @@ -339,42 +322,22 @@ def get_parameters(self): variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, + deriv=self.deltaP_deriv, + func=self.deltaP_func, latex=self.pr_func_doc, num_eq=self.num_out, ) return variables def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - } + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + return constraints - def pr_func(self): + def deltaP_func(self): r""" Equation for pressure drop. - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ #return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI residual = [] @@ -383,25 +346,18 @@ def pr_func(self): residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] return residual - def pr_deriv(self, increment_filter, k): + def deltaP_deriv(self, increment_filter, k): r""" Calculate the partial derivatives for combustion pressure ratio. - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. """ - # self.jacobian[k, 0, 1] = self.pr.val - # self.jacobian[k, self.num_i, 1] = -1 - j = 0 - for c in self.outl: - self.jacobian[k, 0, 1] = 1 - self.jacobian[k, j + 1, 1] = -1 - j += 1 + + i = self.inl[0] + for o in self.outl: + if i.p.is_var: + self.jacobian[k, i.p.J_col] = 1 + if o.p.is_var: + self.jacobian[k, o.p.J_col] = -1 k += 1 def calc_parameters(self): @@ -426,7 +382,6 @@ def __init__(self, label, **kwargs): super().__init__(label, **kwargs) - @staticmethod def component(): return 'separator with species flow splits' @@ -444,16 +399,8 @@ def get_parameters(self): def SFS_func(self): r""" - Equation for pressure drop. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: + Equation for SFS. - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ # residual = [] # for fluid, x in self.inl[0].fluid.val.items(): @@ -476,15 +423,8 @@ def SFS_func(self): def SFS_deriv(self, increment_filter, k): r""" - Calculate the partial derivatives for combustion pressure ratio. + Calculate the partial derivatives for SFS. - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. """ # j=0 @@ -549,48 +489,14 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - self.variable_fluids = set( - [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] - ) - num_fluid_eq = len(self.variable_fluids) - if num_fluid_eq == 0: - num_fluid_eq = 1 - self.variable_fluids = [list(self.inl[0].fluid.is_set)[0]] - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq}, - # 'energy_balance_constraints': { - # 'func': self.energy_balance_func, - # 'deriv': self.energy_balance_deriv, - # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - # 'num_eq': self.num_o}, - 'pressure_constraints': { - 'func': self.pressure_equality_func, - 'deriv': self.pressure_equality_deriv, - 'constant_deriv': True, - 'latex': self.pressure_equality_func_doc, - 'num_eq': self.num_i + self.num_o - 1} - } + constraints = super().get_mandatory_constraints() + del constraints['energy_balance_constraints'] + return constraints def energy_balance_deltaT_func(self): r""" - Calculate energy balance. - - Returns - ------- - residual : list - Residual value of energy balance. + Calculate delta T derivatives. - .. math:: - - 0 = T_{in} - T_{out,j}\\ - \forall j \in \text{outlets} """ residual = [] T_in = T_mix_ph(self.inl[0].get_flow(), T0=self.inl[0].T.val_SI) @@ -622,25 +528,22 @@ def get_parameters(self): variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, + deriv=self.deltaP_deriv, + func=self.deltaP_func, latex=self.pr_func_doc, num_eq=self.num_out, ) return variables - def pr_func(self): + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + return constraints + + def deltaP_func(self): r""" Equation for pressure drop. - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ residual = [] p_in = self.inl[0].p.val_SI @@ -648,17 +551,10 @@ def pr_func(self): residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] return residual - def pr_deriv(self, increment_filter, k): + def deltaP_deriv(self, increment_filter, k): r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. + Calculate the partial derivatives for pressure drop - k : int - Position of equation in Jacobian matrix. """ j = 0 for c in self.outl: @@ -678,30 +574,6 @@ def calc_parameters(self): self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - # 'pressure_constraints': { - # 'func': self.pressure_equality_func, - # 'deriv': self.pressure_equality_deriv, - # 'constant_deriv': True, - # 'latex': self.pressure_equality_func_doc, - # 'num_eq': self.num_i + self.num_o - 1} - } - - class SeparatorWithSpeciesSplitsAndDeltaTAndPr(SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndPr): @staticmethod @@ -713,34 +585,10 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - self.variable_fluids = set( - [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] - ) - num_fluid_eq = len(self.variable_fluids) - if num_fluid_eq == 0: - num_fluid_eq = 1 - self.variable_fluids = [list(self.inl[0].fluid.is_set)[0]] - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq}, - # 'energy_balance_constraints': { - # 'func': self.energy_balance_func, - # 'deriv': self.energy_balance_deriv, - # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - # 'num_eq': self.num_o}, - # 'pressure_constraints': { - # 'func': self.pressure_equality_func, - # 'deriv': self.pressure_equality_deriv, - # 'constant_deriv': True, - # 'latex': self.pressure_equality_func_doc, - # 'num_eq': self.num_i + self.num_o - 1} - } + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints class SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus(SeparatorWithSpeciesSplitsAndDeltaTAndPr):