STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_graphite_properties.py
Go to the documentation of this file.
1"""The graphite insert's specific heat follows temperature (graphite_insert.specific_heat_model).
2
3The configs carried graphite's room-temperature specific heat, 710 J/(kg K), at every temperature;
4it is ~2000 J/(kg K) at the throat's running temperature, so the surface heated ~2.5x too fast and
5the surface chemistry ran early. Expected values here are independent of the code:
6 * NIST-JANAF graphite Cp: 8.517 J/(mol K) at 298.15 K, 21.610 J/(mol K) at 1000 K;
7 * a slab with an adiabatic back stores exactly the heat put into its face, int rho H(T) dy = q t.
8"""
9import copy
10import os
11import sys
12
13import numpy as np
14import pytest
15from scipy.integrate import quad
16
17sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
18
19from engine.core.runner import PintleEngineRunner # noqa: E402
20from engine.pipeline.io import load_config # noqa: E402
21from engine.pipeline.thermal.graphite_properties import cp_butland_maddison # noqa: E402
22from engine.pipeline.thermal.wall_conduction import Layer, WallModel # noqa: E402
23
24ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
25CFG = os.path.join(ROOT, "configs", "ethalox_6500N.yaml")
26PSI = 6894.757293168361
27MW_C = 12.0107e-3 # kg/mol
28RHO, K = 1810.0, 92.67 # GR001CC datasheet
29
30
31@pytest.fixture(autouse=True)
32def _python_physics(monkeypatch):
33 monkeypatch.setenv("ED_ACCEL", "off")
34
35
36@pytest.mark.parametrize("T, cp_janaf", [(298.15, 8.517), (1000.0, 21.610)])
38 assert float(cp_butland_maddison(T)) == pytest.approx(cp_janaf / MW_C, rel=0.03)
39
40
41def _slab(cp_of=None):
42 return WallModel([Layer(0.006, K, RHO, 710.0, "graphite", cp_of=cp_of)], 300.0, n_first=40, first_cell=2e-5)
43
44
46 q, dt, n = 5.0e6, 0.01, 100 # the solver's wall substep
47 wall = _slab(cp_butland_maddison)
48 for _ in range(n):
49 wall.step(dt, q_in=lambda s: q)
50
51 def enthalpy(T):
52 return quad(lambda x: float(cp_butland_maddison(x)), 300.0, T)[0]
53
54 stored = np.trapezoid(RHO * np.array([enthalpy(T) for T in wall.T]), wall.y)
55 assert stored == pytest.approx(q * dt * n, rel=0.01)
56 # the constant room-temperature cp runs the face ~260 K hotter for the same heat
57 flat = _slab()
58 for _ in range(n):
59 flat.step(dt, q_in=lambda s: q)
60 assert flat.T[0] > wall.T[0] + 150.0
61
62
64 a, b = _slab(), _slab(lambda T: np.full_like(np.asarray(T, float), 710.0))
65 for _ in range(50):
66 a.step(0.01, q_in=lambda s: 4.0e6, chemical_mass_flux=lambda s: 0.3, rho_surface=RHO)
67 b.step(0.01, q_in=lambda s: 4.0e6, chemical_mass_flux=lambda s: 0.3, rho_surface=RHO)
68 assert np.array_equal(a.T, b.T) and a.receded == b.receded
69
70
71def _burn(mutate):
72 cfg = load_config(CFG)
73 mutate(cfg)
74 t = np.linspace(0.0, 1.0, 6)
75 P = np.full_like(t, 584.27 * PSI)
76 return PintleEngineRunner(copy.deepcopy(cfg)).evaluate_arrays_with_time(t, P, P, use_coupled_solver=True)
77
78
80 def model(name):
81 def m(cfg):
82 cfg.graphite_insert.specific_heat_model = name
83 return m
84
85 flat = _burn(model("constant"))
86 real = _burn(model("butland_maddison_1973"))
87 assert real["T_graphite_surface"][1] < flat["T_graphite_surface"][1] - 100.0
88 assert real["recession_throat"][-1] < flat["recession_throat"][-1]
89
90
92 def off(name):
93 def m(cfg):
94 cfg.graphite_insert.enabled = False
95 cfg.graphite_insert.specific_heat_model = name
96 return m
97
98 a, b = _burn(off("constant")), _burn(off("butland_maddison_1973"))
99 for key in ("F", "Pc", "A_throat"):
100 assert np.array_equal(np.asarray(a[key]), np.asarray(b[key]))