代码仓库移植

This commit is contained in:
ljz committed 2026-06-03 15:41:04 +08:00
commit 0f57ba94f3
44 files changed
+7119

No files matched your search

+131
View File
@@ -0,0 +1,131 @@
# src/main.py
"""
Entry point: assemble tanks + pipe from config constants, run the solver,
verify total mass/energy conservation, persist history, and generate
plots + animation.
Run from project root:
python3 src/main.py
"""
import os
import sys
# Ensure imports work when running from project root
_HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, _HERE)
import numpy as np
from config import (
GAMMA, R_GAS,
V1, P1_INIT, T1_INIT,
V2, P2_INIT, T2_INIT,
L, D, N_CELLS,
MU, ROUGHNESS,
T_END, CFL, RIEMANN_SOLVER,
ANIMATION_STRIDE, OUTPUT_DIR,
)
from tank import Tank
from pipe import Pipe
from solver import run
from output import (
save_history,
plot_tank_pressure,
plot_tank_temperature,
plot_pipe_final_profiles,
make_pipe_animation,
write_summary_report,
)
def _total_mass(tank1, tank2, pipe):
pipe_mass = float(np.sum(pipe.W[0, :] * pipe.area * pipe.dx))
return tank1.mass + tank2.mass + pipe_mass
def _total_energy(tank1, tank2, pipe):
pipe_energy = float(np.sum(pipe.W[2, :] * pipe.area * pipe.dx))
return tank1.U + tank2.U + pipe_energy
def main():
os.makedirs(OUTPUT_DIR, exist_ok=True)
# --- Assemble ---
tank1 = Tank(V=V1, P_init=P1_INIT, T_init=T1_INIT, gamma=GAMMA, R_gas=R_GAS)
tank2 = Tank(V=V2, P_init=P2_INIT, T_init=T2_INIT, gamma=GAMMA, R_gas=R_GAS)
pipe = Pipe(L=L, D=D, N=N_CELLS, P_init=P2_INIT, T_init=T2_INIT,
gamma=GAMMA, R_gas=R_GAS, mu=MU, roughness=ROUGHNESS,
riemann_solver=RIEMANN_SOLVER)
m_init = _total_mass(tank1, tank2, pipe)
U_init = _total_energy(tank1, tank2, pipe)
print(f"Initial total mass: {m_init:.6e} kg")
print(f"Initial total energy: {U_init:.6e} J")
print(f"Initial P1 = {tank1.P/1e6:.3f} MPa, P2 = {tank2.P/1e6:.3f} MPa")
print(f"Pipe: L={L} m, D={D*1e3:.1f} mm, N={N_CELLS} cells, dx={pipe.dx*1e3:.1f} mm")
print(f"Riemann solver: {RIEMANN_SOLVER.upper()}")
if MU > 0:
print(f"Friction: mu={MU:.2e} Pa·s, roughness={ROUGHNESS:.2e} m (eps/D={ROUGHNESS/D:.4f})")
else:
print("Friction: OFF")
print(f"Running to t_end={T_END} s with CFL={CFL}...")
print()
# --- Run ---
history = run(tank1, tank2, pipe,
t_end=T_END, cfl=CFL,
verbose=True, log_every=200)
n_steps = len(history['t'])
print()
print(f"Simulation complete: {n_steps} steps")
# --- Conservation sanity check (per spec §6.1, §8) ---
m_final = _total_mass(tank1, tank2, pipe)
U_final = _total_energy(tank1, tank2, pipe)
rel_err_m = abs(m_final - m_init) / m_init
rel_err_U = abs(U_final - U_init) / U_init
print(f"Final total mass: {m_final:.6e} kg (rel err = {rel_err_m:.2e})")
print(f"Final total energy: {U_final:.6e} J (rel err = {rel_err_U:.2e})")
print(f"Final P1 = {tank1.P/1e6:.3f} MPa, P2 = {tank2.P/1e6:.3f} MPa")
assert rel_err_m < 1e-10, f"Total mass not conserved: rel_err={rel_err_m:.2e}"
assert rel_err_U < 1e-10, f"Total energy not conserved: rel_err={rel_err_U:.2e}"
# --- Persist + visualize ---
save_history(history, pipe,
os.path.join(OUTPUT_DIR, "history.npz"),
GAMMA, R_GAS)
plot_tank_pressure(history,
os.path.join(OUTPUT_DIR, "tank_pressure.png"))
plot_tank_temperature(history,
os.path.join(OUTPUT_DIR, "tank_temperature.png"))
plot_pipe_final_profiles(history, pipe,
os.path.join(OUTPUT_DIR, "pipe_final_profiles.png"),
GAMMA, R_GAS)
make_pipe_animation(history, pipe,
os.path.join(OUTPUT_DIR, "pipe_animation.gif"),
GAMMA, R_GAS, stride=ANIMATION_STRIDE)
write_summary_report(
history, pipe,
os.path.join(OUTPUT_DIR, "summary_report.html"),
GAMMA, R_GAS,
config={
'V1': V1, 'P1_INIT': P1_INIT, 'T1_INIT': T1_INIT,
'V2': V2, 'P2_INIT': P2_INIT, 'T2_INIT': T2_INIT,
'L': L, 'D': D, 'N_CELLS': N_CELLS,
'T_END': T_END, 'CFL': CFL,
},
)
print(f"Outputs written to {OUTPUT_DIR}/")
print(f" - history.npz")
print(f" - tank_pressure.png")
print(f" - tank_temperature.png")
print(f" - pipe_final_profiles.png")
print(f" - pipe_animation.gif")
print(f" - summary_report.html")
if __name__ == "__main__":
main()