Simulator for Fission Reactors


my brother and I have created a fission reactor simulator for GT6 in Python 3.7 with Qt. It is a project we started to get more familiar with the platform. It works fairly well, however, it is technically not finished in terms of UI. We did not perform rigorous testing of the simulation itself, but it has worked correctly thus far.

We have set up a repository on GitHub (GitHub - Klayto-235/GT6-Simulators: Simulator(s) for the Minecraft mod Gregtech 6.) and invite you to try it out. Also, we are keen on learning how to manage an open source project on GitHub, so you are encouraged to collaborate.

In terms of reactor designs, we’ve come up with a few basic uranium-based designs. Do try and improve on them and share your creations.

Happy melting!

U-238_4x.json (617 Bytes)
U-238_6x.json (937 Bytes)
U-235_9x.json (660 Bytes)
U-235_21x.json (1.2 KB)


Oh hey this looks cool!

Have you thought about making a web/wasm build for it as well?

Does it seem to replicate how GT6’s reactors themselves work well

Are the objects that you can use data driven in case mods add more (unlikely, but similar things have happened before)?


We have not thought about a web version, this was more of a learning project for Python/PyQt since these are not tools we typically use otherwise, but would be useful to know. We are also not aware of any simple way to turn Python (worse yet PyQt) into anything web based. If such a tool exists that would be interesting, rewriting it all is not all that appealing, at least not at the moment. Although come to think of it, it would be much more portable and probably work just as well.

Hopefully it should behave exactly like GT6 reactors, it took some crawling through GT6 source, hopefully there are no mistakes (we even made sure to use divup, so it really should be exactly the same). A simple test case also produced the exact same steady state neutron count so it seems to be working correctly.

As for the objects, adding fuel rods or coolants should be trivial and requires only an icon/color for the GUI and the corresponding data for the fuel/coolant. Adding utility rods (reflector/moderator/absorber) would also work, but at the moment the GUI treats the default 3 differently, so it might look a bit odd. That said, adding new utility rods or similarly new effects to coolants would also require a rewrite of GT6 code, so presumably that won’t happen. :smiley:


What was your thoughts on QT6? I don’t see people use the low level API that you used much anymore? Had you had any thoughts on the newer QtQuick API in QT5/QT6? What made your choice to use the older API?

Sadly not, not something that would run ‘in’ a webpage though, would be possible to host something, but then that’s not free. ^.^;


Yeah, adding in things could only be ‘changed stats’ of existing things, otherwise yeah, a rewrite of a lot of things, lol.

1 Like

Initially we just went with what we found online. So at first the reactor grid was just a grid of buttons, but that turned out to be quite slow (creating the buttons, changing their colors via stylesheet changes, etc). It also didn’t have a way to zoom the whole thing. Then came the Googling, from what I found most of the new stuff (QtQuick, QML) is presumably slower than Stylesheets which in turn are slower than a QGraphicsView. Unfortunately, this also doesn’t work very well (make a large grid, it’ll lag a bit); this seems to be to some extent related to Python and to some to the CPU rendering that Qt defaults to. While it is possible to implement OpenGL rendering with not too much work, we have not yet bothered to do so, particularly because it’s not clear if there will be much benefit (we’d have to rewrite the paint events which would cause extra python function calls which as we know are disturbingly expensive). So it would reduce the rendering load but possibly just add even more as a result of function call overhead, so… not very enticing.

In general, at least for my part, I don’t think I can say much about Qt from this, since I suspect most of the issues I had with it (this time around) are related to Python (and PyQt). I would have to try it in C++, but that’s even less portable than Python so definitely not for this. And I’m not very excited about it for any other projects, I tried once a few years back and the open file dialog caused my Linux kernel to crash in such a spectacular way it didn’t post any error messages, it just froze. I had to hard reset the computer. And it did this consistently. :slight_smile:

P.S.: Why does butt automatically link to Wikipedia?

P.P.S.: Anyway, figure out some good designs with as high an efficiency as possible (without using Thorium salts as a coolant, or IC2 for that matter) and post them here! Maybe we could make a contest, best U238 only design, best U235 etc? :smiley:


It’s not that they are slow, it’s just that QtQuick and such are full GL rendering contexts, just have to keep some things in mind for those, and if you do they can actually be a lot faster than standard blitting rendering. :slight_smile:

Python itself adds a lot of overhead though, this is all more easily and efficiently done in native code. Python’s QT mappings are mostly just for ease of whipping together Qt UI’s, definitely not for speed. ^.^;

C++ is technically more portable than Python, you just have to compile it for what you want to run on though, lol.

That’s impossible, nothing in userland can do anything of the sort to the kernel unless there’s a major kernel or buggy driver bug. QT calls the native systems File dialog box if available, else it renders its own, all very trivial operations though; my guess is that when it called to open your system default file dialog box then ‘that’ is what was having issues. Do you know what DE you had at the time?

No clue but I’d bet something Greg did? ^.^;

EDIT: Yep, it’s something greg did, lol.

1 Like

Perhaps we should have gone with that then, well, if we ever feel like rewriting that bit (again) maybe, but I don’t believe either of us have the time right now. And yes, this was supposed to be one of those simple Qt UIs, initially we did not even consider the possibility of anything this simple being this demanding, after all there is a relatively small number of objects to handle. As for portability, sure, but it’s still easier for people to install Python and just run a script than learn to compile (or even just use a makefile on Windows, which cmd does not recognise by default). Of course if this was the main goal then something browser based would have been even better.

