From 6835e6b4aa40967ca7263a2ae8391a33ab2d0b2d Mon Sep 17 00:00:00 2001 From: Partmedia Date: Sat, 15 Jun 2024 13:05:57 -0800 Subject: [PATCH] Adjust TEG efficiency curve, remove heat transfer limit (#29050) The TEG used to limit hot-cold energy transfer based on actual power drawn, and had maximum efficiency at whatever temperature difference. This PR adjusts the hot-cold energy transfer to be uncapped, "venting" the excess heat that is not used to generate power, and adds an efficiency curve that limits efficiency at low thermal temperatures. People have been cheesing the TEG by hooking up the hot end to the CO2 miner (which produces infinite, room-temperature gas) and the cold end to a space radiator. With this change, you will actually need to set up a burn chamber in order to get appreciable power out of the TEG (see below). If you build a gas holding chamber, you will have to throttle the gas flowing into the TEG instead of constantly cycling the gas through over and over again. --- .../Power/Generation/Teg/TegSystem.cs | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/Content.Server/Power/Generation/Teg/TegSystem.cs b/Content.Server/Power/Generation/Teg/TegSystem.cs index 540bd6c483..bc1bff052c 100644 --- a/Content.Server/Power/Generation/Teg/TegSystem.cs +++ b/Content.Server/Power/Generation/Teg/TegSystem.cs @@ -128,7 +128,6 @@ public sealed class TegSystem : EntitySystem // Shift ramp position based on demand and generation from previous tick. var curRamp = component.RampPosition; var lastDraw = supplier.CurrentSupply; - // Limit amount lost/gained based on power factor. curRamp = MathHelper.Clamp(lastDraw, curRamp / component.RampFactor, curRamp * component.RampFactor); curRamp = MathF.Max(curRamp, component.RampMinimum); component.RampPosition = curRamp; @@ -138,17 +137,28 @@ public sealed class TegSystem : EntitySystem if (airA.Pressure > 0 && airB.Pressure > 0) { var hotA = airA.Temperature > airB.Temperature; - var cHot = hotA ? cA : cB; - - // Calculate maximum amount of energy to generate this tick based on ramping above. - // This clamps the thermal energy transfer as well. - var targetEnergy = curRamp / _atmosphere.AtmosTickRate; - var transferMax = targetEnergy / (component.ThermalEfficiency * component.PowerFactor); // Calculate thermal and electrical energy transfer between the two sides. - var δT = MathF.Abs(airA.Temperature - airB.Temperature); - var transfer = Math.Min(δT * cA * cB / (cA + cB - cHot * component.ThermalEfficiency), transferMax); - electricalEnergy = transfer * component.ThermalEfficiency * component.PowerFactor; + // Assume temperature equalizes, i.e. Ta*cA + Tb*cB = Tf*(cA+cB) + var Tf = (airA.Temperature * cA + airB.Temperature * cB) / (cA + cB); + // The maximum energy we can extract is (Ta - Tf)*cA, which is equal to (Tf - Tb)*cB + var Wmax = MathF.Abs(airA.Temperature - Tf) * cA; + + var N = component.ThermalEfficiency; + + // Calculate Carnot efficiency + var Thot = hotA ? airA.Temperature : airB.Temperature; + var Tcold = hotA ? airB.Temperature : airA.Temperature; + var Nmax = 1 - Tcold / Thot; + N = MathF.Min(N, Nmax); // clamp by Carnot efficiency + + // Reduce efficiency at low temperature differences to encourage burn chambers (instead + // of just feeding the TEG room temperature gas from an infinite gas miner). + var dT = Thot - Tcold; + N *= MathF.Tanh(dT/700); // https://www.wolframalpha.com/input?i=tanh(x/700)+from+0+to+1000 + + var transfer = Wmax * N; + electricalEnergy = transfer * component.PowerFactor; var outTransfer = transfer * (1 - component.ThermalEfficiency); // Adjust thermal energy in transferred gas mixtures. -- 2.51.2