summaryrefslogtreecommitdiff
path: root/opendc-simulator
diff options
context:
space:
mode:
authorDante Niewenhuis <d.niewenhuis@hotmail.com>2025-03-14 15:33:42 +0100
committerGitHub <noreply@github.com>2025-03-14 15:33:42 +0100
commit7dc2639a7fcdf51ef789f4af2e3afff11438be6e (patch)
tree9a67f432f1aa31e57b20471b6cca61e01ccdea70 /opendc-simulator
parent5ec41d49b497010783d25bf13bc042d3e76824e3 (diff)
Added more battery policies (#312)
* some updates * Updates * Added comments and renamed variables * Ran Spotless
Diffstat (limited to 'opendc-simulator')
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java12
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java79
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanBatteryPolicy.java103
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanPlusBatteryPolicy.java105
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java8
-rw-r--r--opendc-simulator/opendc-simulator-flow/src/main/java/org/opendc/simulator/engine/graph/FlowDistributor.java2
6 files changed, 306 insertions, 3 deletions
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java
index 5abbe861..a50f7e73 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java
@@ -31,12 +31,16 @@ import org.opendc.simulator.compute.power.batteries.SimBattery;
import org.opendc.simulator.engine.graph.FlowGraph;
import org.opendc.simulator.engine.graph.FlowNode;
+/**
+ * An abstract class representing a battery policy.
+ * A battery policy is used by a {@link SimBattery} to determine when to charge or discharge the battery.
+ */
public abstract class BatteryPolicy extends FlowNode implements CarbonReceiver {
protected final SimBattery battery;
protected final BatteryAggregator aggregator;
- protected double carbonIntensity;
+ protected double carbonIntensity; // The current carbon Intensity of the grid
protected BatteryState batteryState = BatteryState.IDLE;
@@ -61,6 +65,12 @@ public abstract class BatteryPolicy extends FlowNode implements CarbonReceiver {
@Override
public abstract long onUpdate(long now);
+ /**
+ * Set the battery state.
+ * Both the battery and the aggregator are updated based on the new state.
+ *
+ * @param newBatteryState The new battery state.
+ */
public void setBatteryState(BatteryState newBatteryState) {
if (newBatteryState == this.batteryState) {
return;
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java
new file mode 100644
index 00000000..3a9cb228
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2025 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute.power.batteries.policy;
+
+import org.opendc.simulator.compute.power.batteries.BatteryAggregator;
+import org.opendc.simulator.compute.power.batteries.BatteryState;
+import org.opendc.simulator.compute.power.batteries.SimBattery;
+import org.opendc.simulator.engine.graph.FlowGraph;
+
+/**
+ * A battery policy that uses two thresholds to determine if a better should be charging or discharging.
+ * - If the Carbon Intensity is below the lower threshold,
+ * the battery will start charging until full.
+ * - If the Carbon Intensity is above the upper threshold,
+ * the battery will start discharging until empty.
+ * - If the Carbon Intensity is between the two thresholds,
+ * The battery is idle.
+ */
+public class DoubleThresholdBatteryPolicy extends BatteryPolicy {
+ private final double lowerThreshold;
+ private final double upperThreshold;
+
+ /**
+ *
+ * @param parentGraph The {@link FlowGraph} this stage belongs to.
+ * @param battery The {@link SimBattery} to control.
+ * @param aggregator The {@link BatteryAggregator} to use.
+ * @param lowerThreshold The lower carbon intensity threshold to trigger charging or discharging.
+ * @param upperThreshold The upper carbon intensity threshold to trigger charging or discharging.
+ */
+ public DoubleThresholdBatteryPolicy(
+ FlowGraph parentGraph,
+ SimBattery battery,
+ BatteryAggregator aggregator,
+ double lowerThreshold,
+ double upperThreshold) {
+ super(parentGraph, battery, aggregator);
+
+ this.lowerThreshold = lowerThreshold;
+ this.upperThreshold = upperThreshold;
+ }
+
+ @Override
+ public long onUpdate(long now) {
+
+ if (this.carbonIntensity > this.upperThreshold & !this.battery.isEmpty()) {
+ this.setBatteryState(BatteryState.DISCHARGING);
+ return Long.MAX_VALUE;
+ }
+
+ if (this.carbonIntensity < this.lowerThreshold & !this.battery.isFull()) {
+ this.setBatteryState(BatteryState.CHARGING);
+ return Long.MAX_VALUE;
+ }
+
+ this.setBatteryState(BatteryState.IDLE);
+ return Long.MAX_VALUE;
+ }
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanBatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanBatteryPolicy.java
new file mode 100644
index 00000000..1c127abd
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanBatteryPolicy.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2025 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute.power.batteries.policy;
+
+import java.util.LinkedList;
+import org.opendc.simulator.compute.power.batteries.BatteryAggregator;
+import org.opendc.simulator.compute.power.batteries.BatteryState;
+import org.opendc.simulator.compute.power.batteries.SimBattery;
+import org.opendc.simulator.engine.graph.FlowGraph;
+
+/**
+ * A battery policy that uses a running mean to determine if a battery should be charging or discharging.
+ * This policy is similar to {@link SingleThresholdBatteryPolicy}, but instead of using a predifined threshold,
+ * the threshold is updated dynamically based on the running mean of the carbon intensity.
+ * - If the Carbon Intensity is below the running mean,
+ * the battery will start charging until full.
+ * - If the Carbon Intensity is above the running mean,
+ * the battery will start discharging until empty.
+ */
+public class RunningMeanBatteryPolicy extends BatteryPolicy {
+ private final int windowSize;
+
+ private final LinkedList<Double> pastCarbonIntensities = new LinkedList<>();
+ private double pastCarbonIntensitiesSum = 0.0;
+ private double pastCarbonIntensitiesMean = 0.0;
+
+ /**
+ *
+ * @param parentGraph The {@link FlowGraph} this stage belongs to.
+ * @param battery The {@link SimBattery} to control.
+ * @param aggregator The {@link BatteryAggregator} to use.
+ */
+ public RunningMeanBatteryPolicy(
+ FlowGraph parentGraph,
+ SimBattery battery,
+ BatteryAggregator aggregator,
+ double startingThreshold,
+ int windowSize) {
+ super(parentGraph, battery, aggregator);
+
+ this.windowSize = windowSize;
+
+ this.updatePastCarbonIntensities(startingThreshold);
+ }
+
+ /**
+ * Update the past carbon intensities with the new carbon intensity.
+ *
+ * Update the current sum and mean.
+ * @param newCarbonIntensity
+ */
+ private void updatePastCarbonIntensities(double newCarbonIntensity) {
+ if (this.pastCarbonIntensities.size() == this.windowSize) {
+ this.pastCarbonIntensitiesSum -= this.pastCarbonIntensities.removeFirst();
+ }
+ this.pastCarbonIntensities.addLast(newCarbonIntensity);
+ this.pastCarbonIntensitiesSum += newCarbonIntensity;
+ this.pastCarbonIntensitiesMean = this.pastCarbonIntensitiesSum / this.pastCarbonIntensities.size();
+ }
+
+ @Override
+ public void updateCarbonIntensity(double newCarbonIntensity) {
+ this.updatePastCarbonIntensities(newCarbonIntensity);
+
+ super.updateCarbonIntensity(newCarbonIntensity);
+ }
+
+ @Override
+ public long onUpdate(long now) {
+ if (this.carbonIntensity >= this.pastCarbonIntensitiesMean & !this.battery.isEmpty()) {
+ this.setBatteryState(BatteryState.DISCHARGING);
+ return Long.MAX_VALUE;
+ }
+
+ if (this.carbonIntensity < this.pastCarbonIntensitiesMean & !this.battery.isFull()) {
+ this.setBatteryState(BatteryState.CHARGING);
+ return Long.MAX_VALUE;
+ }
+
+ this.setBatteryState(BatteryState.IDLE);
+ return Long.MAX_VALUE;
+ }
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanPlusBatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanPlusBatteryPolicy.java
new file mode 100644
index 00000000..25b86dde
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/RunningMeanPlusBatteryPolicy.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2025 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.simulator.compute.power.batteries.policy;
+
+import java.util.LinkedList;
+import org.opendc.simulator.compute.power.batteries.BatteryAggregator;
+import org.opendc.simulator.compute.power.batteries.BatteryState;
+import org.opendc.simulator.compute.power.batteries.SimBattery;
+import org.opendc.simulator.engine.graph.FlowGraph;
+
+/**
+ * An improved version of {@link RunningMeanBatteryPolicy}.
+ * It uses the same logic, but only start charging if the carbon intensity is not decreasing anymore.
+ */
+public class RunningMeanPlusBatteryPolicy extends BatteryPolicy {
+ private final int windowSize;
+
+ private final LinkedList<Double> pastCarbonIntensities = new LinkedList<>();
+ private double previousCarbonIntensity = 0.0;
+
+ private double pastCarbonIntensitiesSum = 0.0;
+ private double pastCarbonIntensitiesMean = 0.0;
+
+ /**
+ *
+ * @param parentGraph The {@link FlowGraph} this stage belongs to.
+ * @param battery The {@link SimBattery} to control.
+ * @param aggregator The {@link BatteryAggregator} to use.
+ */
+ public RunningMeanPlusBatteryPolicy(
+ FlowGraph parentGraph,
+ SimBattery battery,
+ BatteryAggregator aggregator,
+ double startingThreshold,
+ int windowSize) {
+ super(parentGraph, battery, aggregator);
+
+ this.windowSize = windowSize;
+
+ this.updatePastCarbonIntensities(startingThreshold);
+ }
+
+ private void updatePastCarbonIntensities(double newCarbonIntensity) {
+ if (this.pastCarbonIntensities.size() == this.windowSize) {
+ this.pastCarbonIntensitiesSum -= this.pastCarbonIntensities.removeFirst();
+ }
+
+ if (this.pastCarbonIntensities.size() > 0) {
+ this.previousCarbonIntensity = this.pastCarbonIntensities.getLast();
+ }
+
+ this.pastCarbonIntensities.addLast(newCarbonIntensity);
+ this.pastCarbonIntensitiesSum += newCarbonIntensity;
+ this.pastCarbonIntensitiesMean = this.pastCarbonIntensitiesSum / this.pastCarbonIntensities.size();
+ }
+
+ @Override
+ public void updateCarbonIntensity(double newCarbonIntensity) {
+ this.updatePastCarbonIntensities(newCarbonIntensity);
+
+ super.updateCarbonIntensity(newCarbonIntensity);
+ }
+
+ private boolean isCharging = false;
+
+ @Override
+ public long onUpdate(long now) {
+ if (this.carbonIntensity >= this.pastCarbonIntensitiesMean & !this.battery.isEmpty()) {
+ this.isCharging = false;
+ this.setBatteryState(BatteryState.DISCHARGING);
+ return Long.MAX_VALUE;
+ }
+
+ if (this.carbonIntensity < this.pastCarbonIntensitiesMean & !this.battery.isFull()) {
+ if (this.carbonIntensity >= this.previousCarbonIntensity || this.isCharging) {
+ this.setBatteryState(BatteryState.CHARGING);
+ return Long.MAX_VALUE;
+ }
+ }
+
+ this.isCharging = false;
+ this.setBatteryState(BatteryState.IDLE);
+ return Long.MAX_VALUE;
+ }
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java
index e917a26f..26d85958 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java
@@ -27,11 +27,17 @@ import org.opendc.simulator.compute.power.batteries.BatteryState;
import org.opendc.simulator.compute.power.batteries.SimBattery;
import org.opendc.simulator.engine.graph.FlowGraph;
+/**
+ * A battery policy that uses a single threshold to determine if a better should be charging or discharging.
+ * - If the Carbon Intensity is below the give thresholds,
+ * the battery will start charging until full.
+ * - If the Carbon Intensity is above the give thresholds,
+ * the battery will start discharging until empty.
+ */
public class SingleThresholdBatteryPolicy extends BatteryPolicy {
private final double carbonThreshold;
/**
- *
* @param parentGraph The {@link FlowGraph} this stage belongs to.
* @param battery The {@link SimBattery} to control.
* @param aggregator The {@link BatteryAggregator} to use.
diff --git a/opendc-simulator/opendc-simulator-flow/src/main/java/org/opendc/simulator/engine/graph/FlowDistributor.java b/opendc-simulator/opendc-simulator-flow/src/main/java/org/opendc/simulator/engine/graph/FlowDistributor.java
index dcbd79bb..c094560e 100644
--- a/opendc-simulator/opendc-simulator-flow/src/main/java/org/opendc/simulator/engine/graph/FlowDistributor.java
+++ b/opendc-simulator/opendc-simulator-flow/src/main/java/org/opendc/simulator/engine/graph/FlowDistributor.java
@@ -208,7 +208,7 @@ public class FlowDistributor extends FlowNode implements FlowSupplier, FlowConsu
other.setConsumerIndex(other.getConsumerIndex() - 1);
}
- HashSet newUpdatedDemands = new HashSet<>();
+ HashSet<Integer> newUpdatedDemands = new HashSet<>();
for (int idx_other : this.updatedDemands) {
if (idx_other > idx) {