From 20d8587552840c0379e35f70dad05c46de439122 Mon Sep 17 00:00:00 2001 From: Dante Niewenhuis Date: Mon, 10 Feb 2025 15:25:26 +0100 Subject: [PATCH] added embodied carbon (#303) --- .../provisioner/HostsProvisioningStep.kt | 2 ++ .../parquet/DfltBatteryExportColumns.kt | 5 +++ .../table/battery/BatteryTableReader.kt | 19 +++++++++--- .../table/battery/BatteryTableReaderImpl.kt | 17 +++++----- .../compute/topology/TopologyFactories.kt | 2 ++ .../compute/topology/specs/BatterySpec.kt | 2 ++ .../compute/topology/specs/TopologySpecs.kt | 12 +++---- .../compute/power/batteries/SimBattery.java | 31 ++++++++++++++++--- 8 files changed, 66 insertions(+), 24 deletions(-) diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt index fcfa1b7b3..68395fe40 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt @@ -91,6 +91,8 @@ public class HostsProvisioningStep internal constructor( cluster.battery!!.initialCharge, cluster.battery!!.name, cluster.name, + cluster.battery!!.embodiedCarbon, + cluster.battery!!.expectedLifetime, ) graph.addEdge(battery, batteryDistributor) diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt index 274eceab9..594d518c8 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt @@ -83,6 +83,11 @@ public object DfltBatteryExportColumns { field = Types.required(FLOAT).named("energy_usage"), ) { it.energyUsage } + public val EMBODIED_CARBON: ExportColumn = + ExportColumn( + field = Types.required(FLOAT).named("embodied_carbon_emission"), + ) { it.embodiedCarbonEmission } + public val CHARGE: ExportColumn = ExportColumn( field = Types.required(FLOAT).named("charge"), diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt index 6747d6761..b8410cb3b 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt @@ -50,11 +50,6 @@ public interface BatteryTableReader : Exportable { */ public val timestampAbsolute: Instant - /** - * The number of connected hosts - */ - public val hostsConnected: Int - /** * The current power draw of the host in W. */ @@ -65,9 +60,23 @@ public interface BatteryTableReader : Exportable { */ public val energyUsage: Double + /** + * The embodied carbon cost of the Battery in kg + */ + public val embodiedCarbonEmission: Double + + /** + * The current state of the battery + */ public val batteryState: BatteryState + /** + * The current charge of the battery in J + */ public val charge: Double + /** + * The capacity of the battery in J + */ public val capacity: Double } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt index 7b666c304..e69d29536 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt @@ -48,9 +48,9 @@ public class BatteryTableReaderImpl( _timestamp = table.timestamp _timestampAbsolute = table.timestampAbsolute - _hostsConnected = table.hostsConnected _powerDraw = table.powerDraw _energyUsage = table.energyUsage + _embodiedCarbonEmission = table.embodiedCarbonEmission _charge = table.charge _capacity = table.capacity _batteryState = table.batteryState @@ -72,10 +72,6 @@ public class BatteryTableReaderImpl( override val timestampAbsolute: Instant get() = _timestampAbsolute - override val hostsConnected: Int - get() = _hostsConnected - private var _hostsConnected: Int = 0 - override val powerDraw: Double get() = _powerDraw private var _powerDraw = 0.0 @@ -85,6 +81,11 @@ public class BatteryTableReaderImpl( private var _energyUsage = 0.0 private var previousEnergyUsage = 0.0 + override val embodiedCarbonEmission: Double + get() = _embodiedCarbonEmission - previousEmbodiedCarbonEmission + private var _embodiedCarbonEmission = 0.0 + private var previousEmbodiedCarbonEmission = 0.0 + override val charge: Double get() = _charge private var _charge = 0.0 @@ -104,11 +105,10 @@ public class BatteryTableReaderImpl( _timestamp = now _timestampAbsolute = now + startTime - _hostsConnected = 0 - battery.updateCounters() _powerDraw = battery.outgoingSupply _energyUsage = battery.totalEnergyUsage + _embodiedCarbonEmission = battery.embodiedCarbonEmission _charge = battery.charge _capacity = battery.capacity @@ -120,10 +120,11 @@ public class BatteryTableReaderImpl( */ override fun reset() { previousEnergyUsage = _energyUsage + previousEmbodiedCarbonEmission = _embodiedCarbonEmission - _hostsConnected = 0 _powerDraw = 0.0 _energyUsage = 0.0 + _embodiedCarbonEmission = 0.0 _charge = 0.0 _capacity = 0.0 _batteryState = BatteryState.IDLE diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt index a857f4960..b62c457cb 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt @@ -143,6 +143,8 @@ private fun ClusterJSONSpec.toClusterSpec(): ClusterSpec { this.battery.chargingSpeed, this.battery.batteryPolicy, this.battery.initialCharge, + this.battery.embodiedCarbon, + this.battery.expectedLifetime, ) } diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt index 79a23a9ed..b5fc98d56 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt @@ -28,4 +28,6 @@ public data class BatterySpec( val chargingSpeed: Double, val batteryPolicy: BatteryPolicyJSONSpec, val initialCharge: Double, + val embodiedCarbon: Double, + val expectedLifetime: Double, ) diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt index 0f7694c19..7b309bc3c 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt @@ -166,6 +166,9 @@ public data class PowerSourceJSONSpec( * @property chargingSpeed The charging speed of the battery in J * @property batteryPolicy The policy used to decide when the battery charges and discharges * @property initialCharge The initial charge in the battery + * @property embodiedCarbon The embodied carbon needed to create the battery in gram + * @property expectedLifetime The expected lifetime of the battery in years + * */ @Serializable public data class BatteryJSONSpec( @@ -174,12 +177,9 @@ public data class BatteryJSONSpec( val chargingSpeed: Double, val batteryPolicy: BatteryPolicyJSONSpec, var initialCharge: Double = 0.0, -) { - init { - this.capacity *= 3600000 - this.initialCharge *= 3600000 - } -} + var embodiedCarbon: Double = 0.0, + var expectedLifetime: Double = 0.0, +) @Serializable public data class BatteryPolicyJSONSpec( diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java index d229d4b5c..f09cbceec 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java @@ -49,6 +49,12 @@ public class SimBattery extends FlowNode implements FlowConsumer, FlowSupplier { private final String name; private final String clusterName; + private final Double embodiedCarbonRate; // The rate of carbon emissions per millisecond + private Double embodiedCarbonEmission = 0.0; + + public Double getEmbodiedCarbonEmission() { + return embodiedCarbonEmission; + } public String getName() { return name; @@ -112,9 +118,16 @@ public boolean isEmpty() { } /** - * Construct a new {@link FlowNode} instance. + * Construct a new {@link SimBattery} instance. * - * @param parentGraph The {@link FlowGraph} this stage belongs to. + * @param parentGraph The {@link FlowGraph} instance this battery is part of. + * @param capacity The capacity of the battery in kWh. + * @param chargingSpeed The charging speed of the battery in J. + * @param initialCharge The initial charge of the battery in kWh. + * @param name The name of the battery. + * @param clusterName The name of the cluster the battery is part of. + * @param totalEmbodiedCarbon The total embodied carbon used to manufacture the battery in kg. + * @param expectedLifeTime The expected lifetime of the battery in years. */ public SimBattery( FlowGraph parentGraph, @@ -122,15 +135,21 @@ public SimBattery( double chargingSpeed, double initialCharge, String name, - String clusterName) { + String clusterName, + Double totalEmbodiedCarbon, + Double expectedLifeTime) { super(parentGraph); - this.capacity = capacity; + this.capacity = capacity * 3600000; this.chargingSpeed = chargingSpeed; - this.charge = initialCharge; + this.charge = initialCharge * 3600000; this.name = name; this.clusterName = clusterName; + + // TODO: maybe change this to days instead of years? + this.embodiedCarbonRate = + (totalEmbodiedCarbon * 1000) / (expectedLifeTime * 365.0 * 24.0 * 60.0 * 60.0 * 1000.0); } public void close() { @@ -188,6 +207,8 @@ public void updateCounters(long now) { long passedTime = now - lastUpdate; + this.embodiedCarbonEmission += this.embodiedCarbonRate * passedTime; + this.updateCharge(passedTime); if (passedTime > 0) { double energyUsage = (this.outgoingSupply * passedTime * 0.001);