From 3994835c65c6f88bc0350bbf9d689e5ccf1e7c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E4=BA=AC=E6=B3=BD?= Date: Tue, 9 Jun 2026 09:22:39 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=93=E7=A7=AF=E5=AF=BC?= =?UTF-8?q?=E6=95=B0=E8=AE=A1=E7=AE=97=E9=80=BB=E8=BE=91=EF=BC=8C=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=AE=8C=E5=96=84index.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cryo_tank/Index.md | 649 +++++++++++++++++++---------- src/cryo_tank/Index.pdf | Bin 80569 -> 0 bytes src/cryo_tank/config.py | 2 +- src/cryo_tank/properties.py | 12 + src/cryo_tank/solver.py | 2 +- src/cryo_tank/tank_model.py | 65 ++- tests/cryo_tank/test_properties.py | 16 + tests/cryo_tank/test_tank_model.py | 43 +- 8 files changed, 557 insertions(+), 232 deletions(-) delete mode 100644 src/cryo_tank/Index.pdf diff --git a/src/cryo_tank/Index.md b/src/cryo_tank/Index.md index 4795ff7..0a1a638 100644 --- a/src/cryo_tank/Index.md +++ b/src/cryo_tank/Index.md @@ -1,7 +1,3 @@ -# cryo_tank 模型方程与 ODE 求解逻辑 - -本文只保留当前 `src/cryo_tank/` 模型内部实际使用的方程,以及 ODE 方程组的求解逻辑。当前版本采用方案二:把气枕温度 `T_ull` 作为 ODE 状态量,氦气质量 `m_He` 由恒压状态方程派生。 - ## 1. 模型假设 当前模型是液氮贮箱的两区集总参数模型: @@ -15,25 +11,29 @@ 对应代码: -- 状态和派生量:`src/cryo_tank/tank_model.py:98-129` -- ODE 右端项:`src/cryo_tank/tank_model.py:131-163` -- 氦气补气温度方程:`src/cryo_tank/tank_model.py:165-214` +- 状态和派生量:`src/cryo_tank/tank_model.py:98-130` +- ODE 右端项:`src/cryo_tank/tank_model.py:132-162` +- 液相温度、气枕体积和氦气补气方程:`src/cryo_tank/tank_model.py:172-257` ## 2. 状态向量 ODE 状态向量为: -```text -y = [m_liq, U_liq, T_ull] -``` +$$ +\mathbf{y}=\left[m_{\mathrm{liq}},\ U_{\mathrm{liq}},\ T_{\mathrm{ull}}\right] +$$ 其中: -```text -m_liq : 液氮质量 [kg] -U_liq : 液相总内能 [J] -T_ull : 气枕区温度 [K] -``` +$$ +\begin{aligned} +m_{\mathrm{liq}} &: \text{液氮质量}\ [\mathrm{kg}] \\ +U_{\mathrm{liq}} &: \text{液相总内能}\ [\mathrm{J}] \\ +T_{\mathrm{ull}} &: \text{气枕区温度}\ [\mathrm{K}] +\end{aligned} +$$ + +式中,`m_liq` 为液氮质量,`U_liq` 为液相总内能,`T_ull` 为氦气气枕温度。`m_liq` 和 `U_liq` 是液相守恒方程的状态量,`T_ull` 是气枕能量方程的状态量。 代码位置:`src/cryo_tank/tank_model.py:1-7`,`src/cryo_tank/tank_model.py:87-89` @@ -41,40 +41,54 @@ T_ull : 气枕区温度 [K] 初始液相体积: -```text -V_liq_0 = (1 - ullage_fraction) * V_total -``` +$$ +V_{\mathrm{liq},0}=\left(1-f_{\mathrm{ull},0}\right)V_{\mathrm{total}} +$$ + +式中,`V_liq_0` 为初始液相体积,`ullage_fraction` 为初始气枕体积分数,`V_total` 为贮箱总容积。 初始气枕体积: -```text -V_ull_0 = ullage_fraction * V_total -``` +$$ +V_{\mathrm{ull},0}=f_{\mathrm{ull},0}V_{\mathrm{total}} +$$ + +式中,`V_ull_0` 为初始气枕体积。 初始液氮质量: -```text -rho_liq_0 = rho_LN2(T_init, P_work) -m_liq_0 = rho_liq_0 * V_liq_0 -``` +$$ +\begin{aligned} +\rho_{\mathrm{liq},0} &= \rho_{\mathrm{LN2}}\left(T_{\mathrm{init}},P_{\mathrm{work}}\right) \\ +m_{\mathrm{liq},0} &= \rho_{\mathrm{liq},0}V_{\mathrm{liq},0} +\end{aligned} +$$ + +式中,`rho_liq_0` 为初始液氮密度,`rho_LN2(T, P)` 为液氮在温度 `T`、压力 `P` 下的密度物性函数,`T_init` 为初始温度,`P_work` 为工作压力,`m_liq_0` 为初始液氮质量。 初始液相总内能: -```text -U_liq_0 = m_liq_0 * u_LN2(T_init, P_work) -``` +$$ +U_{\mathrm{liq},0}=m_{\mathrm{liq},0}u_{\mathrm{LN2}}\left(T_{\mathrm{init}},P_{\mathrm{work}}\right) +$$ + +式中,`U_liq_0` 为初始液相总内能,`u_LN2(T, P)` 为液氮比内能。 初始气枕温度: -```text -T_ull_0 = T_init -``` +$$ +T_{\mathrm{ull},0}=T_{\mathrm{init}} +$$ + +式中,`T_ull_0` 为初始气枕温度。 初始氦气质量是派生量: -```text -m_He_0 = rho_He(T_init, P_work) * V_ull_0 -``` +$$ +m_{\mathrm{He},0}=\rho_{\mathrm{He}}\left(T_{\mathrm{init}},P_{\mathrm{work}}\right)V_{\mathrm{ull},0} +$$ + +式中,`m_He_0` 为初始氦气质量,`rho_He(T, P)` 为氦气密度物性函数。 代码位置:`src/cryo_tank/tank_model.py:71-85` @@ -82,43 +96,57 @@ m_He_0 = rho_He(T_init, P_work) * V_ull_0 横截面积: -```text -A_cross = V_total / H_tank -``` +$$ +A_{\mathrm{cross}}=\frac{V_{\mathrm{total}}}{H_{\mathrm{tank}}} +$$ + +式中,`A_cross` 为圆柱贮箱横截面积,`H_tank` 为贮箱高度。 圆柱直径: -```text -D = sqrt(4 * A_cross / pi) -``` +$$ +D=\sqrt{\frac{4A_{\mathrm{cross}}}{\pi}} +$$ + +式中,`D` 为等效圆柱直径,`pi` 为圆周率。 侧面积: -```text -A_side = pi * D * H_tank -``` +$$ +A_{\mathrm{side}}=\pi D H_{\mathrm{tank}} +$$ + +式中,`A_side` 为圆柱侧壁面积。 端盖面积: -```text -A_cap = A_cross -``` +$$ +A_{\mathrm{cap}}=A_{\mathrm{cross}} +$$ + +式中,`A_cap` 为单个端盖面积。 总面积: -```text -A_total = A_side + 2 * A_cap -``` +$$ +A_{\mathrm{total}}=A_{\mathrm{side}}+2A_{\mathrm{cap}} +$$ + +式中,`A_total` 为贮箱外表面总面积,包含侧壁和两个端盖。 代码位置:`src/cryo_tank/tank_model.py:41-48` 液位对应的湿壁和干壁面积: -```text -level = clamp(liquid_level, 0, H_tank) -A_wet = A_cap + pi * D * level -A_dry = A_cap + pi * D * (H_tank - level) -``` +$$ +\begin{aligned} +L &= \operatorname{clamp}\left(H_{\mathrm{liq}},0,H_{\mathrm{tank}}\right) \\ +A_{\mathrm{wet}} &= A_{\mathrm{cap}}+\pi D L \\ +A_{\mathrm{dry}} &= A_{\mathrm{cap}}+\pi D\left(H_{\mathrm{tank}}-L\right) +\end{aligned} +$$ + +式中,`liquid_level` 为由液相体积换算得到的液位,`level` 为限制在 `[0, H_tank]` 范围内的液位,`A_wet` 为与液相接触的湿壁面积,`A_dry` 为与气枕接触的干壁面积。 代码位置:`src/cryo_tank/tank_model.py:91-96` @@ -126,32 +154,40 @@ A_dry = A_cap + pi * D * (H_tank - level) 给定状态: -```text -y = [m_liq, U_liq, T_ull] -``` +$$ +\mathbf{y}=\left[m_{\mathrm{liq}},\ U_{\mathrm{liq}},\ T_{\mathrm{ull}}\right] +$$ ### 5.1 液相派生量 -```text -u_liq = U_liq / m_liq -T_liq = T_LN2_from_u(u_liq, P_work) -rho_liq = rho_LN2(T_liq, P_work) -V_liq = m_liq / rho_liq -liquid_level = V_liq / A_cross -fill_fraction = liquid_level / H_tank -``` +$$ +\begin{aligned} +u_{\mathrm{liq}} &= \frac{U_{\mathrm{liq}}}{m_{\mathrm{liq}}} \\ +T_{\mathrm{liq}} &= T_{\mathrm{LN2}}\left(u_{\mathrm{liq}},P_{\mathrm{work}}\right) \\ +\rho_{\mathrm{liq}} &= \rho_{\mathrm{LN2}}\left(T_{\mathrm{liq}},P_{\mathrm{work}}\right) \\ +V_{\mathrm{liq}} &= \frac{m_{\mathrm{liq}}}{\rho_{\mathrm{liq}}} \\ +H_{\mathrm{liq}} &= \frac{V_{\mathrm{liq}}}{A_{\mathrm{cross}}} \\ +f_{\mathrm{fill}} &= \frac{H_{\mathrm{liq}}}{H_{\mathrm{tank}}} +\end{aligned} +$$ + +式中,`u_liq` 为液氮比内能,`T_liq` 为由比内能和压力反算得到的液相温度,`rho_liq` 为当前液氮密度,`V_liq` 为液相体积,`liquid_level` 为液位高度,`fill_fraction` 为液位高度占贮箱高度的比例。 代码位置:`src/cryo_tank/tank_model.py:107-113` ### 5.2 气枕派生量 -```text -V_ull = V_total - V_liq -P_He = P_work -rho_He = rho_He(T_ull, P_He) -m_He = rho_He * V_ull -U_ull = m_He * u_He(T_ull, P_He) -``` +$$ +\begin{aligned} +V_{\mathrm{ull}} &= V_{\mathrm{total}}-V_{\mathrm{liq}} \\ +P_{\mathrm{He}} &= P_{\mathrm{work}} \\ +\rho_{\mathrm{He}} &= \rho_{\mathrm{He}}\left(T_{\mathrm{ull}},P_{\mathrm{He}}\right) \\ +m_{\mathrm{He}} &= \rho_{\mathrm{He}}V_{\mathrm{ull}} \\ +U_{\mathrm{ull}} &= m_{\mathrm{He}}u_{\mathrm{He}}\left(T_{\mathrm{ull}},P_{\mathrm{He}}\right) +\end{aligned} +$$ + +式中,`V_ull` 为气枕体积,`P_He` 为氦气压力,`rho_He` 为当前氦气密度,`m_He` 为维持恒压所需的氦气质量,`U_ull` 为气枕氦气总内能,`u_He(T, P)` 为氦气比内能。 代码位置:`src/cryo_tank/tank_model.py:115-121` @@ -159,26 +195,32 @@ U_ull = m_He * u_He(T_ull, P_He) ### 6.1 液相与气枕界面换热 -```text -Q_liq_to_ull = h_conv * A_cross * (T_liq - T_ull) -``` +$$ +Q_{\mathrm{liq}\to\mathrm{ull}}=h_{\mathrm{conv}}A_{\mathrm{cross}}\left(T_{\mathrm{liq}}-T_{\mathrm{ull}}\right) +$$ + +式中,`Q_liq_to_ull` 为液相到气枕的界面换热率,`h_conv` 为界面对流换热系数,`A_cross` 为气液界面面积,`T_liq` 和 `T_ull` 分别为液相温度和气枕温度。 符号约定: -```text -Q_liq_to_ull > 0 : 热量从液相传给气枕 -Q_liq_to_ull < 0 : 热量从气枕传给液相 -``` +$$ +\begin{aligned} +Q_{\mathrm{liq}\to\mathrm{ull}} &> 0 && \text{热量从液相传给气枕} \\ +Q_{\mathrm{liq}\to\mathrm{ull}} &< 0 && \text{热量从气枕传给液相} +\end{aligned} +$$ -代码位置:`src/cryo_tank/tank_model.py:141-142` +代码位置:`src/cryo_tank/tank_model.py:142-143` ### 6.2 外界总漏热 当前主程序默认使用 MLI 漏热模型: -```text -Q_leak = A_total * q_mli -``` +$$ +Q_{\mathrm{leak}}=A_{\mathrm{total}}q_{\mathrm{MLI}} +$$ + +式中,`Q_leak` 为外界向贮箱的总漏热率,`q_mli` 为 MLI 单位面积漏热热流密度。 代码位置: @@ -187,10 +229,14 @@ Q_leak = A_total * q_mli 代码中还提供 Foam 漏热模型: -```text -T_mean = (T_inner + T_env) / 2 -Q_leak = A_total * k_eff(T_mean) * (T_env - T_inner) / delta -``` +$$ +\begin{aligned} +T_{\mathrm{mean}} &= \frac{T_{\mathrm{inner}}+T_{\mathrm{env}}}{2} \\ +Q_{\mathrm{leak}} &= A_{\mathrm{total}}k_{\mathrm{eff}}\left(T_{\mathrm{mean}}\right)\frac{T_{\mathrm{env}}-T_{\mathrm{inner}}}{\delta} +\end{aligned} +$$ + +式中,`T_mean` 为泡沫层平均温度,`T_inner` 为贮箱内侧温度,`T_env` 为环境温度,`k_eff` 为有效导热系数,`delta` 为泡沫保温层厚度。 如果 `k_eff` 是常数,则直接使用该常数。 @@ -200,92 +246,141 @@ Q_leak = A_total * k_eff(T_mean) * (T_env - T_inner) / delta 总漏热按湿壁面积和干壁面积分配: -```text -Q_leak_liq = Q_leak * A_wet / (A_wet + A_dry) -Q_leak_ull = Q_leak * A_dry / (A_wet + A_dry) -``` +$$ +\begin{aligned} +Q_{\mathrm{leak,liq}} &= Q_{\mathrm{leak}}\frac{A_{\mathrm{wet}}}{A_{\mathrm{wet}}+A_{\mathrm{dry}}} \\ +Q_{\mathrm{leak,ull}} &= Q_{\mathrm{leak}}\frac{A_{\mathrm{dry}}}{A_{\mathrm{wet}}+A_{\mathrm{dry}}} +\end{aligned} +$$ -代码位置:`src/cryo_tank/tank_model.py:144-148` +式中,`Q_leak_liq` 为分配到液相的漏热,`Q_leak_ull` 为分配到气枕的漏热。 + +代码位置:`src/cryo_tank/tank_model.py:145-149` ## 7. 液氮质量方程 液氮质量变化率: -```text -dm_liq/dt = mdot_in_ln2 - mdot_out_ln2 -``` +$$ +\frac{dm_{\mathrm{liq}}}{dt}=\dot{m}_{\mathrm{in,LN2}}-\dot{m}_{\mathrm{out,LN2}} +$$ + +式中,`dm_liq/dt` 为液氮质量变化率,`mdot_in_ln2` 为液氮入口质量流量,`mdot_out_ln2` 为液氮出口质量流量。 代码位置: - 净流量预计算:`src/cryo_tank/tank_model.py:64-65` -- ODE 中使用:`src/cryo_tank/tank_model.py:150-151` +- ODE 中使用:`src/cryo_tank/tank_model.py:151-152` ## 8. 液相能量方程 入口液氮焓: -```text -h_in_ln2 = h_LN2(T_in_ln2, P_work) -``` +$$ +h_{\mathrm{in,LN2}}=h_{\mathrm{LN2}}\left(T_{\mathrm{in,LN2}},P_{\mathrm{work}}\right) +$$ + +式中,`h_in_ln2` 为入口液氮比焓,`h_LN2(T, P)` 为液氮比焓物性函数,`T_in_ln2` 为入口液氮温度。 当前液相出口焓: -```text -h_liq = h_LN2(T_liq, P_work) -``` +$$ +h_{\mathrm{liq}}=h_{\mathrm{LN2}}\left(T_{\mathrm{liq}},P_{\mathrm{work}}\right) +$$ + +式中,`h_liq` 为当前液相出口比焓,模型假定出口液氮状态等于贮箱液相主体状态。 液相总内能变化率: -```text -dU_liq/dt = - mdot_in_ln2 * h_in_ln2 - - mdot_out_ln2 * h_liq - - Q_liq_to_ull - + Q_leak_liq -``` +$$ +\frac{dU_{\mathrm{liq}}}{dt}=\dot{m}_{\mathrm{in,LN2}}h_{\mathrm{in,LN2}}-\dot{m}_{\mathrm{out,LN2}}h_{\mathrm{liq}}-Q_{\mathrm{liq}\to\mathrm{ull}}+Q_{\mathrm{leak,liq}} +$$ + +式中,`dU_liq/dt` 为液相总内能变化率;入口液氮携带焓流 `mdot_in_ln2 * h_in_ln2`,出口液氮带走焓流 `mdot_out_ln2 * h_liq`,液相向气枕换热为 `Q_liq_to_ull`,外界向液相漏热为 `Q_leak_liq`。 代码位置: - 入口焓预计算:`src/cryo_tank/tank_model.py:60-62` -- 能量方程:`src/cryo_tank/tank_model.py:152-156` +- 能量方程调用:`src/cryo_tank/tank_model.py:153-155` +- 能量方程实现:`src/cryo_tank/tank_model.py:164-170` ## 9. 气枕温度和氦气质量导数方程 当前模型把 `T_ull` 作为 ODE 状态。氦气质量由恒压关系派生: -```text -m_He = rho_He(T_ull, P_work) * V_ull -``` +$$ +m_{\mathrm{He}}=\rho_{\mathrm{He}}\left(T_{\mathrm{ull}},P_{\mathrm{work}}\right)V_{\mathrm{ull}} +$$ + +式中,`m_He` 是派生氦气质量,不是 ODE 独立状态。 代码位置:`src/cryo_tank/tank_model.py:115-121` ### 9.1 气枕体积变化率 -液氮质量变化导致气枕体积变化: +液相体积由液氮质量和恒压液氮密度决定: -```text -dV_ull/dt = -dm_liq_dt / rho_liq -``` +$$ +V_{\mathrm{liq}}=\frac{m_{\mathrm{liq}}}{\rho_{\mathrm{liq}}\left(T_{\mathrm{liq}},P_{\mathrm{work}}\right)} +$$ -代码位置:`src/cryo_tank/tank_model.py:186-188` +气枕体积为: + +$$ +V_{\mathrm{ull}}=V_{\mathrm{total}}-V_{\mathrm{liq}} +$$ + +对液相体积求全导数: + +$$ +\frac{dV_{\mathrm{liq}}}{dt}=\frac{1}{\rho_{\mathrm{liq}}}\frac{dm_{\mathrm{liq}}}{dt}-\frac{m_{\mathrm{liq}}}{\rho_{\mathrm{liq}}^2} +\left(\frac{\partial\rho_{\mathrm{liq}}}{\partial T}\right)_P\frac{dT_{\mathrm{liq}}}{dt} +$$ + +其中液相温度变化率由 `u_liq = U_liq / m_liq` 得到: + +$$ +\frac{dT_{\mathrm{liq}}}{dt}=\frac{\frac{dU_{\mathrm{liq}}}{dt}-u_{\mathrm{liq}}\frac{dm_{\mathrm{liq}}}{dt}}{m_{\mathrm{liq}}\left(\frac{\partial u_{\mathrm{liq}}}{\partial T}\right)_P} +$$ + +因此气枕体积变化率为: + +$$ +\frac{dV_{\mathrm{ull}}}{dt}=-\frac{1}{\rho_{\mathrm{liq}}}\frac{dm_{\mathrm{liq}}}{dt}+\frac{m_{\mathrm{liq}}}{\rho_{\mathrm{liq}}^2} +\left(\frac{\partial\rho_{\mathrm{liq}}}{\partial T}\right)_P\frac{dT_{\mathrm{liq}}}{dt} +$$ + +式中,`dV_ull/dt` 为气枕体积变化率,第一项为液氮质量变化导致的体积变化,第二项为液氮温度变化导致密度变化后产生的体积修正项。液氮的恒压密度温度导数和恒压内能温度导数由 CoolProp 提供。 + +代码位置: + +- LN2 恒压偏导:`src/cryo_tank/properties.py:47-56` +- 液相温度变化率:`src/cryo_tank/tank_model.py:172-180` +- 气枕体积变化率:`src/cryo_tank/tank_model.py:182-194` ### 9.2 气枕区非氦气入口热量 -```text -Q_ull_no_he = Q_liq_to_ull + Q_leak_ull -``` +$$ +Q_{\mathrm{ull,noHe}}=Q_{\mathrm{liq}\to\mathrm{ull}}+Q_{\mathrm{leak,ull}} +$$ -代码位置:`src/cryo_tank/tank_model.py:188` +式中,`Q_ull_no_he` 为不含氦气入口焓流的气枕净受热率,包括液相传入气枕的界面换热和分配到气枕干壁的外界漏热。 + +代码位置:`src/cryo_tank/tank_model.py:221` ### 9.3 恒压氦气状态函数 在固定压力 `P_work` 下,给定 `T_ull` 和 `V_ull`: -```text -rho = rho_He(T_ull, P_work) -m(T, V) = rho * V -U(T, V) = m(T, V) * u_He(T_ull, P_work) -``` +$$ +\begin{aligned} +\rho &= \rho_{\mathrm{He}}\left(T_{\mathrm{ull}},P_{\mathrm{work}}\right) \\ +m(T,V) &= \rho V \\ +U(T,V) &= m(T,V)u_{\mathrm{He}}\left(T_{\mathrm{ull}},P_{\mathrm{work}}\right) +\end{aligned} +$$ + +式中,`rho` 为氦气密度,`T` 表示 `T_ull`,`V` 表示 `V_ull`,`m(T, V)` 为恒压下由温度和体积确定的氦气质量,`U(T, V)` 为恒压下由温度和体积确定的气枕总内能。 代码位置:`src/cryo_tank/tank_model.py:115-121` @@ -293,120 +388,226 @@ U(T, V) = m(T, V) * u_He(T_ull, P_work) 代码不再对温度和体积做有限差分,而是使用恒压物性导数: -```text -drhodT_P = (partial rho / partial T)_P -dudT_P = (partial u / partial T)_P -``` +$$ +\begin{aligned} +\left(\frac{\partial\rho}{\partial T}\right)_P &= \rho_T\big|_P \\ +\left(\frac{\partial u}{\partial T}\right)_P &= u_T\big|_P +\end{aligned} +$$ -CoolProp 偏导接口位置:`src/cryo_tank/properties.py:100-109` +式中,`drhodT_P` 为恒压氦气密度对温度的偏导数,`dudT_P` 为恒压氦气比内能对温度的偏导数。 + +CoolProp 偏导接口位置:`src/cryo_tank/properties.py:113-122` 由此得到: -```text -m_T = V_ull * drhodT_P -m_V = rho -U_T = V_ull * (u * drhodT_P + rho * dudT_P) -U_V = rho * u -``` +$$ +\begin{aligned} +m_T &= V_{\mathrm{ull}}\left(\frac{\partial\rho}{\partial T}\right)_P \\ +m_V &= \rho \\ +U_T &= V_{\mathrm{ull}}\left[u\left(\frac{\partial\rho}{\partial T}\right)_P+\rho\left(\frac{\partial u}{\partial T}\right)_P\right] \\ +U_V &= \rho u +\end{aligned} +$$ -代码位置:`src/cryo_tank/tank_model.py:165-178` +式中,`m_T = (partial m / partial T)_V`,`m_V = (partial m / partial V)_T`,`U_T = (partial U / partial T)_V`,`U_V = (partial U / partial V)_T`。这些偏导用于把 `dm_He/dt` 和 `dU_ull/dt` 展开为 `dT_ull/dt` 与 `dV_ull/dt` 的线性组合。 + +推导过程如下。恒压下 `rho = rho(T, P_work)`,`u = u(T, P_work)`,所以: + +$$ +m(T,V)=\rho\left(T,P_{\mathrm{work}}\right)V +$$ + +对温度和体积求偏导: + +$$ +\begin{aligned} +m_T &= \left(\frac{\partial m}{\partial T}\right)_V + = V\left(\frac{\partial\rho}{\partial T}\right)_P + = V_{\mathrm{ull}}\rho_T\big|_P \\ +m_V &= \left(\frac{\partial m}{\partial V}\right)_T + = \rho +\end{aligned} +$$ + +气枕总内能为: + +$$ +U(T,V)=m(T,V)u\left(T,P_{\mathrm{work}}\right)=\rho\left(T,P_{\mathrm{work}}\right)Vu\left(T,P_{\mathrm{work}}\right) +$$ + +对温度和体积求偏导: + +$$ +\begin{aligned} +U_T &= \left(\frac{\partial U}{\partial T}\right)_V + = V\left[u\left(\frac{\partial\rho}{\partial T}\right)_P+\rho\left(\frac{\partial u}{\partial T}\right)_P\right] \\ + &= V_{\mathrm{ull}}\left(u\rho_T\big|_P+\rho u_T\big|_P\right) \\ +U_V &= \left(\frac{\partial U}{\partial V}\right)_T + = \rho u +\end{aligned} +$$ + +代码位置:`src/cryo_tank/tank_model.py:196-209` ### 9.5 气枕温度变化率 氦气入口焓: -```text -h_in_he = h_He(T_in_he, P_work) -``` +$$ +h_{\mathrm{in,He}}=h_{\mathrm{He}}\left(T_{\mathrm{in,He}},P_{\mathrm{work}}\right) +$$ + +式中,`h_in_he` 为入口氦气比焓,`h_He(T, P)` 为氦气比焓物性函数,`T_in_he` 为入口氦气温度。 + +氦气气枕能量方程采用开口、变体积控制体的一阶热力学形式: + +$$ +\frac{dU_{\mathrm{ull}}}{dt}=\dot{m}_{\mathrm{He}}h_{\mathrm{in,He}}+Q_{\mathrm{ull,noHe}}-P_{\mathrm{work}}\frac{dV_{\mathrm{ull}}}{dt} +$$ + +式中,`dU_ull/dt` 为气枕氦气总内能变化率,`mdot_He * h_in_he` 为补入氦气带入的焓流,`Q_ull_no_he` 为界面换热与外界漏热给气枕的热输入,`P_work * dV_ull/dt` 为气枕边界膨胀功项。当前模型无气枕出口流量,因此没有出口焓流项。 + +由恒压状态函数的全微分: + +$$ +\begin{aligned} +\frac{dm_{\mathrm{He}}}{dt} &= m_T\frac{dT_{\mathrm{ull}}}{dt}+m_V\frac{dV_{\mathrm{ull}}}{dt} \\ +\frac{dU_{\mathrm{ull}}}{dt} &= U_T\frac{dT_{\mathrm{ull}}}{dt}+U_V\frac{dV_{\mathrm{ull}}}{dt} +\end{aligned} +$$ + +把质量导数代入气枕能量方程: + +$$ +U_T\frac{dT_{\mathrm{ull}}}{dt}+U_V\frac{dV_{\mathrm{ull}}}{dt}=h_{\mathrm{in,He}}\left(m_T\frac{dT_{\mathrm{ull}}}{dt}+m_V\frac{dV_{\mathrm{ull}}}{dt}\right)+Q_{\mathrm{ull,noHe}}-P_{\mathrm{work}}\frac{dV_{\mathrm{ull}}}{dt} +$$ + +整理 `dT_ull/dt` 项: + +$$ +\left(U_T-h_{\mathrm{in,He}}m_T\right)\frac{dT_{\mathrm{ull}}}{dt}=Q_{\mathrm{ull,noHe}}-\left(U_V+P_{\mathrm{work}}-h_{\mathrm{in,He}}m_V\right)\frac{dV_{\mathrm{ull}}}{dt} +$$ 气枕温度变化率: -```text -dT_ull/dt = - [Q_ull_no_he - (U_V + P_work - h_in_he * m_V) * dV_ull/dt] - / [U_T - h_in_he * m_T] -``` +$$ +\frac{dT_{\mathrm{ull}}}{dt}=\frac{Q_{\mathrm{ull,noHe}}-\left(U_V+P_{\mathrm{work}}-h_{\mathrm{in,He}}m_V\right)\frac{dV_{\mathrm{ull}}}{dt}}{U_T-h_{\mathrm{in,He}}m_T} +$$ -代码位置:`src/cryo_tank/tank_model.py:190-197` +式中,分子表示扣除体积变化、边界功和入口质量变化耦合项后的气枕有效热输入,分母表示在恒压约束和入口补气耦合下气枕对温度变化的等效热容项。 + +代码位置:`src/cryo_tank/tank_model.py:223-230` 若分母过小: -```text -if abs(U_T - h_in_he * m_T) < 1e-30: - dT_ull/dt = 0 - mdot_He = 0 -``` +$$ +\left|U_T-h_{\mathrm{in,He}}m_T\right|<10^{-30} +\quad\Longrightarrow\quad +\begin{cases} +\dfrac{dT_{\mathrm{ull}}}{dt}=0 \\ +\dot{m}_{\mathrm{He}}=0 +\end{cases} +$$ -代码位置:`src/cryo_tank/tank_model.py:190-193` +式中,`1e-30` 是数值保护阈值,用于避免除以过小分母。 + +代码位置:`src/cryo_tank/tank_model.py:223-226` ### 9.6 氦气质量变化率 -```text -dm_He/dt = mdot_He -``` +$$ +\frac{dm_{\mathrm{He}}}{dt}=\dot{m}_{\mathrm{He}} +$$ + +式中,`dm_He/dt` 为恒压约束下氦气质量变化率,`mdot_He` 为需要补入的氦气质量流量。 其中: -```text -mdot_He = m_T * dT_ull/dt + m_V * dV_ull/dt -``` +$$ +\dot{m}_{\mathrm{He}}=m_T\frac{dT_{\mathrm{ull}}}{dt}+m_V\frac{dV_{\mathrm{ull}}}{dt} +$$ -代码位置:`src/cryo_tank/tank_model.py:198` +式中,第一项为气枕温度变化导致的氦气质量变化,第二项为气枕体积变化导致的氦气质量变化。 + +代码位置:`src/cryo_tank/tank_model.py:231` 若 `mdot_He < 0`,报告流量钳制为 0: -```text -mdot_He = 0 -``` +$$ +\dot{m}_{\mathrm{He}}=0 +$$ -代码位置:`src/cryo_tank/tank_model.py:200-205` +式中,钳制只作用于报告的补气流量;当前 ODE 状态 `T_ull` 的导数仍由未钳制前的恒压能量方程求得。 + +代码位置:`src/cryo_tank/tank_model.py:233-238` ## 10. 完整 ODE 方程组 状态向量: -```text -y = [m_liq, U_liq, T_ull] -``` +$$ +\mathbf{y}=\left[m_{\mathrm{liq}},\ U_{\mathrm{liq}},\ T_{\mathrm{ull}}\right] +$$ + +式中,`y` 为 ODE 状态向量,三个分量分别为液氮质量、液相总内能和气枕温度。 ODE 方程组: -```text -dm_liq/dt = mdot_in_ln2 - mdot_out_ln2 -``` +$$ +\frac{dm_{\mathrm{liq}}}{dt}=\dot{m}_{\mathrm{in,LN2}}-\dot{m}_{\mathrm{out,LN2}} +$$ -```text -dU_liq/dt = - mdot_in_ln2 * h_in_ln2 - - mdot_out_ln2 * h_liq - - Q_liq_to_ull - + Q_leak_liq -``` +式中,液氮质量变化率等于入口液氮质量流量减去出口液氮质量流量。 -```text -dT_ull/dt = - [Q_ull_no_he - (U_V + P_work - h_in_he * m_V) * dV_ull/dt] - / [U_T - h_in_he * m_T] -``` +$$ +\frac{dU_{\mathrm{liq}}}{dt}=\dot{m}_{\mathrm{in,LN2}}h_{\mathrm{in,LN2}}-\dot{m}_{\mathrm{out,LN2}}h_{\mathrm{liq}}-Q_{\mathrm{liq}\to\mathrm{ull}}+Q_{\mathrm{leak,liq}} +$$ + +式中,液相总内能变化率由入口焓流、出口焓流、液相向气枕换热和液相漏热共同决定。 + +$$ +\frac{dT_{\mathrm{ull}}}{dt}=\frac{Q_{\mathrm{ull,noHe}}-\left(U_V+P_{\mathrm{work}}-h_{\mathrm{in,He}}m_V\right)\frac{dV_{\mathrm{ull}}}{dt}}{U_T-h_{\mathrm{in,He}}m_T} +$$ + +式中,气枕温度变化率由氦气气枕能量方程和恒压状态方程联立得到。 其中: -```text -h_liq = h_LN2(T_liq, P_work) -Q_liq_to_ull = h_conv * A_cross * (T_liq - T_ull) -Q_ull_no_he = Q_liq_to_ull + Q_leak_ull -Q_leak_liq = Q_leak * A_wet / (A_wet + A_dry) -Q_leak_ull = Q_leak * A_dry / (A_wet + A_dry) -``` +$$ +\begin{aligned} +h_{\mathrm{liq}} &= h_{\mathrm{LN2}}\left(T_{\mathrm{liq}},P_{\mathrm{work}}\right) \\ +Q_{\mathrm{liq}\to\mathrm{ull}} &= h_{\mathrm{conv}}A_{\mathrm{cross}}\left(T_{\mathrm{liq}}-T_{\mathrm{ull}}\right) \\ +Q_{\mathrm{ull,noHe}} &= Q_{\mathrm{liq}\to\mathrm{ull}}+Q_{\mathrm{leak,ull}} \\ +Q_{\mathrm{leak,liq}} &= Q_{\mathrm{leak}}\frac{A_{\mathrm{wet}}}{A_{\mathrm{wet}}+A_{\mathrm{dry}}} \\ +Q_{\mathrm{leak,ull}} &= Q_{\mathrm{leak}}\frac{A_{\mathrm{dry}}}{A_{\mathrm{wet}}+A_{\mathrm{dry}}} +\end{aligned} +$$ + +气枕体积变化率使用完整链式法则: + +$$ +\begin{aligned} +\frac{dT_{\mathrm{liq}}}{dt} &= \frac{\frac{dU_{\mathrm{liq}}}{dt}-u_{\mathrm{liq}}\frac{dm_{\mathrm{liq}}}{dt}}{m_{\mathrm{liq}}\left(\frac{\partial u_{\mathrm{liq}}}{\partial T}\right)_P} \\ +\frac{dV_{\mathrm{ull}}}{dt} &= -\frac{1}{\rho_{\mathrm{liq}}}\frac{dm_{\mathrm{liq}}}{dt}+\frac{m_{\mathrm{liq}}}{\rho_{\mathrm{liq}}^2} +\left(\frac{\partial\rho_{\mathrm{liq}}}{\partial T}\right)_P\frac{dT_{\mathrm{liq}}}{dt} +\end{aligned} +$$ + +式中,`h_liq` 为当前液相比焓,`Q_liq_to_ull` 为液相到气枕界面换热,`Q_ull_no_he` 为不含入口氦气焓流的气枕热输入,`Q_leak_liq` 和 `Q_leak_ull` 分别为分配到液相和气枕的漏热;`dV_ull/dt` 同时包含液氮质量变化和液氮密度随温度变化的贡献。 氦气质量和质量流量是派生量: -```text -m_He = rho_He(T_ull, P_work) * V_ull -mdot_He = m_T * dT_ull/dt + m_V * dV_ull/dt -``` +$$ +\begin{aligned} +m_{\mathrm{He}} &= \rho_{\mathrm{He}}\left(T_{\mathrm{ull}},P_{\mathrm{work}}\right)V_{\mathrm{ull}} \\ +\dot{m}_{\mathrm{He}} &= m_T\frac{dT_{\mathrm{ull}}}{dt}+m_V\frac{dV_{\mathrm{ull}}}{dt} +\end{aligned} +$$ -代码位置:`src/cryo_tank/tank_model.py:131-214` +式中,`m_He` 为恒压状态方程给出的当前氦气质量,`mdot_He` 为由质量全微分得到的所需补气流量。 + +代码位置:`src/cryo_tank/tank_model.py:132-257` ## 11. ODE 求解逻辑 @@ -416,13 +617,17 @@ mdot_He = m_T * dT_ull/dt + m_V * dV_ull/dt run(tank, t_end, rtol=1e-8, atol=1e-10, max_step=10.0) ``` +式中,`tank` 为 `CryoTank` 模型实例,`t_end` 为仿真终止时间,`rtol` 和 `atol` 为相对、绝对误差容限,`max_step` 为求解器最大时间步长。 + 代码位置:`src/cryo_tank/solver.py:22-24` 求解初值: -```text -y0 = tank.initial_state() -``` +$$ +\mathbf{y}_0=\operatorname{initial\_state}\left(\mathrm{tank}\right) +$$ + +式中,`y0` 为初始 ODE 状态向量。 代码位置:`src/cryo_tank/solver.py:43` @@ -442,20 +647,28 @@ solve_ivp( ) ``` +式中,`tank.rhs` 为 ODE 右端函数,`[0.0, t_end]` 为积分时间区间,`method="RK45"` 指四、五阶 Runge-Kutta 自适应算法,`events` 用于注册液体排空终止事件,`dense_output=True` 表示生成连续插值解。 + 代码位置:`src/cryo_tank/solver.py:45-55` 液体排空事件: -```text -event(t, y) = m_liq -``` +$$ +g(t,\mathbf{y})=m_{\mathrm{liq}} +$$ + +式中,`event(t, y)` 为事件函数;当状态中的 `m_liq` 到达零时,事件函数到达零。 事件属性: -```text -terminal = True -direction = -1 -``` +$$ +\begin{aligned} +\mathrm{terminal} &= \mathrm{True} \\ +\mathrm{direction} &= -1 +\end{aligned} +$$ + +式中,`terminal=True` 表示事件触发后终止积分,`direction=-1` 表示只检测事件函数从正值下降到零的穿越。 含义: @@ -472,19 +685,25 @@ direction = -1 求解完成后,`solver.run()` 对每个输出时刻执行: -```text -info = tank.derive(y_i) -``` +$$ +\mathrm{info}_i=\operatorname{derive}\left(\mathbf{y}_i\right) +$$ + +式中,`y_i` 为某一输出时刻的状态向量,`info` 为根据该状态计算出的温度、体积、质量和换热等派生量字典。 并重新计算: -```text -Q_liq_to_ull -Q_leak -Q_leak_liq -Q_leak_ull -mdot_He -``` +$$ +\left\{ +Q_{\mathrm{liq}\to\mathrm{ull}},\ +Q_{\mathrm{leak}},\ +Q_{\mathrm{leak,liq}},\ +Q_{\mathrm{leak,ull}},\ +\dot{m}_{\mathrm{He}} +\right\} +$$ + +式中,这些量分别为界面换热、总漏热、液相漏热、气枕漏热和派生氦气补气质量流量,用于输出和结果分析。 其中 `m_He`、`U_ull`、`mdot_He` 均为后处理派生结果,不是独立 ODE 状态。 diff --git a/src/cryo_tank/Index.pdf b/src/cryo_tank/Index.pdf deleted file mode 100644 index 6f289924808d6644eb6f0cf723e355c5f2af0f2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80569 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 0 else 0.0 + + dU_liq_dt = self._liquid_energy_rate( + info, Q_liq_to_ull, Q_leak_liq + ) _, mdot_He = self._solve_ullage_temperature_rate( - info, Q_liq_to_ull, Q_leak_ull + info, Q_liq_to_ull, Q_leak_ull, dU_liq_dt ) return mdot_He diff --git a/tests/cryo_tank/test_properties.py b/tests/cryo_tank/test_properties.py index dadf977..371340a 100644 --- a/tests/cryo_tank/test_properties.py +++ b/tests/cryo_tank/test_properties.py @@ -6,6 +6,7 @@ sys.path.insert(0, "src") from cryo_tank.properties import ( ln2_rho, ln2_h, ln2_u, ln2_T_from_u, + ln2_drho_dT_const_p, ln2_du_dT_const_p, he_u, he_h, he_cp, he_cv, ) from cryo_tank.config import P_WORKING @@ -32,6 +33,21 @@ class TestLN2Properties: T_recovered = ln2_T_from_u(u, P_WORKING) assert abs(T_recovered - T_orig) < 0.01 + def test_ln2_density_derivative_matches_finite_difference(self): + T = 78.0 + step = 1e-3 + actual = ln2_drho_dT_const_p(T, P_WORKING) + expected = ( + ln2_rho(T + step, P_WORKING) + - ln2_rho(T - step, P_WORKING) + ) / (2.0 * step) + assert actual < 0.0 + assert abs(actual - expected) / abs(expected) < 1e-5 + + def test_ln2_internal_energy_derivative_is_positive(self): + du_dT = ln2_du_dT_const_p(78.0, P_WORKING) + assert du_dT > 0.0 + class TestHeliumProperties: """Helium properties.""" diff --git a/tests/cryo_tank/test_tank_model.py b/tests/cryo_tank/test_tank_model.py index fef21e9..0fa354d 100644 --- a/tests/cryo_tank/test_tank_model.py +++ b/tests/cryo_tank/test_tank_model.py @@ -12,10 +12,9 @@ from cryo_tank.config import ( ) -def _make_tank(): +def _make_tank(**overrides): """Create a CryoTank with default config and MLI heat leak.""" - heat_leak = MLIHeatLeak(A_total=A_TOTAL, q_mli=1.0) - return CryoTank( + kw = dict( V_total=V_TOTAL, H_tank=H_TANK, P_work=P_WORKING, T_init=T_INIT, ullage_fraction=ULLAGE_FRACTION, @@ -23,8 +22,10 @@ def _make_tank(): mdot_out_ln2=MDOT_OUT_LN2, T_in_he=T_IN_HE, h_conv=H_CONV_SURFACE, T_env=T_ENV, - heat_leak_model=heat_leak, + heat_leak_model=MLIHeatLeak(A_total=A_TOTAL, q_mli=1.0), ) + kw.update(overrides) + return CryoTank(**kw) class TestGeometry: @@ -75,3 +76,37 @@ class TestInitialState: info = tank.derive(y0) P_He = info['P_He'] assert abs(P_He - P_WORKING) / P_WORKING < 1e-12 + + +class TestVolumeRate: + + def test_ullage_volume_rate_includes_liquid_thermal_expansion(self): + tank = _make_tank( + mdot_in_ln2=0.0, + mdot_out_ln2=0.0, + h_conv=0.0, + ) + y0 = tank.initial_state() + info = tank.derive(y0) + + Q_liq_to_ull = 0.0 + Q_leak = tank.heat_leak_model.compute(info['T_liq'], tank.T_env) + A_wet, A_dry = tank.wetted_areas(info['liquid_level']) + Q_leak_liq = Q_leak * A_wet / (A_wet + A_dry) + dU_liq_dt = tank._liquid_energy_rate( + info, Q_liq_to_ull, Q_leak_liq + ) + + dV_ull_dt = tank._ullage_volume_rate( + info, tank.dm_liq_dt, dU_liq_dt + ) + + y_next = y0.copy() + dt = 1.0 + y_next[1] += dU_liq_dt * dt + finite_difference = ( + tank.derive(y_next)['V_ull'] - info['V_ull'] + ) / dt + + assert dV_ull_dt < 0.0 + assert abs(dV_ull_dt - finite_difference) / abs(finite_difference) < 1e-5