def __init__(self, identifier: str = 'gas', latex: Optional[str] = None, comment: Optional[str] = None) -> None: """ Args: identifier: Identifier of matter latex: Latex-version of identifier. If None, identical with identifier comment: Comment on matter Note: Do NOT define a self.__call__() method in this class """ super().__init__(identifier=identifier, latex=latex, comment=comment) # self.a.calc = self._a self.D_in_air = Property('D_in_air', 'm2/s', calc=lambda T, p=atm(), x=0.: None) self.T.ref = C2K(15.)
def _rho_el(self, T: float = C2K(20), p: float = atm(), x: float = 0.) -> float: """ Reference: Rykalin, in Radaj: Heat Effects of Welding, Springer 1992, p.68 T[deg C] rho [Ohm*mm] 0 1.26e-4 400 4e-4 800 10.2e-4 1200 12e-4 1600 12.6e-4 """ T_Celsius = max(K2C(T), 20.) # specific resistance in [Ohm m] if T_Celsius < 800: rho_el = ( (1.081e-8 * T_Celsius + 2.53e-6) * T_Celsius + 1.26e-3) * 1e-4 elif T < self.T_sol: rho_el = ( (-3.75e-9 * T_Celsius + 1.2e-5) * T_Celsius + 3e-3) * 1e-4 else: rho_el = 2 * 1.2e-6 return rho_el
def __init__(self, identifier: str = 'matter', latex: Optional[str] = None, comment: Optional[str] = None) -> None: """ Args: identifier: Identifier of matter latex: Latex-version of identifier. If None, latex is identical with identifier comment: Comment on matter Note: Do NOT define a self.__call__() method in this class """ super().__init__(identifier=identifier, latex=latex, comment=comment) self.a = Property('a', 'm$^2$/s', comment='thermal diffusity', calc = self._a) self.beta = Property('beta', '1/K', latex=r'$\beta_{th}$', comment='volumetric thermal expansion') self.c_p = Property('c_p', 'J/kg/K', comment='specific heat capacity') self.c_sound = Property('c_sound', 'm/s', latex='$c_{sound}$') self.c_sound.calc = lambda T, p, x: None self.composition: Dict[str, float] = OrderedDict() self.compressible: bool = False self.E = Property('E', 'Pa', comment="Young's (elastic) modulus") self.h_melt: float = None self.h_vap: float = None self.k = Property('k', 'W/m/K', latex='$k$', comment='thermal conductivity') self.M = Property('M', 'kmol/kg', comment='molar mass') self.M.calc = lambda T=0, p=0, x=0: None self.nu_mech: float = None self.rho = Property('rho', 'kg/m$^3$', latex=r'$\varrho$', ref=1., comment='density') self.rho.T.ref = C2K(20.) self.rho.p.ref = atm() self.rho_el = Property('rho_el', r'$\Omega$', latex=r'$\varrho_{el}$', comment='electric resistance') self.T_boil: float = 0. self.T_flash_point: float = 0. self.T_liq: float = 0. self.T_melt: float = 0. self.T_sol: float = 0. if self.E() is None or np.abs(self.E()) < 1e-20: self.rho.calc = lambda T, p, x: self.rho.ref \ / (1. + (T - self.rho.T.ref) * self.beta()) else: self.rho.calc = lambda T, p, x: self.rho.ref \ / (1. + (T - self.rho.T.ref) * self.beta()) \ / (1. - (p - self.rho.p.ref) / self.E())
def _nu(self, T: float, p: float = atm(), x: float = 0.) -> Optional[float]: try: rho = self.rho(T, p, x) if rho is None or np.abs(rho) < 1e-10: return None return self.mu(T, p, x) / rho except: return None
def _mu(self, T: float = C2K(20), p: float = atm(), x: float = 0.) -> float: """ [JONE96]: eta = eta0 * exp(E / (R*T)), eta0 = 0.3699e-3 kg/(m s), E = 41.4e3 J/mol, and R = 8.3144 J/(K mol) """ return 0.3699e-3 * np.exp(41.4e3 / (8.3144*T)) \ if T > self.T_deform else 1e20
def set_all_ref(self, T: float, p: float = atm(), x: float = 0.) -> bool: none_set = True for attr in dir(self): if not attr.startswith('_'): val = getattr(self, attr) if isinstance(val, Property): print(f'{attr=}, {val=}') none_set = False val.T.ref = T val.p.ref = p val.x.ref = x return not none_set
def _a(self, T: float, p: float = atm(), x: float = 0.) -> Optional[float]: try: k = self.k(T, p, x) c_p = self.c_p(T, p, x) rho = self.rho(T, p, x) if k is None or c_p is None or rho is None: return None c_p__rho = c_p * rho if np.abs(c_p__rho) < 1e-10: return None return k / c_p__rho except: return None
def _c_p(self, T: float = C2K(20), p: float = atm(), x: float = 0.) -> float: Tp = [ 300, 600, 900, 1033, 1040, 1184, 1184.1, 1400, 1673, 1673.1, 1809, 1809.1, 2000, 3000 ] Up = [ 430, 580, 760, 1260, 1160, 720, 610, 640, 680, 730, 760, 790, 790, 790 ] return np.interp(T, Tp, Up)
def _mu(self, T: float, p: float = atm(), x: float = 0.) -> float: y_all, M_all, mu_all = [], [], [] for gas, mole_frac in self.components.items(): if mole_frac < 1e-8: continue p_partial = mole_frac * p y_all.append(mole_frac) M_all.append(gas.M(T, p, x)) mu_all.append(gas.mu(T, p_partial, x)) return mix_mole(y=y_all, M=M_all, property_=mu_all)
def _rho(self, T: float, p: float = atm(), x: float = 0.) -> float: rho = 0. for gas, mole_frac in self.components.items(): if mole_frac < 1e-8: continue p_partial = mole_frac * p rho_i = gas.rho(T, p_partial, x) if rho_i is None: return None rho += mole_frac * rho_i return rho
def _rho(self, T: float = C2K(20), p: float = atm(), x: float = 0.) -> float: """ Reference for liquid iron: Steinberg, D. J.: Met. Trans. 5 (1974), 1341, in [Iida93] """ T_Celsius = min(K2C(T), 1600) if T_Celsius > 1536: rho = 7030 + (-8.8e-1) * (T_Celsius - 1536) elif T_Celsius > 723: rho = (-1e-4 * T_Celsius - 0.2) * T_Celsius + 7852.3 else: rho = (-1e-4 * T_Celsius - 0.3) * T_Celsius + 7849.1 return rho
def __init__(self, identifier: str = 'Property', unit: str = '/', absolute: bool = True, latex: Optional[str] = None, val: Optional[Union[float, Iterable[float]]] = None, ref: Optional[Union[float, Iterable[float]]] = None, comment: Optional[str] = None, calc: Optional[Callable[..., float]] = None) -> None: super().__init__(identifier=identifier, unit=unit, absolute=absolute, latex=latex, val=val, ref=ref, comment=comment) # reference temperature gases: 15C, solids: 20C or 25C, liquids: 20C T_Celsius = 20. self.T = Parameter(identifier='T', unit='K', absolute=True) self.T.ref = C2K(T_Celsius) self.T['operational'] = Range(C2K(-40.), C2K(200.)) self.T.accuracy = Range('-1', '+1') self.p = Parameter(identifier='p', unit='Pa', absolute=True) self.p.ref = atm() self.p['operational'] = Range(0. + self.p.ref, 100e5 + self.p.ref) self.p.accuracy = Range('-1%FS', '+1%FS') self.x = Parameter(identifier='x', unit='/', absolute=True) self.x['operational'] = Range(0., 1.) self.x.ref = 0. self.accuracy = Range('-1%', '1%') self.repeatability = Range('-0.1', '+0.1', '95%') if calc is None: calc = lambda T, p, x: 1. self.calc = calc self.regression_coefficients: Optional[Iterable[float]] = None
def _k(self, T: float, p: float = atm(), x: float = 0.) -> float: y_all, M_all, k_all, mu_all = [], [], [], [] for gas, mole_frac in self.components.items(): if mole_frac < 1e-8: continue p_partial = mole_frac * p y_all.append(mole_frac) M_all.append(gas.M(T, p, x)) k_all.append(gas.k(T, p_partial, x)) mu_all.append(gas.mu(T, p_partial, x)) if self._k_mix_formula.startswith('mas'): k = mix_mason(y=y_all, M=M_all, k=k_all, mu=mu_all) else: k = mix_mole(y=y_all, M=M_all, property_=k_all) return k
def _mu(self, T: float, p: float = atm(), x: float = 0.) -> Optional[float]: try: return self.nu(T, p, x) * self.rho(T, p, x) except: return None
def _k(self, T: float = C2K(20), p: float = atm(), x: float = 0.) -> float: Tp = [ 300, 600, 900, 1184, 1400, 1673, 1673.1, 1809, 1809.1, 2000, 3000 ] Up = [59.6, 54.6, 37.4, 28.2, 30.6, 33.7, 33.4, 34.6, 40.3, 42.6, 48] return np.interp(T, Tp, Up)