[15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Sat May 27, 2017 7:00 am
by D0SBoots
Steps to reproduce: Build the layout shown in the screenshot. The first command was run with everything fresh (both reactors at 15C). Then I manually inserted 1 fuel, let it burn to completion, and ran the command again. The discrepancy is 100% reproducible for me, no matter how many times I rebuild it.
Re: [15.15] Nuclear Reactor provides 8.04444GJ of power
Posted: Sat May 27, 2017 7:10 am
by Choumiko
Its 800.044 (or 800,044 in your region)
Re: [15.15] Nuclear Reactor provides 8.04444GJ of power
Posted: Sat May 27, 2017 9:14 pm
by D0SBoots
The temperature rise of the reactors is 800.004444C. Because nuclear reactors have a heat capacity of 10 MJ/K, that means 8.00004444GJ were burned.
Edit: I see what you were getting at now, I failed at decimals.
Re: [15.15] Nuclear Reactor provides 8.04444GJ of power
Posted: Mon May 29, 2017 3:42 am
by TruePikachu
Did you fuel both reactors or only one of them?
Re: [15.15] Nuclear Reactor provides 8.04444GJ of power
Posted: Mon May 29, 2017 9:16 am
by D0SBoots
Only one.
Now that I think of it, only one reactor is required for the demonstration, as long as it's fresh-built. That also simplifies the console commands to print the temperature.
Re: [15.15] Nuclear Reactor provides 8.04444GJ of power
Posted: Mon May 29, 2017 9:35 am
by BenSeidel
Unfortunately, in computer science, 1+1≠2.
Re: [15.15] Nuclear Reactor provides 8.04444GJ of power
Posted: Mon May 29, 2017 9:37 am
by mrvn
What exactly is the "discrepancy" here? The reactor was cold. You insert fuel, it gets hot. Is the problem that a single fuel cell makes it rise 800°? That a 800° rise is way to much energy for the heat capacity the reactor is supposed to have?
Re: [15.15] Nuclear Reactor provides 8.04444GJ of power
Posted: Mon May 29, 2017 1:11 pm
by posila
I assume you don't like the .0044444 part. It is minor issue. Everything is calculated in ticks, there are 60 ticks in second, and dividing by 60 creates ugly values that create some floating point errors.
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Mon May 29, 2017 5:02 pm
by D0SBoots
Thanks. I figured it was a minor issue, but the procedure seemed to be to let you guys do the triaging.
I don't think this is a floating-point issue, though - the effect is several orders of magnitude too large and the resulting fraction is too regular. It's as if the reactor is running for an extra 1/15 of a tick - which I know isn't possible, but that's how the math comes out.
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Tue May 30, 2017 3:38 am
by TruePikachu
D0SBoots wrote:the resulting fraction is too regular
? (rational 800.00444444441d0) ;; This is the _exact_ value of the number
3518456755756431/4398046511104
? (rationalize 800.00444444441d0) ;; This is the closest "reasonable" fraction to the number
102923312593/128653426
Yeah, I can't figure out how that temperature was arrived at.
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Tue May 30, 2017 11:47 am
by orzelek
It might be because you are doing direct calculations not arriving at the result by summing up over ticks.
My guess is that rounding error will cumulate over each tick resulting in different result then direct calculation.
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Tue May 30, 2017 12:10 pm
by mrvn
He is summing up heat per tick.
But is the game counting heat or energy? As you seem to talking purely about a rounding error that makes a difference.
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Fri Jun 09, 2017 5:44 am
by D0SBoots
An issue cropped up that I suspected was related, so I dug into this further. The related issue is that I was trying to do "steady state" measurements of various nuclear setups, but I noticed that the temperatures kept periodically fluctuating, and I quickly determined it was happening at the end of the nuclear cycle, which made me suspect this.
So, I decided to do a tick-by-tick log of the temperature of a fresh, unconnected reactor across two fuel cycles (because after that, its temperature is maxed out.)
Here's the script if you want to try yourself. (The console will strip newlines, and lua doesn't care, so you can just copy-paste the whole thing in):
local end_tick = game.tick + 16000
local filename = "reactor-temperatures.csv"
local acc = {}
local fun = function(e)
local result = {e.tick}
local reactors = game.surfaces[1].find_entities_filtered{name = "nuclear-reactor"}
for i, v in ipairs(reactors) do
result[i+1] = v.temperature
end
acc[#acc+1] = table.concat(result, ",")
if e.tick >= end_tick then
acc[#acc+1] = ""
game.write_file(filename, table.concat(acc, "\n"))
game.print("Wrote " .. filename)
script.on_event(defines.events.on_tick, nil)
end
end
script.on_event(defines.events.on_tick, fun)
That gives a buffer of 15 seconds to insert two fuel into the reactor once you execute the script. It will print a log line when it's finished, and the output will look like this:
The key is what's happening on tick 1612668 (in my game): An extra tick is spent adding 0.00444444444 temperature to the reactor. Furthermore, this explains the fluctuations in the otherwise steady-state behavior: 1 out of every 12001 ticks, the reactor is producing almost no heat. I thought the small extra fraction might be there to balance out the one extra tick, so that the average power output remains 40MW, but that's not the case either: The average power ends up being 800.00444444/20*12000/12001 ~= 39.9969MW.
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Fri Jun 09, 2017 8:47 am
by mrvn
Looks like a fuel cell has an amount of fuel not divisible by the amount spend each tick. So at 12001 only 1/15th remains and only gives a little heat.
Did you put only one fuel cell into the reactor at a time? What I mean is: If there is a second fuel cell ready to go will it give a full ticks heat using part of the second fuel cell?
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Fri Jun 09, 2017 4:36 pm
by D0SBoots
I put two fuel cells in at the same time (well, technically one followed very quickly by a second) because I wanted to test exactly that. The "stutter" happens even with fuel ready and waiting.
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Sun Jun 11, 2017 8:23 am
by D0SBoots
So, I've discovered two more things:
1. This affects more than just the nuclear reactor, it affects boilers too. Setup: One boiler feeding one storage tank, run this script and then manually feed it 50 coal.
local end_tick = game.tick + 7000
local filename = "boiler-steam.csv"
local acc = {}
local fun = function(e)
local result = {e.tick}
local steam = 0
local boilers = game.surfaces[1].find_entities_filtered{name = "boiler"}
for i, v in ipairs(boilers) do
local box = v.fluidbox[2]
if box then
steam = steam + box.amount
end
end
local tanks = game.surfaces[1].find_entities_filtered{name = "storage-tank"}
for i, v in ipairs(tanks) do
local box = v.fluidbox[1]
if box then
steam = steam + box.amount
end
end
result[2] = steam
acc[#acc+1] = table.concat(result, ",")
if e.tick >= end_tick then
acc[#acc+1] = ""
game.write_file(filename, table.concat(acc, "\n"))
game.print("Wrote " .. filename)
script.on_event(defines.events.on_tick, nil)
end
end
script.on_event(defines.events.on_tick, fun)
What's really interesting here is that unlike with the nuclear reactor, a boiler burning coal would naturally have a "partial tick" in its cycle. 1.8MW = 30kJ/tick, 133 ticks * 30kJ/tick = 3990J, so there's 10J = .333333 units of steam left over after it finishes its full-burning ticks. But that's not the fraction we see - instead we see the same 1/15 fraction that we saw with the nuclear reactor. It's as if something in the game is hardcoded somehow to round any partial tick at the end of a burner cycle to 1/15, even if it should have come out even.
As an aside, this means that the actual average power output of a boiler is 1.787462MW (when burning coal).
2. The second thing I realized is that since this is more widespread, it's a dup of viewtopic.php?f=7&t=48374. Although it's weird that it being more widespread would make it not a bug...
Re: [15.15] Nuclear Reactor provides 8.00004GJ of power
Posted: Sun Jun 11, 2017 11:36 pm
by D0SBoots
OK, I've tracked this down to a small but definite bug in the burner subsystem.
Code and results hidden for length
Setup: Boiler with 50 coal directly connected to an offshore pump and two steam engines, and 4 beacons to completely load it.
local end_tick = game.tick + 1500
local filename = "boiler-coal3.csv"
local acc = {}
local fun = function(e)
local result = {e.tick}
local steam = 0
local boilers = game.surfaces[1].find_entities_filtered{name = "boiler"}
for i, v in ipairs(boilers) do
result[2] = v.burner.remaining_burning_fuel
local box = v.fluidbox[2]
if box then
result[3] = box.amount
end
end
local tanks = game.surfaces[1].find_entities_filtered{name = "steam-engine"}
for i, v in ipairs(tanks) do
local box = v.fluidbox[1]
if box then
steam = box.amount
end
end
result[4] = steam
acc[#acc+1] = table.concat(result, ",")
if e.tick >= end_tick then
acc[#acc+1] = ""
game.write_file(filename, table.concat(acc, "\n"))
game.print("Wrote " .. filename)
script.on_event(defines.events.on_tick, nil)
end
end
script.on_event(defines.events.on_tick, fun)
What's interesting is that the burner's fuel_remaining decreases by 60000J/tick, as expected, until the tick after it goes negative, where the whole tick is spent just adding the next fuel and applying the deficit to the new fuel. In the tick after that, the fuel_remaining goes down by 64000J - 60000 for the current tick, and 4000J for the previous one, as can be seen by the drop in steam. This is the 1/15 of a tick that we've seen before.
However, because the boiler is flexible in how quickly it burns, I've played around with it and discovered that the 1/15 isn't a rule, but actually an upper limit. In that second tick after the wrap-around, the burner is being limited to 16/15 of its usual maximum capacity for that tick. So, if the boiler is running at 8/15 of capacity or below, the bug doesn't appear at all - all the numbers are perfectly regular, with no anomaly in steam production. At higher capacities, you start seeing the anomaly as the production is artificially low for one tick, but the boiler then goes to max production for a few ticks to compensate, and since there are large fluidbox buffers nobody notices. It's only when running at or near maximum capacity that this becomes noticeable. And since the nuclear reactor (and other burners, like the furnaces) are always running flat-out, the bug always affects them.