def eta_s_char_func(self): r""" Equation for given isentropic efficiency characteristic. Returns ------- residual : float Residual value of equation. .. math:: 0 = \left(h_{out}-h_{in}\right) \cdot \eta_{s,design} \cdot f\left( expr \right) -\left( h_{out,s} - h_{in} \right) """ p = self.eta_s_char.param expr = self.get_char_expr(p, **self.eta_s_char.char_params) if not expr: msg = ('Please choose a valid parameter, you want to link the ' 'isentropic efficiency to at component ' + self.label + '.') logging.error(msg) raise ValueError(msg) i = self.inl[0] o = self.outl[0] return ( self.eta_s.design * self.eta_s_char.char_func.evaluate(expr) * (o.h.val_SI - i.h.val_SI) - (isentropic(i.get_flow(), o.get_flow(), T0=self.inl[0].T.val_SI) - i.h.val_SI))
def calc_parameters(self): r"""Postprocessing parameter calculation.""" Turbomachine.calc_parameters(self) self.eta_s.val = ( (isentropic(self.inl[0].get_flow(), self.outl[0].get_flow(), T0=self.inl[0].T.val_SI) - self.inl[0].h.val_SI) / (self.outl[0].h.val_SI - self.inl[0].h.val_SI))
def eta_s_func(self): r""" Equation for given isentropic efficiency of a compressor. Returns ------- residual : float Residual value of equation. .. math:: 0 = -\left( h_{out} - h_{in} \right) \cdot \eta_{s} + \left( h_{out,s} - h_{in} \right) """ return ( -(self.outl[0].h.val_SI - self.inl[0].h.val_SI) * self.eta_s.val + (isentropic(self.inl[0].get_flow(), self.outl[0].get_flow(), T0=self.inl[0].T.val_SI) - self.inl[0].h.val_SI))
def char_map_eta_s_func(self): r""" Calculate isentropic efficiency from characteristic map. Returns ------- residual : float Residual value of equation. Note ---- - X: speedline index (rotational speed is constant) - Y: nondimensional mass flow - igva: variable inlet guide vane angle for value manipulation according to :cite:`GasTurb2018`. .. math:: X = \sqrt{\frac{T_\mathrm{in,design}}{T_\mathrm{in}}}\\ Y = \frac{\dot{m}_\mathrm{in} \cdot p_\mathrm{in,design}} {\dot{m}_\mathrm{in,design} \cdot p_\mathrm{in} \cdot X}\\ \vec{Y} = f\left(X,Y\right)\cdot\left(1-\frac{igva}{100}\right)\\ \vec{Z}=f\left(X,Y\right)\cdot\left(1-\frac{igva^2}{10000}\right)\\ 0 = \frac{\eta_\mathrm{s}}{\eta_\mathrm{s,design}} - f\left(Y,\vec{Y},\vec{Z}\right) """ i = self.inl[0] o = self.outl[0] T = T_mix_ph(i.get_flow(), T0=i.T.val_SI) x = np.sqrt(i.T.design / T) y = (i.m.val_SI * i.p.design) / (i.m.design * i.p.val_SI * x) yarr, zarr = self.char_map_eta_s.char_func.evaluate_x(x) # value manipulation with igva yarr *= (1 - self.igva.val / 100) zarr *= (1 - self.igva.val ** 2 / 10000) eta = self.char_map_eta_s.char_func.evaluate_y(y, yarr, zarr) return ( (isentropic(i.get_flow(), o.get_flow(), T0=T) - i.h.val_SI) / (o.h.val_SI - i.h.val_SI) / self.eta_s.design - eta)
def test_Compressor(self): """Test component properties of compressors.""" instance = Compressor('compressor') self.setup_network(instance) # compress NH3, other fluids in network are for turbine, pump, ... fl = {'N2': 1, 'O2': 0, 'Ar': 0, 'DowQ': 0, 'NH3': 0} self.c1.set_attr(fluid=fl, v=1, p=1, T=5) self.c2.set_attr(p=6) instance.set_attr(eta_s=0.8) self.nw.solve('design') convergence_check(self.nw.lin_dep) self.nw.save('tmp') # test isentropic efficiency value eta_s_d = ((isentropic(self.c1.get_flow(), self.c2.get_flow()) - self.c1.h.val_SI) / (self.c2.h.val_SI - self.c1.h.val_SI)) msg = ('Value of isentropic efficiency must be ' + str(eta_s_d) + ', is ' + str(instance.eta_s.val) + '.') assert round(eta_s_d, 3) == round(instance.eta_s.val, 3), msg # trigger invalid value for isentropic efficiency instance.set_attr(eta_s=1.1) self.nw.solve('design') convergence_check(self.nw.lin_dep) # test calculated value eta_s = ((isentropic(self.c1.get_flow(), self.c2.get_flow()) - self.c1.h.val_SI) / (self.c2.h.val_SI - self.c1.h.val_SI)) msg = ('Value of isentropic efficiency must be ' + str(eta_s) + ', is ' + str(instance.eta_s.val) + '.') assert round(eta_s, 3) == round(instance.eta_s.val, 3), msg # remove pressure at outlet, use characteristic map for pressure # rise calculation self.c2.set_attr(p=np.nan) instance.set_attr(char_map_pr={ 'char_func': ldc('compressor', 'char_map_pr', 'DEFAULT', CharMap), 'is_set': True }, char_map_eta_s={ 'char_func': ldc('compressor', 'char_map_eta_s', 'DEFAULT', CharMap), 'is_set': True }, eta_s=np.nan, igva=0) # offdesign test, efficiency value should be at design value self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) msg = ('Value of isentropic efficiency (' + str(instance.eta_s.val) + ') must be identical to design case (' + str(eta_s) + ').') assert round(eta_s_d, 2) == round(instance.eta_s.val, 2), msg # move to highest available speedline, mass flow below lowest value # at that line self.c1.set_attr(v=np.nan, m=self.c1.m.val * 0.8, T=-30) self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) # should be value eta_s = eta_s_d * instance.char_map_eta_s.char_func.z[6, 0] msg = ('Value of isentropic efficiency (' + str(instance.eta_s.val) + ') must be at (' + str(round(eta_s, 4)) + ').') assert round(eta_s, 4) == round(instance.eta_s.val, 4), msg # going below lowest available speedline, above highest mass flow at # that line self.c1.set_attr(T=175) self.nw.solve('offdesign', design_path='tmp', init_path='tmp') convergence_check(self.nw.lin_dep) # should be value eta_s = eta_s_d * instance.char_map_eta_s.char_func.z[0, 9] msg = ('Value of isentropic efficiency (' + str(instance.eta_s.val) + ') must be at (' + str(round(eta_s, 4)) + ').') assert round(eta_s, 4) == round(instance.eta_s.val, 4), msg # back to design properties, test eta_s_char self.c2.set_attr(p=6) self.c1.set_attr(v=1, T=5, m=np.nan) # test parameter specification for eta_s_char with unset char map instance.set_attr( eta_s_char={ 'char_func': ldc('compressor', 'eta_s_char', 'DEFAULT', CharLine), 'is_set': True, 'param': 'm' }) instance.char_map_eta_s.is_set = False instance.char_map_pr.is_set = False self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) msg = ('Value of isentropic efficiency must be ' + str(eta_s_d) + ', is ' + str(instance.eta_s.val) + '.') assert round(eta_s_d, 3) == round(instance.eta_s.val, 3), msg # move up in volumetric flow self.c1.set_attr(v=1.5) self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) eta_s = round( eta_s_d * instance.eta_s_char.char_func.evaluate( self.c1.m.val_SI / self.c1.m.design), 3) msg = ('Value of isentropic efficiency must be ' + str(eta_s) + ', is ' + str(round(instance.eta_s.val, 3)) + '.') assert eta_s == round(instance.eta_s.val, 3), msg # test parameter specification for pr instance.eta_s_char.set_attr(param='pr') self.c1.set_attr(v=1) self.c2.set_attr(p=6) self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) expr = (self.c2.p.val_SI * self.c1.p.design / (self.c2.p.design * self.c1.p.val_SI)) eta_s = round(eta_s_d * instance.eta_s_char.char_func.evaluate(expr), 3) msg = ('Value of isentropic efficiency must be ' + str(eta_s) + ', is ' + str(round(instance.eta_s.val, 3)) + '.') assert eta_s == round(instance.eta_s.val, 3), msg shutil.rmtree('./tmp', ignore_errors=True)
def test_Turbine(self): """Test component properties of turbines.""" instance = Turbine('turbine') self.setup_network(instance) fl = {'N2': 0.7556, 'O2': 0.2315, 'Ar': 0.0129, 'DowQ': 0, 'NH3': 0} self.c1.set_attr(fluid=fl, m=15, p=10) self.c2.set_attr(p=1, T=25) instance.set_attr(eta_s=0.85) self.nw.solve('design') convergence_check(self.nw.lin_dep) self.nw.save('tmp') # design value of isentropic efficiency eta_s_d = ((self.c2.h.val_SI - self.c1.h.val_SI) / (isentropic(self.c1.get_flow(), self.c2.get_flow()) - self.c1.h.val_SI)) msg = ('Value of isentropic efficiency must be ' + str(round(eta_s_d, 3)) + ', is ' + str(instance.eta_s.val) + '.') assert round(eta_s_d, 3) == round(instance.eta_s.val, 3), msg # trigger invalid value for isentropic efficiency instance.set_attr(eta_s=1.1) self.nw.solve('design') convergence_check(self.nw.lin_dep) eta_s = ((self.c2.h.val_SI - self.c1.h.val_SI) / (isentropic(self.c1.get_flow(), self.c2.get_flow()) - self.c1.h.val_SI)) msg = ('Value of isentropic efficiency must be ' + str(eta_s) + ', is ' + str(instance.eta_s.val) + '.') assert round(eta_s, 3) == round(instance.eta_s.val, 3), msg # unset isentropic efficiency and inlet pressure, # use characteristcs and cone law instead, parameters have to be in # design state self.c1.set_attr(p=np.nan) instance.cone.is_set = True instance.eta_s_char.is_set = True instance.eta_s.is_set = False self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) # check efficiency msg = ('Value of isentropic efficiency (' + str(instance.eta_s.val) + ') must be identical to design case (' + str(eta_s_d) + ').') assert round(eta_s_d, 2) == round(instance.eta_s.val, 2), msg # check pressure msg = ('Value of inlet pressure (' + str(round(self.c1.p.val_SI)) + ') must be identical to design case (' + str(round(self.c1.p.design)) + ').') assert round(self.c1.p.design) == round(self.c1.p.val_SI), msg # lowering mass flow, inlet pressure must sink according to cone law self.c1.set_attr(m=self.c1.m.val * 0.8) self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) msg = ('Value of pressure ratio (' + str(instance.pr.val) + ') must be at (' + str(0.128) + ').') assert 0.128 == round(instance.pr.val, 3), msg # testing more parameters for eta_s_char # test parameter specification v self.c1.set_attr(m=10) instance.eta_s_char.param = 'v' self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) expr = self.c1.v.val_SI / self.c1.v.design eta_s = round(eta_s_d * instance.eta_s_char.char_func.evaluate(expr), 3) msg = ('Value of isentropic efficiency (' + str(round(instance.eta_s.val, 3)) + ') must be (' + str(eta_s) + ').') assert eta_s == round(instance.eta_s.val, 3), msg # test parameter specification pr instance.eta_s_char.param = 'pr' self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) expr = (self.c2.p.val_SI * self.c1.p.design / (self.c2.p.design * self.c1.p.val_SI)) eta_s = round(eta_s_d * instance.eta_s_char.char_func.evaluate(expr), 3) msg = ('Value of isentropic efficiency (' + str(round(instance.eta_s.val, 3)) + ') must be (' + str(eta_s) + ').') assert eta_s == round(instance.eta_s.val, 3), msg shutil.rmtree('./tmp', ignore_errors=True)
def test_Pump(self): """Test component properties of pumps.""" instance = Pump('pump') self.setup_network(instance) fl = {'N2': 0, 'O2': 0, 'Ar': 0, 'DowQ': 1, 'NH3': 0} self.c1.set_attr(fluid=fl, v=1, p=5, T=50) self.c2.set_attr(p=7) instance.set_attr(eta_s=1) self.nw.solve('design') convergence_check(self.nw.lin_dep) # test calculated value for efficiency eta_s = ((isentropic(self.c1.get_flow(), self.c2.get_flow()) - self.c1.h.val_SI) / (self.c2.h.val_SI - self.c1.h.val_SI)) msg = ('Value of isentropic efficiency must be ' + str(eta_s) + ', is ' + str(instance.eta_s.val) + '.') assert eta_s == instance.eta_s.val, msg # isentropic efficiency of 1 means inlet and outlet entropy are # identical s1 = round(s_mix_ph(self.c1.get_flow()), 4) s2 = round(s_mix_ph(self.c2.get_flow()), 4) msg = ('Value of entropy must be identical for inlet (' + str(s1) + ') and outlet (' + str(s2) + ') at 100 % isentropic efficiency.') assert s1 == s2, msg # specify realistic value for efficiency, outlet pressure from flow # char eta_s_d = 0.8 instance.set_attr(eta_s=eta_s_d) self.nw.solve('design') convergence_check(self.nw.lin_dep) self.nw.save('tmp') self.c2.set_attr(p=np.nan) # flow char (pressure rise vs. volumetric flow) x = [0, 0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4] y = np.array([14, 13.5, 12.5, 11, 9, 6.5, 3.5, 0]) * 1e5 char = {'char_func': CharLine(x, y), 'is_set': True} # apply flow char and eta_s char instance.set_attr(flow_char=char, eta_s=np.nan, eta_s_char={ 'char_func': ldc('pump', 'eta_s_char', 'DEFAULT', CharLine), 'is_set': True }) self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) # value for difference pressure dp = 650000.0 msg = ('Value of pressure rise must be ' + str(dp) + ', is ' + str(self.c2.p.val_SI - self.c1.p.val_SI) + '.') assert round(self.c2.p.val_SI - self.c1.p.val_SI, 0) == dp, msg # test ohter volumetric flow on flow char self.c1.set_attr(v=0.9) self.nw.solve('offdesign', design_path='tmp') convergence_check(self.nw.lin_dep) dp = 775000.0 msg = ('Value of pressure rise must be ' + str(dp) + ', is ' + str(round(self.c2.p.val_SI - self.c1.p.val_SI, 0)) + '.') assert round(self.c2.p.val_SI - self.c1.p.val_SI, 0) == dp, msg # test value of isentropic efficiency eta_s = round( eta_s_d * instance.eta_s_char.char_func.evaluate( self.c1.v.val_SI / self.c1.v.design), 3) msg = ('Value of isentropic efficiency must be ' + str(eta_s) + ', is ' + str(instance.eta_s.val) + '.') assert eta_s == round(instance.eta_s.val, 3), msg instance.eta_s_char.is_set = False # test boundaries of characteristic line: # lower boundary instance.set_attr(eta_s=0.8) self.c1.set_attr(m=0, v=None) self.nw.solve('design') convergence_check(self.nw.lin_dep) msg = ('Value of power must be ' + str(14e5) + ', is ' + str(round(self.c2.p.val_SI - self.c1.p.val_SI, 0)) + '.') assert round(self.c2.p.val_SI - self.c1.p.val_SI, 0) == 14e5, msg # upper boundary self.c1.set_attr(v=1.5, m=None) self.nw.solve('design') convergence_check(self.nw.lin_dep) msg = ('Value of power must be 0, is ' + str(round(self.c2.p.val_SI - self.c1.p.val_SI, 0)) + '.') assert round(self.c2.p.val_SI - self.c1.p.val_SI, 0) == 0, msg shutil.rmtree('./tmp', ignore_errors=True)