nx_steam.nx source
↩ module page · 90 lines · 3643 B
1// nx_steam.nx -- FOOD-SCIENCE SUITE / STEAM & THERMODYNAMICS rung. The
2// physics of steam that runs retorts, blanchers, evaporators, and driers:
3// the saturated-steam pressure/temperature table, latent heat of
4// vaporization, and the sensible + latent energy of a process.
5//
6// Data-driven (steam tables ARE tabulated data -> integer-exact, no float):
7// temperature in C, pressure in kPa (absolute), latent heat hfg in kJ/kg,
8// energy in joules, specific heat x1000 (water cp = 4.186 J/g.K -> 4186).
9//
10// THE exceed: a retort chart gives a fixed time; this gives the SATURATION
11// pressure a retort temperature demands, the latent heat a condensing-steam
12// process delivers, and the total energy to bring + boil a mass -- the
13// thermodynamics a process engineer actually sizes on.
14//
15// grounded: iapws_saturated_steam_tables + latent_heat_of_vaporization
16// + retort_saturated_steam_121C_15psig
17// genealogy_id: steam_thermodynamics + nishi_food_science_suite
18
19import "nx_syscalls.nx"
20const ST_MAGIC_2407: i64 = 2407
21const ST_MAGIC_2358: i64 = 2358
22const ST_MAGIC_2308: i64 = 2308
23const ST_MAGIC_2257: i64 = 2257
24const ST_MAGIC_2230: i64 = 2230
25const ST_MAGIC_2216: i64 = 2216
26const ST_MAGIC_2200: i64 = 2200
27
28const ST_CP_WATER_X1000: i64 = 4186 // J/g.K x1000
29const ST_ATM_KPA: i64 = 101 // 1 atm (for gauge pressure)
30
31// ===== Saturated-steam table (absolute pressure, kPa) =============
32
33func st_sat_pressure_kpa(temp_c: i64) -> i64 {
34 if temp_c == 40 { return 7 }
35 if temp_c == 60 { return 20 }
36 if temp_c == 80 { return 47 }
37 if temp_c == 100 { return 101 }
38 if temp_c == 110 { return 143 }
39 if temp_c == 115 { return 169 }
40 if temp_c == 121 { return 205 } // retort standard (121.1 C)
41 return -1
42}
43
44// Latent heat of vaporization hfg (kJ/kg) -- decreases as temperature rises.
45func st_latent_heat_kjkg(temp_c: i64) -> i64 {
46 if temp_c == 40 { return ST_MAGIC_2407 }
47 if temp_c == 60 { return ST_MAGIC_2358 }
48 if temp_c == 80 { return ST_MAGIC_2308 }
49 if temp_c == 100 { return ST_MAGIC_2257 }
50 if temp_c == 110 { return ST_MAGIC_2230 }
51 if temp_c == 115 { return ST_MAGIC_2216 }
52 if temp_c == 121 { return ST_MAGIC_2200 }
53 return -1
54}
55
56// ===== Process energy =============================================
57
58// Sensible heat (J) to raise `mass_g` by delta_t using specific heat (x1000).
59func st_sensible_heat_j(mass_g: i64, cp_x1000: i64, delta_t: i64) -> i64 {
60 return mass_g * cp_x1000 * delta_t / 1000
61}
62
63// Latent heat (J) to vaporize `mass_g` at a temperature (hfg kJ/kg).
64// mass_g/1000 kg * hfg kJ/kg * 1000 J/kJ == mass_g * hfg.
65func st_latent_energy_j(mass_g: i64, hfg_kjkg: i64) -> i64 {
66 return mass_g * hfg_kjkg
67}
68
69// Total energy (J) to heat water from start_c to boiling AND evaporate it.
70func st_energy_to_boil_j(mass_g: i64, start_c: i64) -> i64 {
71 let sensible: i64 = st_sensible_heat_j(mass_g, ST_CP_WATER_X1000, 100 - start_c)
72 let latent: i64 = st_latent_energy_j(mass_g, st_latent_heat_kjkg(100))
73 return sensible + latent
74}
75
76// Energy (J) that condensing steam DELIVERS to a food at a temperature --
77// the mechanism by which a retort/blancher heats.
78func st_condensation_energy_j(mass_steam_g: i64, temp_c: i64) -> i64 {
79 let hfg: i64 = st_latent_heat_kjkg(temp_c)
80 if hfg < 0 { return -1 }
81 return mass_steam_g * hfg
82}
83
84// Gauge pressure (kPa above atmospheric) a retort needs for saturated
85// steam at a temperature -- what the pressure vessel is rated to.
86func st_retort_gauge_kpa(temp_c: i64) -> i64 {
87 let p: i64 = st_sat_pressure_kpa(temp_c)
88 if p < 0 { return -1 }
89 return p - ST_ATM_KPA
90}