Source code for fluidsolve.material

'''
Material property definitions used by hydraulic components.

This module provides a lightweight ``Material`` model with the constants needed
for component calculations (for example density, thermal conductivity, and
surface roughness). It is designed to supply practical engineering defaults
while still allowing user overrides.

Main features:

* predefined defaults for common conditions,
* unit-aware material properties using the shared unit registry,
* simple initialization from a material key/name,
* explicit override of key properties for custom materials.

Typical use cases:

* define pipe/wall roughness assumptions,
* set density values for pressure/head related conversions,
* pass consistent material settings through factory-created components.

Typical usage::

  mat = Material(mat='rvs')
  custom = Material(name='custom_steel', rho=7800 * u.kg / u.m**3, e=5 * u.um)

The class intentionally keeps the data model compact so that materials remain
easy to construct, inspect, and serialize as part of larger hydraulic models.
'''
# =============================================================================
# PYLINT DIRECTIVES
# =============================================================================

# =============================================================================
# IMPORTS
# =============================================================================
from typing import Any
# module own
import fluidsolve.aux_tools as flsa
import fluidsolve.medium    as flsme
# units
u         = flsme.unitRegistry
Quantity  = flsme.Quantity  # type: ignore[misc]

# =============================================================================
# SOME CONSTANTS
# =============================================================================
''' gravity '''
CTE_G     = 9.80665 * u.m/u.s**2
''' normal temperature '''
CTE_NT    = 20.0 * u.degC
''' density of water '''
CTE_RHO   = 1 * u.kg/u.m**3
''' thermal conductivity of water '''
CTE_K     = 1 * u.W/u.m/u.degK
''' absolute roughness (epsilon) of stainless steel '''
CTE_E_RVS = 1.6 * u.um

# =============================================================================
# MATERIAL CLASS
# =============================================================================
[docs] class Material (): ''' Class representing a material. Can be created just using a known name. Can also get an arbitrary name. In that case, the user has to provide the constants (rho, mu, ...) Args: mat (str, optional): The material (in the database) name. Defaults to 'rvs'. name (str, optional): Material name. Defaults to self._mat. T (int | float | Quantity, optional): The temperature. Defaults to 20°C. rho (int | float | Quantity, optional): The density. Defaults to water (at temperature). k (int | float | Quantity, optional): The thermal conductivity. Defaults to water (at temperature). e (int | float | Quantity, optional): The absolute roughness. Defaults to rvs. Returns: None ''' # -------------------------------------------------------------------------- # INITIALIZE
[docs] def __init__(self, **kwargs: int) -> None: args = flsa.GetArgs(kwargs) self._mat: str = args.getArg( 'mat', [ flsa.vFun.default('mat'), flsa.vFun.istype(str), ] ) self._name: str = args.getArg( 'name', [ flsa.vFun.default(self._mat), flsa.vFun.istype(str), ] ) # the product out of the material library, if it exists self._cmat = None # conditions self._T: Quantity = args.getArg( 'T', [ flsa.vFun.default(CTE_NT), flsa.vFun.istype((float, Quantity)), flsa.vFun.tounits(u.degK) ] ) # update the material with this conditions #self._updateProduct() # override rho, e self._rho: Quantity = args.getArg( 'rho', [ flsa.vFun.default(CTE_RHO), flsa.vFun.istype((float, Quantity)), flsa.vFun.tounits(u.kg/u.m**3) ] ) self._k: Quantity = args.getArg( 'k', [ flsa.vFun.default(CTE_K), flsa.vFun.istype((float, Quantity)), flsa.vFun.tounits(u.W/u.m/u.degK) ] ) self._e: Quantity = args.getArg( 'e', [ flsa.vFun.default(CTE_E_RVS), flsa.vFun.istype((float, Quantity)), flsa.vFun.tounits(u.um) ] )
# -------------------------------------------------------------------------- # PROPERTIES @property def name(self) -> str: ''' Name property. Returns: str: Name property. ''' return self._name @name.setter def name(self, value: str) -> None: ''' Set name property. Args: value (str): Name. ''' self._name = value @property def cmat(self) -> str: ''' underlying material object. Returns: Any: cmat property. ''' return self._cmat @property def T(self) -> Quantity: ''' Temperature property. Returns: Quantity: Temperature in °C (internally stored in K). ''' return self._T.to(u.degC) @T.setter def T(self, value: int | float | Quantity) -> None: ''' Set temperature. Args: value (int | float | Quantity): temperature (default in °C). ''' self._T = flsa.toUnits(value, u.degK) self._updateProduct() @property def rho(self) -> Quantity: ''' Density property. Returns: Quantity: Density (in kg/m3) property. ''' return self._rho @rho.setter def rho(self, value: int | float | Quantity) -> None: ''' Set density property. Args: value (int | float | Quantity): Density (default in kg/m3). ''' self._rho = flsa.toUnits(value, u.kg/u.m**3) @property def k(self) -> Quantity: ''' Thermal conductivity property. Returns: Quantity: Thermal conductivity (in W/m/K) property. ''' return self._k @k.setter def k(self, value: int | float | Quantity) -> None: ''' Set k property. Args: value (int | float | Quantity): Thermal conductivity (in W/m/K) property. ''' self._k = flsa.toUnits(value, u.W/u.m/u.degK) @property def e(self) -> Quantity: ''' Absolute roughness (epsilon) property. Returns: Quantity: absolute roughness (epsilon) (in um) property. ''' return self._e @e.setter def e(self, value: int | float | Quantity) -> None: ''' Set e property. Args: value (int | float | Quantity): Absolute roughness (epsilon) (in um) property. ''' self._e = flsa.toUnits(value, u.um)
[docs] def _updateProduct(self) -> Any: ''' Update the properties from the material library. ''' self._cmat = None
[docs] def __str__(self) -> str: ''' String representation Returns: str: String representation ''' return self.toString(0)
def __format__(self, format_spec: str) -> str: if format_spec == '': return str(self) try: detail = int(format_spec) except ValueError as exc: raise ValueError(f'Invalid format spec for {type(self).__name__}: {format_spec!r}') from exc return self.toString(detail)
[docs] def toString(self, detail: int=0) -> str: ''' String representation. Can be in more or less detail. Args: detail (int, optional): The details to be returned. Defaults to 0. Returns: str: String representation ''' name = self._name if self._name else '-' if detail == 0: return f'Material {name}: rho:{self._rho:.2f~P}, e:{self._e:.2e~P}' else: return f'Material {name} : T:{self._T:.2f~P}, rho:{self._rho:.2f~P}, e:{self._e:.2e~P}, k:{self._k:.2e~P}'
[docs] def __repr__(self) -> str: ''' Representation of the material object Returns: str: representation ''' if self._name=='': return f'Material(mat="water",rho={self._rho:.2f~P}, e={self._e:.2e~P})' else: return f'Material(name="{self._name}", mat="{self._mat}",rho={self._rho:.2f~P}, mu={self._e:.2e~P})'