Various functions and classes to aid in engineering computations.
Computes the properties of dry air.
class Air(T, P=101325.0, Z=1.0):
where T is Temperature (K), P is pressure (Pa) and Z is compressibility factor.
from scisuit.dryair import Air
air = Air(T=300, P=101325.0, Z=1.0)
def cp(self) ->number:
"""
returns kJ/kgK, does not take P and Z into account.
"""
def k(self) -> number:
"""
returns W/mK, does not take P and Z into account.
"""
def mu(self) -> number:
"""
computes viscosity and
returns Pa·s, does not take P and Z into account.
"""
def Pr(self) -> number:
"""
Computes Prandtl number
"""
def rho() -> number:
"""
computes density.
returns kg/m3, uses ideal gas equation taking into account T, P and Z.
"""
Food in ScienceSuit is assumed to be composed of macronutrients, ash and salt:
For applications and detailed discussion please see digitalization of food.
In order to create a variable of type Food, we run the following command:
myfood = Food(Water=30, CHO=70)
print(myfood)
#output
Weight (unit weight)=1.00
Temperature (C)=20.00
Water (%)=30.00
CHO (%)=70.00
Aw=0.751
This command creates a food material and assigns it to variable myfood. The keys are water, CHO, protein, lipid or oil or fat, ash and salt and are case-insensitive. By default the variable myfood's temperature is 20 °C. Its weight is 1 unit and 30% of it is water and 70% is carbohydrate (please note that if the total percentage in the above command-line was not 100, it would have been adjusted to 100).
Please note that in the following example, although the sum of percentages in myfood2 is not equal to 100%, it will be automatically adjusted to 100% and therefore the percentages of water and carbohydrate in myfood and myfood2 are the same.
myfood2 = Food(Water=15, CHO=35)
myfood2
#output
Weight (unit weight)=1.00
Temperature (C)=20.00
Water (%)=30.00
CHO (%)=70.00
Aw=0.751
Food data structure supports some arithmetic operations: Let f1, f2 and f3 denote Food and a and b an arbitrary numbers.
Addition operation can be considered as the unit operation of mixing of food materials. The data structure allows mixing of different food materials at different temperatures. Mass and energy balances are performed automatically.
Let's create two food materials:
f1 = Food(Water=30, CHO=70)
f2 = Food(oil=40, protein=60)
Say, we would like to mix equal proportions of f1 and f2:
f3 = f1 + f2
print(f3)
#output
Weight (unit weight)=2.00
Temperature (C)=20.00
Water (%)=15.00
Protein (%)=30.00
CHO (%)=35.00
Lipid (%)=20.00
Aw=0.334
Here, the addition operation yielded a new food material and as expected the new food material f3 is composed of water, protein, carbohydrate and lipid. Its weight is 2 units (please see member function normalize() ) and its temperature is 20°C.
Instead of equal proportions, say we want to mix 20% f1 and 80% f2:
f4 = 0.2*f1 + 0.8*f2
print(f4)
#output
Weight (unit weight)=1.00
Temperature (C)=20.00
Water (%)=6.00
Protein (%)=48.00
CHO (%)=14.00
Lipid (%)=32.00
Aw=0.085
It should be noticed that although f1 and f2 are mixed, we have named the variable as f4 instead of f3. This is due to the fact that two food materials are considered to be equivalent if they contain the same amount of each macro-components.
Subtraction can be considered as the unit operation evaporation or extraction. Therefore, it is only allowed to subtract f2 from f1, if and only if, f2 is at the same temperature with f1 and contains exactly the same, but to a lesser amount of, macro-components.
In the following example our goal is to make a powder out of milk. We know that we need to remove water from the milk to achieve this goal. Therefore, we create two food materials, namely milk and water.
milk = Food(water=88.13, protein=3.15, CHO=4.80, lipid=3.25, ash=0.67)
water = Food(water=100)
powder = milk - 0.87*water
print(powder)
#output
Weight (unit weight)=0.13
Temperature (C)=20.00
Water (%)=8.69
Protein (%)=24.23
CHO (%)=36.92
Lipid (%)=25.00
Ash (%)=5.15
Aw=0.192
A few things should be noted here:
Unlike addition or subtraction, which yielded new food materials, multiplication does not yield a new food material. It only changes the weight of the food material. This is necessary to be able to perform addition or subtraction operations:
Taking the previous example:
f4 = 0.2*f1 + 0.8*f2
To be able to perform this addition, behind the scenes first a temporary food material from 0.2*f1 is created, say this is temp1, and then another temporary food material from 0.8*f2, say temp2. f4 is actually f4=temp1+temp2
def cp(self, T:float = None)->float:
"""
If T (in °C) is not specified then Food's current temperature will be used.\n
Returns specific heat capacity in kJ/kgK
Thermo-physical properties are valid in the range of -40<=T(C) <=150
2006, ASHRAE Handbook Chapter 9, Table 1 (source: Choi and Okos (1986))
"""
def k(self, T:float=None)->float:
"""
If T (in °C) is not specified then Food's current temperature will be used.\n
Returns conductivity in W/mK
For salt: 5.704 molal solution at 20C, Riedel L. (1962),
Thermal Conductivities of Aqueous Solutions of Strong Electrolytes
Chem.-1ng.-Technik., 23 (3) P.59 - 64
"""
def conductivity(self)->float:
"""Alias for k()"""
def rho(self, T:float = None)->float:
"""
If T (in °C) is not specified then Food's current temperature will be used.\n
Returns density in kg/m3
"""
def density(self)->float:
"""Alias for rho()"""
def aw(self)->float|None:
"""
Returns value of water activity or None
Warning:
At T>25 C, built-in computation might return None.
Therefore, must be used with caution at T>25.
"""
def molecularweight(self)->float:
"""
Average molecular weight of the food item
returns g/mol
"""
def enthalpy(self, T)->float:
"""
Computes enthalpy for frozen and unfrozen foods, returns: kJ/kg
T: Initial freezing temperature
Reference:
2006 ASHRAE Handbook, thermal properties of foods (Eq #18)
Notes:
If foods current temperature smaller than Tfreezing it will
compute the enthalpy for frozen foods.
"""
def freezing_T(self)->None:
"""
Estimates the initial freezing temperature of a food item \n
returns in Celcius (None if estimation fails)
Warning:
Not implemented in the base class (Food), raises error
"""
def x_ice(self, T:float)->float | None:
"""
Computes the fraction of ice
T: Initial freezing temperature
"""
def dielectric(self, f:int=2450)->Dielectric:
"""
Computes dielectric properties
f: frequency in MHz
Reference:
Gulati T, Datta AK (2013). Enabling computer-aided food process engineering: Property estimation
equations for transport phenomena-based models, Journal of Food Engineering, 116, 483-504
"""
def makefrom(self, inputs:list[Food])->list[float]:
"""
Performs material balances
Given a list of food items, computes the amount of each to be mixed to
make the current food item
"""
def ingredients(self)->dict:
"""
returns ingredients
"""
def normalize(self):
"""sets the weight to 1.0"""
@property
def temperature(self):
"""in Celcius, same as property T"""
@property
def T(self):
"""in Celcius, same as property temperature"""
@property
def weight(self):
""" unit weight, NOT recommended to set the weight externally """
@property
def water(self)->float:
@property
def cho(self)->float:
@property
def lipid(self)->float:
@property
def protein(self)->float:
@property
def ash(self)->float:
@property
def salt(self)->float:
Computes the thermodynamic properties of humid air.
def psychrometry(
P:Real=None,
Tdb:Real=None,
Twb:Real=None,
Tdp:Real=None,
W:Real=None,
RH:Real=None,
H:Real=None,
V:Real=None)->PsychrometryResult:
The properties of humid air are:
| Property | Unit | Key |
| Pressure | kPa | P |
| Dry-bulb temperature | °C | Tdb |
| Wet-bulb temperature | °C | Twb |
| Dew-point temperature | °C | Tdp |
| Absolute humidity | kg/kg dry air | W |
| Relative humidity | % | RH |
| Specific volume | m3/kg dry air | V |
| Enthalpy | kJ/kg dry air | H |
result = psychrometry(P=101.3, Tdb=50, RH=40)
print(result)
#output
P=101.3 kPa
Tdb=50.0 C
Twb=35.22 C
Tdp=32.21 C
H=132.63 kJ/kg da
RH=40.0 %
W=0.0319 kg/kg da
V=0.963 m3/kg da
class PsychrometryResult:
@property
def P(self):
"""Pressure in kPa"""
@property
def Tdb(self):
"""Dry bulb temperature in Celcius"""
@property
def Twb(self):
"""Wet bulb temperature in Celcius"""
@property
def Tdp(self):
"""Dew point temperature in Celcius"""
@property
def H(self):
"""Enthalpy in kJ/kg da"""
@property
def RH(self):
"""Relative Humidity in %"""
@property
def W(self):
"""Absolute Humidity in kg/kg da"""
@property
def V(self):
"""Specific volume in m3/kg da"""
@property
def Pws(self):
"""water vapor pressure at saturation in kPa"""
@property
def Pw(self):
"""water vapor pressure in kPa"""
@property
def Ws(self):
"""Absolute humidity at saturation kg/kg da"""
Thermodynamic property data of refrigerants as numpy arrays.
@_dc.dataclass
class Refrigerant:
"""
Properties of refrigerants
S: Saturated
T: Saturation temperature (K)
`P:` Saturation pressure (kPa)
vf, vg: specific volume (m3/kg)
hf, hg: enthalpy (kJ/kg)
sf, sg: entropy (kJ/kgK)
"""
@_dc.dataclass
class SR12:
"""Dichlorodifluoromethane"""
T = np.array([])
P = np.array([])
vf = np.array([])
vg = np.array([])
hf =np.array([])
hg =np.array([])
sf = np.array([])
sg =np.array([])
@_dc.dataclass
class SR22:
"""Chlorodifluoromethane"""
@_dc.dataclass
class SR23:
"""Trifluoromethane (Fluoroform)"""
@_dc.dataclass
class SR32:
"""Difluoromethane"""
@_dc.dataclass
class SR125:
"""Pentafluoroethane"""
@_dc.dataclass
class SR134A:
"""1,1,1,2-Tetrafluoroethane"""
@_dc.dataclass
class SR143A:
"""1,1,1-Trifluoroethane"""
@_dc.dataclass
class SR717:
"""Ammonia"""
@_dc.dataclass
class SR718:
"""water"""
Computes thermo-physical properties of water.
class Water:
def __init__(self, T:float) -> None:
"""
T in Celcius.
"""
w=Water(30)
print(w.viscosity())
print(w.cp())
print(w.conductivity())
print(w.density())
print(w.Prandtl())
def cp(self)->float:
"""
Computes specific heat capacity, kJ/kgK
Thermo-physical properties are valid in the range of -40<=T(C) <=150
2006, ASHRAE Handbook Chapter 9, Table 1 (source: Choi and Okos (1986))
"""
def conductivity(self)->float:
"""Thermal conductivity, result W/mK"""
def density(self)->float:
"""returns kg/m3"""
def viscosity(self)->float:
"""
returns Pa.s
Reference:
Joseph Kestin, Mordechai Sokolov, and William A. Wakeham
Viscosity of liquid water in the range -8°C to 150°C
Journal of Physical and Chemical Reference Data 7, 941 (1978);
"""
def Prandtl(self):
"""Prandtl number"""
@property
def T(self):
@T.setter
def T(self, T):