Skip to content

Commit

Permalink
async reactor simulation
Browse files Browse the repository at this point in the history
fake ticks are wonderful things
  • Loading branch information
RogueLogix committed Feb 3, 2024
1 parent 02ff3a3 commit 9fe97f8
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package net.roguelogix.biggerreactors.multiblocks.reactor.simulation.cpu;

import net.roguelogix.biggerreactors.multiblocks.reactor.simulation.SimulationConfiguration;
import net.roguelogix.biggerreactors.multiblocks.reactor.simulation.SimulationDescription;

public class AsyncReactorSimulation extends FullPassReactorSimulation {

private final Thread asyncThread = new Thread(this::asyncThreadFunc);

private boolean requestRunning;
private double runningResultAverageIntensity = 0;
private double currentResultAverageIntensity = 0;
private final ReactorStateData asyncReactorStateData = new ReactorStateData();
private final IrradiationResult currentResult = new IrradiationResult();
private final IrradiationResult scaledResult = new IrradiationResult();
public int tickNumber = 0;
public int realTicks = 0;

public AsyncReactorSimulation(SimulationDescription simulationDescription, SimulationConfiguration configuration) {
super(simulationDescription, configuration);
asyncThread.setDaemon(true);
asyncThread.setName(this.getClass().getSimpleName());
asyncThread.start();
}

private void asyncThreadFunc() {
while (true) {
if (!requestRunning) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
continue;
}
runIrradiationRequest(fullPassIrradiationRequest, asyncReactorStateData);
requestRunning = false;
}
}

