[15.15] Nuclear Reactor provides 8.00004GJ of power

We are aware of them, but they have low priority. We have more important things to do. They go here in order not to take space in the main bug thread list.
Post Reply
D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

[15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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.
Attachments
Nuclear Bug.jpg
Nuclear Bug.jpg (239.52 KiB) Viewed 5991 times
Last edited by D0SBoots on Mon May 29, 2017 4:45 pm, edited 1 time in total.

Choumiko
Smart Inserter
Smart Inserter
Posts: 1352
Joined: Fri Mar 21, 2014 10:51 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.04444GJ of power

Post by Choumiko »

Its 800.044 (or 800,044 in your region)

D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.04444GJ of power

Post 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. :(
Last edited by D0SBoots on Mon May 29, 2017 4:47 pm, edited 1 time in total.

User avatar
TruePikachu
Filter Inserter
Filter Inserter
Posts: 978
Joined: Sat Apr 09, 2016 8:39 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.04444GJ of power

Post by TruePikachu »

Did you fuel both reactors or only one of them?

D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.04444GJ of power

Post 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.

BenSeidel
Filter Inserter
Filter Inserter
Posts: 584
Joined: Tue Jun 28, 2016 1:44 am
Contact:

Re: [15.15] Nuclear Reactor provides 8.04444GJ of power

Post by BenSeidel »

Unfortunately, in computer science, 1+1≠2.

mrvn
Smart Inserter
Smart Inserter
Posts: 5703
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: [15.15] Nuclear Reactor provides 8.04444GJ of power

Post 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?

posila
Factorio Staff
Factorio Staff
Posts: 5201
Joined: Thu Jun 11, 2015 1:35 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.04444GJ of power

Post 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.

D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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.

User avatar
TruePikachu
Filter Inserter
Filter Inserter
Posts: 978
Joined: Sat Apr 09, 2016 8:39 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post by TruePikachu »

D0SBoots wrote:the resulting fraction is too regular

Code: Select all

? (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
Hm, I'll try to replicate that number...

Code: Select all

? (defconstant +uranium-burn-ticks+ (* 60 200))
+URANIUM-BURN-TICKS+
? (defconstant +double-heat-rise-per-tick+ (float (/ 800 +uranium-burn-ticks+) 1.0d0))
+DOUBLE-HEAT-RISE-PER-TICK+
? +double-heat-rise-per-tick+
0.06666666666666667D0
? (loop :with temperature = 15.0d0 :for n :from 0 :below +uranium-burn-ticks+ :do (incf temperature +double-heat-rise-per-tick+) :finally (return (- temperature 15.0d0)))
800.0000000002171D0
Yeah, I can't figure out how that temperature was arrived at.

orzelek
Smart Inserter
Smart Inserter
Posts: 3911
Joined: Fri Apr 03, 2015 10:20 am
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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.

mrvn
Smart Inserter
Smart Inserter
Posts: 5703
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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.

D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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):

Code: Select all

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:

Code: Select all

1600405,15
1600406,15
1600407,15
1600408,15
...
1600666,15
1600667,15
1600668,15.066666666667
1600669,15.133333333333
1600670,15.2
1600671,15.266666666667
1600672,15.333333333333
1600673,15.4
1600674,15.466666666667
...
1612662,814.66666666688
1612663,814.73333333355
1612664,814.80000000022
1612665,814.86666666688
1612666,814.93333333355
1612667,815.00000000022
1612668,815.00444444466
1612669,815.07111111133
1612670,815.13777777799
1612671,815.20444444466
1612672,815.27111111133
1612673,815.337777778
...
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.

mrvn
Smart Inserter
Smart Inserter
Posts: 5703
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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?

D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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.

D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post 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.

Code: Select all

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)
The output looks like this:

Code: Select all

...
1629087,0
1629088,0
1629089,0
1629090,1
1629091,2
1629092,3
...
1629220,131
1629221,132
1629222,133
1629223,133.06666666667
1629224,134.06666666667
1629225,135.06666666667
...
1629354,264.06666666667
1629355,265.06666666667
1629356,266.06666666667
1629357,266.13333333333
1629358,267.13333333333
1629359,268.13333333333
...
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...

D0SBoots
Inserter
Inserter
Posts: 43
Joined: Sat Nov 05, 2016 10:11 pm
Contact:

Re: [15.15] Nuclear Reactor provides 8.00004GJ of power

Post by D0SBoots »

OK, I've tracked this down to a small but definite bug in the burner subsystem.
Code and results hidden for length
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.

Post Reply

Return to “Minor issues”