def energy_group_func(self): r""" Equation for solar collector energy balance. Returns ------- residual : float Residual value of equation. .. math:: \begin{split} 0 = & \dot{m} \cdot \left( h_{out} - h_{in} \right)\\ & - A \cdot \left[E \cdot \eta_{opt} - \alpha_1 \cdot \left(T_m - T_{amb} \right) - \alpha_2 \cdot \left(T_m - T_{amb}\right)^2 \right]\\ T_m = & \frac{T_{out} + T_{in}}{2}\\ \end{split} Reference: :cite:`Quaschning2013`. """ i = self.inl[0].get_flow() o = self.outl[0].get_flow() T_m = (T_mix_ph(i, T0=self.inl[0].T.val_SI) + T_mix_ph(o, T0=self.outl[0].T.val_SI)) / 2 return (i[0] * (o[2] - i[2]) - self.A.val * ( self.E.val * self.eta_opt.val - (T_m - self.Tamb.val_SI) * self.lkf_lin.val - self.lkf_quad.val * (T_m - self.Tamb.val_SI) ** 2))
def additional_equations(self, k): r""" Calculate vector vec_res with results of additional equations. Equations **mandatroy equations** .. math:: 0 = fluid_{i,in} - fluid_{i,out_{j}} \; \forall i \in \mathrm{fluid}, \; \forall j \in outlets .. math:: 0 = T_{in} - T_{out,i} \; \forall i \in \mathrm{outlets} """ ###################################################################### # equations for fluid balance for fluid, x in self.inl[0].fluid.val.items(): res = x * self.inl[0].m.val_SI for o in self.outl: res -= o.fluid.val[fluid] * o.m.val_SI self.vec_res[k] = res k += 1 ###################################################################### # equations for energy balance for o in self.outl: self.vec_res[k] = ( T_mix_ph(self.inl[0].to_flow(), T0=self.inl[0].T.val_SI) - T_mix_ph(o.to_flow(), T0=o.T.val_SI)) k += 1
def kA_char_func(self): r""" Calculate heat transfer from heat transfer coefficient characteristic. Returns ------- residual : float Residual value of equation. .. math:: 0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + kA_{design} \cdot f_{kA} \cdot \frac{T_{out,1} - T_{in,2} - T_{sat} \left(p_{in,1}\right) + T_{out,2}} {\ln{\frac{T_{out,1} - T_{in,2}} {T_{sat} \left(p_{in,1}\right) - T_{out,2}}}} f_{kA} = \frac{2}{\frac{1}{f_1 \left( expr_1\right)} + \frac{1}{f_2 \left( expr_2\right)}} Note ---- For standard functions f\ :subscript:`1` \ and f\ :subscript:`2` \ see module :py:mod:`tespy.data`. """ p1 = self.kA_char1.param p2 = self.kA_char2.param f1 = self.get_char_expr(p1, **self.kA_char1.char_params) f2 = self.get_char_expr(p2, **self.kA_char2.char_params) i1 = self.inl[0] i2 = self.inl[1] o1 = self.outl[0] o2 = self.outl[1] # temperature value manipulation for convergence stability T_i1 = T_bp_p(i1.get_flow()) T_i2 = T_mix_ph(i2.get_flow(), T0=i2.T.val_SI) T_o1 = T_mix_ph(o1.get_flow(), T0=o1.T.val_SI) T_o2 = T_mix_ph(o2.get_flow(), T0=o2.T.val_SI) if T_i1 <= T_o2 and not i1.T.val_set: T_i1 = T_o2 + 0.5 if T_i1 <= T_o2 and not o2.T.val_set: T_o2 = T_i1 - 0.5 if T_o1 <= T_i2 and not o1.T.val_set: T_o1 = T_i2 + 1 if T_o1 <= T_i2 and not i2.T.val_set: T_i2 = T_o1 - 1 td_log = ((T_o1 - T_i2 - T_i1 + T_o2) / np.log((T_o1 - T_i2) / (T_i1 - T_o2))) fkA1 = self.kA_char1.char_func.evaluate(f1) fkA2 = self.kA_char2.char_func.evaluate(f2) fkA = 2 / (1 / fkA1 + 1 / fkA2) return ( i1.m.val_SI * (o1.h.val_SI - i1.h.val_SI) + self.kA.design * fkA * td_log)
def kA_char_group_func(self): r""" Calculate heat transfer from heat transfer coefficient characteristic. Returns ------- residual : float Residual value of equation. .. math:: 0 = \dot{m}_{in} \cdot \left( h_{out} - h_{in}\right) + kA_{design} \cdot f_{kA} \cdot \Delta T_{log} \Delta T_{log} = \begin{cases} \frac{T_{in}-T_{out}}{\ln{\frac{T_{in}-T_{amb}} {T_{out}-T_{amb}}}} & T_{in} > T_{out} \\ \frac{T_{out}-T_{in}}{\ln{\frac{T_{out}-T_{amb}} {T_{in}-T_{amb}}}} & T_{in} < T_{out}\\ 0 & T_{in} = T_{out} \end{cases} f_{kA} = \frac{2}{1 + \frac{1}{f\left( expr\right)}} T_{amb}: \text{ambient temperature} Note ---- For standard function of f\ :subscript:`kA` \ see module :py:mod:`tespy.data`. """ p = self.kA_char.param expr = self.get_char_expr(p, **self.kA_char.char_params) i, o = self.inl[0].get_flow(), self.outl[0].get_flow() # For numerical stability: If temperature differences have # different sign use mean difference to avoid negative logarithm. ttd_1 = T_mix_ph(i, T0=self.inl[0].T.val_SI) - self.Tamb.val_SI ttd_2 = T_mix_ph(o, T0=self.outl[0].T.val_SI) - self.Tamb.val_SI if (ttd_1 / ttd_2) < 0: td_log = (ttd_2 + ttd_1) / 2 elif ttd_1 > ttd_2: td_log = (ttd_1 - ttd_2) / np.log(ttd_1 / ttd_2) elif ttd_1 < ttd_2: td_log = (ttd_2 - ttd_1) / np.log(ttd_2 / ttd_1) else: td_log = 0 fkA = 2 / (1 + 1 / self.kA_char.char_func.evaluate(expr)) return i[0] * (o[2] - i[2]) + self.kA.design * fkA * td_log
def gas_temperature_func(self): r""" Equation for temperature equality of product gases. Returns ------- residual : float Residual value of equation. .. math:: 0 = T_\mathrm{out,2} - T_\mathrm{out,3} """ return (T_mix_ph(self.outl[1].get_flow()) - T_mix_ph(self.outl[2].get_flow()))
def ttd_l_func(self): r""" Equation for upper terminal temperature difference. Returns ------- residual : float Residual value of equation. .. math:: 0 = ttd_{l} - T_{out,1} + T_{in,2} """ T_i2 = T_mix_ph(self.inl[1].get_flow(), T0=self.inl[1].T.val_SI) T_o1 = T_mix_ph(self.outl[0].get_flow(), T0=self.outl[0].T.val_SI) return self.ttd_l.val - T_o1 + T_i2
def desuperheat(ude): ttd_min = ude.params['ttd_min'] return ( ude.conns[0].h.val_SI - ude.conns[1].h.val_SI - ude.params['distance'] * ( ude.conns[0].h.val_SI - h_mix_pT( ude.conns[1].get_flow(), T_mix_ph(ude.conns[2].get_flow()) + ttd_min)))
def energy_balance_func(self): r""" Calculate energy balance. Returns ------- residual : list Residual value of energy balance. .. 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) for o in self.outl: residual += [T_in - T_mix_ph(o.get_flow(), T0=o.T.val_SI)] return residual
def kA_group_func(self): r""" Calculate heat transfer from heat transfer coefficient. Returns ------- residual : float Residual value of equation. .. math:: 0 = \dot{m}_{in} \cdot \left( h_{out} - h_{in}\right) + kA \cdot \Delta T_{log} \Delta T_{log} = \begin{cases} \frac{T_{in}-T_{out}}{\ln{\frac{T_{in}-T_{amb}} {T_{out}-T_{amb}}}} & T_{in} > T_{out} \\ \frac{T_{out}-T_{in}}{\ln{\frac{T_{out}-T_{amb}} {T_{in}-T_{amb}}}} & T_{in} < T_{out}\\ 0 & T_{in} = T_{out} \end{cases} T_{amb}: \text{ambient temperature} """ i, o = self.inl[0].get_flow(), self.outl[0].get_flow() ttd_1 = T_mix_ph(i, T0=self.inl[0].T.val_SI) - self.Tamb.val_SI ttd_2 = T_mix_ph(o, T0=self.outl[0].T.val_SI) - self.Tamb.val_SI # For numerical stability: If temperature differences have # different sign use mean difference to avoid negative logarithm. if (ttd_1 / ttd_2) < 0: td_log = (ttd_2 + ttd_1) / 2 elif ttd_1 > ttd_2: td_log = (ttd_1 - ttd_2) / np.log(ttd_1 / ttd_2) elif ttd_1 < ttd_2: td_log = (ttd_2 - ttd_1) / np.log(ttd_2 / ttd_1) else: td_log = 0 return i[0] * (o[2] - i[2]) + self.kA.val * td_log
def additional_equations(self): r""" Calculates vector vec_res with results of additional equations for this component. Equations **mandatroy equations** .. math:: 0 = fluid_{i,in} - fluid_{i,out_{j}} \; \forall i \in \mathrm{fluid}, \; \forall j \in outlets .. math:: 0 = T_{in} - T_{out,i} \; \forall i \in \mathrm{outlets} Returns ------- vec_res : list Vector of residual values. """ vec_res = [] ###################################################################### # equations for fluid balance for fluid, x in self.inl[0].fluid.val.items(): res = x * self.inl[0].m.val_SI for o in self.outl: res -= o.fluid.val[fluid] * o.m.val_SI vec_res += [res] ###################################################################### # equations for energy balance for o in self.outl: vec_res += [ T_mix_ph(self.inl[0].to_flow(), T0=self.inl[0].T.val_SI) - T_mix_ph(o.to_flow(), T0=o.T.val_SI) ] return vec_res
def kA_func(self): r""" Calculate heat transfer from heat transfer coefficient. Returns ------- residual : float Residual value of equation. .. math:: 0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + kA \cdot \frac{T_{out,1} - T_{in,2} - T_{sat} \left(p_{in,1}\right) + T_{out,2}} {\ln{\frac{T_{out,1} - T_{in,2}} {T_{sat} \left(p_{in,1}\right) - T_{out,2}}}} """ i1 = self.inl[0] i2 = self.inl[1] o1 = self.outl[0] o2 = self.outl[1] T_i1 = T_bp_p(i1.get_flow()) T_i2 = T_mix_ph(i2.get_flow(), T0=i2.T.val_SI) T_o1 = T_mix_ph(o1.get_flow(), T0=o1.T.val_SI) T_o2 = T_mix_ph(o2.get_flow(), T0=o2.T.val_SI) if T_i1 <= T_o2 and not i1.T.val_set: T_i1 = T_o2 + 0.5 if T_i1 <= T_o2 and not o2.T.val_set: T_o2 = T_i1 - 0.5 if T_o1 <= T_i2 and not o1.T.val_set: T_o1 = T_i2 + 1 if T_o1 <= T_i2 and not i2.T.val_set: T_i2 = T_o1 - 1 td_log = ((T_o1 - T_i2 - T_i1 + T_o2) / np.log((T_o1 - T_i2) / (T_i1 - T_o2))) return i1.m.val_SI * (o1.h.val_SI - i1.h.val_SI) + self.kA.val * td_log
def kA_func(self): r""" Calculate heat transfer from heat transfer coefficient. Returns ------- residual : float Residual value of equation. .. math:: 0 = \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1}\right) + kA \cdot \frac{T_{out,1} - T_{in,2} - T_{in,1} + T_{out,2}} {\ln{\frac{T_{out,1} - T_{in,2}}{T_{in,1} - T_{out,2}}}} """ i1 = self.inl[0] i2 = self.inl[1] o1 = self.outl[0] o2 = self.outl[1] # temperature value manipulation for convergence stability T_i1 = T_mix_ph(i1.get_flow(), T0=i1.T.val_SI) T_i2 = T_mix_ph(i2.get_flow(), T0=i2.T.val_SI) T_o1 = T_mix_ph(o1.get_flow(), T0=o1.T.val_SI) T_o2 = T_mix_ph(o2.get_flow(), T0=o2.T.val_SI) if T_i1 <= T_o2: T_i1 = T_o2 + 0.01 if T_i1 <= T_o2: T_o2 = T_i1 - 0.01 if T_i1 <= T_o2: T_o1 = T_i2 + 0.02 if T_o1 <= T_i2: T_i2 = T_o1 - 0.02 td_log = ((T_o1 - T_i2 - T_i1 + T_o2) / np.log( (T_o1 - T_i2) / (T_i1 - T_o2))) return i1.m.val_SI * (o1.h.val_SI - i1.h.val_SI) + self.kA.val * td_log
def energy_group_func(self): r""" Equation for solar collector energy balance. Returns ------- residual : float Residual value of equation. .. math:: \begin{split} T_m = & \frac{T_{out} + T_{in}}{2}\\ iam = & 1 - iam_1 \cdot |aoi| - iam_2 \cdot aoi^2\\ 0 = & \dot{m} \cdot \left( h_{out} - h_{in} \right)\\ & - A \cdot \left[E \cdot \eta_{opt} \cdot doc^{1.5} \cdot iam \right. \\ & \left. - c_1 \cdot \left(T_m - T_{amb} \right) - c_2 \cdot \left(T_m - T_{amb}\right)^2 \vphantom{ \eta_{opt} \cdot doc^{1.5}} \right] \end{split} Reference: :cite:`Janotte2014`. """ i = self.inl[0].get_flow() o = self.outl[0].get_flow() T_m = (T_mix_ph(i, T0=self.inl[0].T.val_SI) + T_mix_ph(o, T0=self.outl[0].T.val_SI)) / 2 iam = (1 - self.iam_1.val * abs(self.aoi.val) - self.iam_2.val * self.aoi.val**2) return (i[0] * (o[2] - i[2]) - self.A.val * (self.E.val * self.eta_opt.val * self.doc.val**1.5 * iam - (T_m - self.Tamb.val_SI) * self.c_1.val - self.c_2.val * (T_m - self.Tamb.val_SI)**2))
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 ttd_u_func(self): r""" Equation for upper terminal temperature difference. Returns ------- residual : float Residual value of equation. .. math:: 0 = ttd_{u} - T_{sat} \left(p_{in,1}\right) + T_{out,2} Note ---- The upper terminal temperature difference ttd_u refers to boiling temperature at hot side inlet. """ T_i1 = T_bp_p(self.inl[0].get_flow()) T_o2 = T_mix_ph(self.outl[1].get_flow(), T0=self.outl[1].T.val_SI) return self.ttd_u.val - T_i1 + T_o2
def equations(self): r"""Calculate vector vec_res with results of equations.""" k = 0 ###################################################################### # equations for fluids # equations for fluid composition in cooling water for fluid, x in self.inl[0].fluid.val.items(): self.vec_res[k] = x - self.outl[0].fluid.val[fluid] k += 1 # equations to constrain fluids to inlets/outlets self.vec_res[k] = 1 - self.inl[1].fluid.val[self.h2o] k += 1 self.vec_res[k] = 1 - self.outl[1].fluid.val[self.o2] k += 1 self.vec_res[k] = 1 - self.outl[2].fluid.val[self.h2] k += 1 # equations to ban fluids off inlets/outlets for fluid in self.inl[1].fluid.val.keys(): if fluid != self.h2o: self.vec_res[k] = 0 - self.inl[1].fluid.val[fluid] k += 1 if fluid != self.o2: self.vec_res[k] = 0 - self.outl[1].fluid.val[fluid] k += 1 if fluid != self.h2: self.vec_res[k] = 0 - self.outl[2].fluid.val[fluid] k += 1 ###################################################################### # eqations for mass flow balance # equation to calculate the ratio of o2 in water o2 = molar_masses[self.o2] / ( molar_masses[self.o2] + 2 * molar_masses[self.h2]) # equation for mass flow balance cooling water self.vec_res[k] = self.inl[0].m.val_SI - self.outl[0].m.val_SI k += 1 # equations for mass flow balance electrolyzer self.vec_res[k] = o2 * self.inl[1].m.val_SI - self.outl[1].m.val_SI k += 1 self.vec_res[k] = ( (1 - o2) * self.inl[1].m.val_SI - self.outl[2].m.val_SI) k += 1 ###################################################################### # equations for pressure to set o2 and h2 output equal self.vec_res[k] = self.inl[1].p.val_SI - self.outl[1].p.val_SI k += 1 self.vec_res[k] = self.inl[1].p.val_SI - self.outl[2].p.val_SI k += 1 ###################################################################### # equation for energy balance if np.absolute(self.vec_res[k]) > err ** 2 or self.it % 4 == 0: self.vec_res[k] = self.P.val + self.energy_balance() k += 1 ###################################################################### # temperature electrolyzer outlet if np.absolute(self.vec_res[k]) > err ** 2 or self.it % 4 == 0: self.vec_res[k] = ( T_mix_ph(self.outl[1].to_flow()) - T_mix_ph(self.outl[2].to_flow())) k += 1 ###################################################################### # power vs hydrogen production if self.e.is_set: self.vec_res[k] = self.P.val - self.outl[2].m.val_SI * self.e.val k += 1 ###################################################################### # specified pressure ratio if self.pr_c.is_set: self.vec_res[k] = ( self.inl[0].p.val_SI * self.pr_c.val - self.outl[0].p.val_SI) k += 1 ###################################################################### # specified zeta value if self.zeta.is_set: if np.absolute(self.vec_res[k]) > err ** 2 or self.it % 4 == 0: self.vec_res[k] = self.zeta_func(zeta='zeta') k += 1 # equation for heat transfer if self.Q.is_set: self.vec_res[k] = ( self.Q.val - self.inl[0].m.val_SI * (self.inl[0].h.val_SI - self.outl[0].h.val_SI)) k += 1 ###################################################################### # specified efficiency (efficiency definition: e0 / e) if self.eta.is_set: self.vec_res[k] = ( self.P.val - self.outl[2].m.val_SI * self.e0 / self.eta.val) k += 1 ###################################################################### # specified characteristic line for efficiency if self.eta_char.is_set: self.vec_res[k] = self.eta_char_func() k += 1
def equations(self): r""" Calculates vector vec_res with results of equations for this component. Returns ------- vec_res : list Vector of residual values. """ vec_res = [] ###################################################################### # equations for fluids # equations for fluid composition in cooling water for fluid, x in self.inl[0].fluid.val.items(): vec_res += [x - self.outl[0].fluid.val[fluid]] # equations to constrain fluids to inlets/outlets vec_res += [1 - self.inl[1].fluid.val[self.h2o]] vec_res += [1 - self.outl[1].fluid.val[self.o2]] vec_res += [1 - self.outl[2].fluid.val[self.h2]] # equations to ban fluids off inlets/outlets for fluid in self.inl[1].fluid.val.keys(): if fluid != self.h2o: vec_res += [0 - self.inl[1].fluid.val[fluid]] if fluid != self.o2: vec_res += [0 - self.outl[1].fluid.val[fluid]] if fluid != self.h2: vec_res += [0 - self.outl[2].fluid.val[fluid]] ###################################################################### # eqations for mass flow balance # equation to calculate the ratio of o2 in water o2 = molar_masses[self.o2] / (molar_masses[self.o2] + 2 * molar_masses[self.h2]) # equation for mass flow balance cooling water vec_res += [self.inl[0].m.val_SI - self.outl[0].m.val_SI] # equations for mass flow balance electrolyzer vec_res += [o2 * self.inl[1].m.val_SI - self.outl[1].m.val_SI] vec_res += [(1 - o2) * self.inl[1].m.val_SI - self.outl[2].m.val_SI] ###################################################################### # equations for pressure to set o2 and h2 output equal vec_res += [self.inl[1].p.val_SI - self.outl[1].p.val_SI] vec_res += [self.inl[1].p.val_SI - self.outl[2].p.val_SI] ###################################################################### # equation for energy balance vec_res += [self.P.val + self.energy_balance()] ###################################################################### # temperature electrolyzer outlet vec_res += [T_mix_ph(self.outl[1].to_flow()) - T_mix_ph(self.outl[2].to_flow())] ###################################################################### # power vs hydrogen production if self.e.is_set: vec_res += [self.P.val - self.outl[2].m.val_SI * self.e.val] ###################################################################### #pr_c.val = pressure ratio Druckverlust (als Faktor vorgegeben) if self.pr_c.is_set: vec_res += [self.inl[0].p.val_SI * self.pr_c.val - self.outl[0].p.val_SI] if self.zeta.is_set: vec_res += [self.zeta_func()] # equation for heat transfer if self.Q.is_set: vec_res += [self.Q.val - self.inl[0].m.val_SI * (self.inl[0].h.val_SI - self.outl[0].h.val_SI)] ###################################################################### # specified efficiency (efficiency definition: e0 / e) if self.eta.is_set: vec_res += [self.P.val - self.outl[2].m.val_SI * self.e0 / self.eta.val] ###################################################################### # specified characteristic line for efficiency if self.eta_char.is_set: vec_res += [self.eta_char_func()] return vec_res