I agree, and yet somehow something did break spectacularly. The odd thing was it only ever happened with the Qt program, anything else using the open file dialog worked just fine. I am not sure what DE it was, it might have been Gnome 3 (with xorg). I didn’t dig too deep there though, had better things to do.


In the newest commit you mentioned finding a potential bug in the GT6 code and I can confirm it is indeed a small oversight.
@Gregorius The breeder and absorber rod in some cases output more heat than intended, because they don’t consider the coolant used. I think it will just be easier if I outline the small changes required for fixing this here than make a pull request, just replace line 77 with:

int tDivider = 2;
if (MT.Na.mLiquid.isFluidEqual(aReactor.mTanks[0].getFluid())) tDivider *= 12;
else if (MT.Sn.mLiquid.isFluidEqual(aReactor.mTanks[0].getFluid())) tDivider *= 6;
aReactor.mEnergy += UT.Code.divup(aReactor.oNeutronCounts[aSlot], tDivider);

and line 46 with:

int tDivider = 1;
if (MT.Na.mLiquid.isFluidEqual(aReactor.mTanks[0].getFluid())) tDivider *= 6;
else if (MT.Sn.mLiquid.isFluidEqual(aReactor.mTanks[0].getFluid())) tDivider *= 3;
aReactor.mEnergy += UT.Code.divup(aReactor.oNeutronCounts[aSlot] * 2, tDivider);

Since this only means that some reactors will output less HU energy, there should be no danger of explosions to existing designs, neutron counts aren’t changed so control systems will still work the same.

The issue can also be fixed in another way, which may provide a better code structure and minimally better performance, by applying the heat modification in the reactor class rather than on the fuel rod. In at line 106 and in at line 133 this could be added:

int tDivider = 1;
if (MT.Na.mLiquid.isFluidEqual(mTanks[0].getFluid())) tDivider *= 6;
else if (MT.Sn.mLiquid.isFluidEqual(mTanks[0].getFluid())) tDivider *= 3;
mEnergy = UT.Code.divup(mEnergy - tEnergy, tDivider) + tEnergy;

and then changing line 189-192 to just:

aReactor.mEnergy += aReactor.oNeutronCounts[aSlot];

I would highly recommend a pull request for that one, and make sure your Dev Env doesnt mess up the whitespace again.


Ok, pull request has been made. Since I got the development environment to build this time, I could also test that these changes work correctly. Went with the second, cleaner approach.


Yeah that was one reason i wanted you to make a pull request, so you can actually test it.

1 Like

If you could, it would be great if you just give me a heads up when this gets released so that I fix the simulator.


He submitted a PR and I accepted it, so just check the GT6 GitHub Page :wink:

1 Like

What version of PyQt6 did you use? In the one I installed (6.2.3) I get various errors, for example ArrowCursor is PyQt6.QtCore.Qt.CursorShape.ArrowCursor and not PyQt6.QtCore.Qt.ArrowCursor. There were other issues but I didn’t try to fix them since I’m not that familiar with Qt or PyQt6


It was written in Python 3.7 with PyQt6 (6.0.3).
I’ve moved this to a branch and now main is ported to 3.10 and 6.2.3 (make sure you have a new version of pyqtgraph too), so hopefully it’ll work for you now!

One note, it is not updated to include the latest change in GT (durability now updates every tick and durability loss is related to neutron count on the rod rather than neutron output of the rod).
While I think the change makes sense, since it penalizes bad fuels (U238), it is more than 2 lines to fix and I haven’t had time yet. Also because when I do take the time I should rewrite the simulation class anyway, since it’s a mess that was written as I was decrypting how things work, I think I recently noticed that in some cases the simulation doesn’t EXACTLY match the behaviour with time, though the steady state was correct. So yeah, I’ll fix that at some point in the not too far future, hopefully.
Until such time there is an experimental branch that, probably, reflects the change in GT, but it’s not been tested and it doesn’t terminate the same tick that a rod depletes but rather at the end of the corresponding second (20 ticks), in most cases that’s fairly irrelevant and you probably won’t care. I think GT should notice this after the tick, but I’m not even sure about that, have to check the code again to see when it checks neighbouring rods and itself, I forgot, might be it does the same.
Note that this is for version 6.14.24 that has not been released yet, but the change will affect reactor efficiency, a reactor that might be very good now might not be so good once that change is applied.


Thanks, I’m able to run it now. I’m getting errors if I try to open options or material costs, though.


Good catch, I forgot to do those, that’s why we have beta testers such as yourself! Please let me know if you find anything else. (I think options and material costs work in all 3 branches now, but testing was very limited maybe there’s an option I forgot to fix, these are work hours after all.)


Sorry to necrobump, but with all the new nuclear changes that happened in the last few months, I just wanted to know if you were thinking of eventually reviving the project, or of it technically still works well enough.


Hmm, yes, that has crossed my mind. I’m not the one who implemented the simulation part though. And, honestly, I don’t want to reverse engineer that clump of crusty spaghetti ( :thinking: @Qubituary).

However, I have resumed work on the web version. That might take some time at my pace though.


Whoa whoa rude rude. I agree that bit could be cleaner but in my defense it was built on the go while digging through the 20 java files that hold bits and pieces so you know, I’ll pass the blame on to someone else. :slight_smile:

Anyway, I’ll take a look at what changed.