@Override
protected double radiate() {
setupIrradiationTick();
if (!requestRunning) {
realTicks++;
currentResult.fuelRFAdded = fullPassIrradiationRequest.result.fuelRFAdded;
currentResult.fuelRadAdded = fullPassIrradiationRequest.result.fuelRadAdded;
currentResult.caseRFAdded = fullPassIrradiationRequest.result.caseRFAdded;

fullPassIrradiationRequest.updateCache();
asyncReactorStateData.update(this);
currentResultAverageIntensity = runningResultAverageIntensity;
runningResultAverageIntensity = 0;
for (int i = 0; i < initialIntensties.length; i++) {
runningResultAverageIntensity += initialIntensties[i];
}
runningResultAverageIntensity /= initialIntensties.length;
if (realTicks < 2) {
runIrradiationRequest(fullPassIrradiationRequest, asyncReactorStateData);
} else {
requestRunning = true;
asyncThread.interrupt();
}
}

scaledResult.fuelRFAdded = currentResult.fuelRFAdded;
scaledResult.fuelRadAdded = currentResult.fuelRadAdded;
scaledResult.caseRFAdded = currentResult.caseRFAdded;

double averageIntensity = 0;
for (int i = 0; i < initialIntensties.length; i++) {
averageIntensity += initialIntensties[i];
}
averageIntensity /= initialIntensties.length;

double scalingFactor = averageIntensity / currentResultAverageIntensity;

scaledResult.fuelRFAdded *= scalingFactor;
scaledResult.fuelRadAdded *= scalingFactor;
scaledResult.caseRFAdded *= scalingFactor;

collectIrradiationResult(scaledResult);
tickNumber++;
return realizeIrradiationTick();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ protected static class IrradiationResult {
protected double initialHardness;

protected IrradiationRequest fullPassIrradiationRequest;
protected final ReactorStateData reactorStateData = new ReactorStateData();

protected double rawFuelUsage = 0;
protected double fuelRFAdded = 0;
Expand All @@ -124,7 +125,7 @@ protected double radiate() {

setupIrradiationTick();
fullPassIrradiationRequest.updateCache();
runIrradiationRequest(fullPassIrradiationRequest);
runIrradiationRequest(fullPassIrradiationRequest, reactorStateData);
collectIrradiationResult(fullPassIrradiationRequest.result);
return realizeIrradiationTick();
}
Expand Down Expand Up @@ -182,6 +183,8 @@ protected void setupIrradiationTick() {

this.rawFuelUsage = rawFuelUsage / controlRods.length;
this.fuelRFAdded = fuelRFAdded;

reactorStateData.update(this);
}

protected void collectIrradiationResult(IrradiationResult result) {
Expand Down Expand Up @@ -222,7 +225,40 @@ protected double realizeIrradiationTick() {
return rawFuelUsage;
}

protected void runIrradiationRequest(IrradiationRequest request) {
protected static class ReactorStateData {

int x, z;
SimUtil.ControlRod[][] controlRodsXZ;
SimUtil.ControlRod[] controlRods;
double[] initialIntensities;
double initialHardness;
double fuelAbsorptionTemperatureCoefficient;

public void update(FullPassReactorSimulation reactor) {
if(x != reactor.x || z != reactor.z || controlRods.length != reactor.controlRods.length){
x = reactor.x;
z = reactor.z;
controlRodsXZ = new SimUtil.ControlRod[x][z];
controlRods = new SimUtil.ControlRod[reactor.controlRods.length];
for (int i = 0; i < controlRods.length; i++) {
var reactorRod = reactor.controlRods[i];
var copyRod = new SimUtil.ControlRod(reactorRod.x, reactorRod.z);
controlRods[i] = copyRod;
controlRodsXZ[copyRod.x][copyRod.z] = copyRod;
}
initialIntensities = new double[reactor.initialIntensties.length];
}

for (int i = 0; i < initialIntensities.length; i++) {
controlRods[i].insertion = reactor.controlRods[i].insertion;
initialIntensities[i] = reactor.initialIntensties[i];
}
initialHardness = reactor.initialHardness;
fuelAbsorptionTemperatureCoefficient = reactor.fuelAbsorptionTemperatureCoefficient;
}
}

protected void runIrradiationRequest(IrradiationRequest request, ReactorStateData reactorState) {
final double FuelAbsorptionCoefficient = this.FuelAbsorptionCoefficient;
final double FuelModerationFactor = this.FuelModerationFactor;
final double fuelHardnessMultiplier = this.fuelHardnessMultiplier;
Expand All @@ -236,12 +272,12 @@ protected void runIrradiationRequest(IrradiationRequest request) {
int rods = 0;
for (int cro = 0; cro < request.controlRodCount; cro++) {
final int cri = cro + request.baseControlRod;
final var controlRod = controlRods[cri];
final var initialIntensity = initialIntensties[cri] * rayMultiplier;
final var controlRod = reactorState.controlRods[cri];
final var initialIntensity = reactorState.initialIntensities[cri] * rayMultiplier;
for (int i = 0; i < SimUtil.rays.size(); i++) {
for (int j = 0; j < intensities.length; j++) {
intensities[j] = initialIntensity;
hardnesses[j] = initialHardness;
hardnesses[j] = reactorState.initialHardness;
}
final var raySteps = SimUtil.rays.get(i);
//noinspection ForLoopReplaceableByForEach
Expand Down Expand Up @@ -281,7 +317,7 @@ protected void runIrradiationRequest(IrradiationRequest request) {
} else {
// Scale control rod insertion 0..1
// TODO: race condition with computer craft is possible here
final double controlRodInsertion = controlRodsXZ[currentX][currentZ].insertion * .001;
final double controlRodInsertion = reactorState.controlRodsXZ[currentX][currentZ].insertion * .001;
final double halfRodInsertion = controlRodInsertion * 0.5;
// Full insertion doubles the moderation factor of the fuel as well as adding its own level
final double fuelModerationFactor = FuelModerationFactor + (FuelModerationFactor * controlRodInsertion + controlRodInsertion);
Expand All @@ -306,7 +342,7 @@ protected void runIrradiationRequest(IrradiationRequest request) {
// Fuel absorptiveness is determined by control rod + a heat modifier.
// Starts at 1 and decays towards 0.05, reaching 0.6 at 1000 and just under 0.2 at 2000. Inflection point at about 500-600.
// Harder radiation makes absorption more difficult.
final double baseAbsorption = fuelAbsorptionTemperatureCoefficient * (1.0 - (neutronHardness * fuelHardnessMultiplier));
final double baseAbsorption = reactorState.fuelAbsorptionTemperatureCoefficient * (1.0 - (neutronHardness * fuelHardnessMultiplier));

// Some fuels are better at absorbing radiation than others
final double scaledAbsorption = baseAbsorption * stepFuelAbsorptionCoefficient;
Expand Down Expand Up @@ -348,7 +384,7 @@ public static class MultiThreaded extends FullPassReactorSimulation {
protected final Event[] irradiationRequestEvents;
@Nullable
private Event doneEvent;
private final Runnable mainRunnable = () -> runIrradiationRequest(fullPassIrradiationRequest);
private final Runnable mainRunnable = () -> runIrradiationRequest(fullPassIrradiationRequest, reactorStateData);

public MultiThreaded(SimulationDescription simulationDescription, SimulationConfiguration configuration) {
this(simulationDescription, configuration, false);
Expand All @@ -368,7 +404,7 @@ public MultiThreaded(SimulationDescription simulationDescription, SimulationConf
int baseRod = i * batchSize;
int rodCount = Math.min(batchSize, controlRods.length - baseRod);
final var request = new IrradiationRequest(baseRod, rodCount, cacheArray, y);
irradiationRequestRunnables[i] = () -> runIrradiationRequest(request);
irradiationRequestRunnables[i] = () -> runIrradiationRequest(request, reactorStateData);
irradiationRequests[i] = request;
}
} else {
Expand Down

0 comments on commit 9fe97f8

Please sign in to comment.