STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_wall_conduction.py
Go to the documentation of this file.
1"""The wall conduction model against closed-form solutions (Carslaw & Jaeger; Landau 1950).
2
3Every expected number here is a textbook formula evaluated in the test, not a number the
4model produced.
5"""
6import math
7import os
8import sys
9
10import numpy as np
11from scipy.special import erfc
12
13sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
14
15from engine.pipeline.thermal.wall_conduction import Layer, WallModel # noqa: E402
16
17K, RHO, CP = 0.35, 1600.0, 1500.0 # phenolic-like
18ALPHA = K / (RHO * CP)
19
20
22 """Semi-infinite solid, constant flux: Ts - T0 = 2 q sqrt(t/pi) / sqrt(k rho c)."""
23 q, t_end, dt = 2.0e6, 0.2, 0.001
24 w = WallModel([Layer(0.0127, K, RHO, CP)], 300.0)
25 for _ in range(int(round(t_end / dt))):
26 w.step(dt, q_in=lambda s: q)
27 expect = 300.0 + 2.0 * q * math.sqrt(t_end / math.pi) / math.sqrt(K * RHO * CP)
28 assert abs(w.T[0] - expect) / (expect - 300.0) < 0.01
29
30
32 """Surface stepped to Ts: T(y,t) = T0 + (Ts-T0) erfc(y / 2 sqrt(alpha t))."""
33 Ts, T0, t_end, dt = 1500.0, 300.0, 1.0, 0.002
34 w = WallModel([Layer(0.0127, K, RHO, CP)], T0)
35 # a very stiff film holds the face at Ts
36 for _ in range(int(round(t_end / dt))):
37 w.step(dt, q_in=lambda s: 1e9 * (Ts - s))
38 y = np.array([0.1e-3, 0.3e-3, 0.6e-3])
39 got = np.interp(y, w.y, w.T)
40 expect = T0 + (Ts - T0) * erfc(y / (2.0 * math.sqrt(ALPHA * t_end)))
41 assert np.all(np.abs(got - expect) < 0.02 * (Ts - T0))
42
43
45 """Quasi-steady ablation at T_abl: v = q / (rho (H + cp (T_abl - T0))); the T_p isotherm sits
46 (alpha/v) ln((T_abl - T0)/(T_p - T0)) below the receding face."""
47 q, H, T_abl, T0, Tp = 2.0e6, 2.5e6, 1986.0, 300.0, 950.0
48 w = WallModel([Layer(0.05, K, RHO, CP)], T0)
49 for _ in range(1500):
50 out = w.step(0.005, q_in=lambda s: q, T_ablation=T_abl, H_surface=H, rho_surface=RHO)
51 v = q / (RHO * (H + CP * (T_abl - T0)))
52 assert abs(out["recession"] / 0.005 - v) / v < 0.03
53 depth = ALPHA / v * math.log((T_abl - T0) / (Tp - T0))
54 assert abs(w.depth_of_isotherm(Tp) - depth) / depth < 0.05
55 assert w.T[0] == T_abl
56
57
59 """Adiabatic faces after shutdown: the profile relaxes to the mean, energy conserved."""
60 lay = [Layer(0.006, 100.0, 2260.0, 710.0)]
61 w = WallModel(lay, 300.0, n_first=40, first_cell=2e-5)
62 for _ in range(100):
63 w.step(0.01, q_in=lambda s: 5e6)
64 C = w._C
65 E_before = float(np.sum(C * w.T))
66 peaks = w.soak(60.0, dt=0.1)
67 E_after = float(np.sum(w._C * w.T))
68 assert abs(E_after - E_before) / E_before < 1e-6
69 T_mean = E_before / float(np.sum(C))
70 assert abs(w.T_back - T_mean) < 1.0
71 assert peaks["T_back_peak"] >= w.T_back - 1e-9