From 376a71100d730c4ef8c61d95140bd83f4827d554 Mon Sep 17 00:00:00 2001 From: Ilya246 <57039557+Ilya246@users.noreply.github.com> Date: Tue, 8 Aug 2023 12:16:23 +0400 Subject: [PATCH] Fix radiator transfer rate in high-pressure environments (#18858) Co-authored-by: Kevin Zheng --- .../Atmos/EntitySystems/HeatExchangerSystem.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs index 7aa8b18949..8faa58d54c 100644 --- a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs +++ b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs @@ -58,7 +58,20 @@ public sealed class HeatExchangerSystem : EntitySystem // Positive dN flows from inlet to outlet var dt = (float)(_gameTiming.CurTime - device.LastProcess).TotalSeconds; var dP = inlet.Air.Pressure - outlet.Air.Pressure; - var dN = comp.G*dP*dt; + + // What we want is dN/dt = G*dP (first-order constant-coefficient differential equation w.r.t. P). + // However, by approximating dN = G*dP*dt using Forward Euler dN can be larger than all of the gas + // available for sufficiently large dP. However, we know that dN cannot exceed: + // + // dNMax = (n2T2/V2 - n1T1/V1)/(T2/V1 + T2/V2) = Δp/R/T2/(1/V1 + 1/V2) + // + // Because that is the amount of gas that needs to be transferred to equalize pressures [citation needed]. + // So we just limit abs(dN) < abs(dNMax). + // + // Also, by factoring out dP we can avoid taking any abs(). + // transferLimit below is equal to dNMax/dP + var transferLimit = 1/Atmospherics.R/outlet.Air.Temperature/(1/inlet.Air.Volume + 1/outlet.Air.Volume); + var dN = dP*Math.Min(comp.G*dt, transferLimit); GasMixture xfer; if (dN > 0)