Skip to content

Commit df1028c

Browse files
Added Batteries (#300)
* Batteries are implemented. Small problem with the deletion when running larger workloads. Added mock files for the Battery implementation. Updated the Carbon Model to allow for multiple receivers of CarbonIntensity * Implemented batteries in OpenDC. * Spotless applied
1 parent f471d06 commit df1028c

File tree

27 files changed

+1361
-45
lines changed

27 files changed

+1361
-45
lines changed

opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public class Guest(
9696

9797
val scalingPolicy = NoDelayScaling()
9898

99+
// TODO: This is not being used at the moment
99100
val bootworkload =
100101
TraceWorkload(
101102
ArrayList(

opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ import org.opendc.compute.simulator.host.SimHost
2727
import org.opendc.compute.simulator.service.ComputeService
2828
import org.opendc.compute.topology.specs.ClusterSpec
2929
import org.opendc.compute.topology.specs.HostSpec
30+
import org.opendc.simulator.compute.power.CarbonModel
3031
import org.opendc.simulator.compute.power.SimPowerSource
32+
import org.opendc.simulator.compute.power.batteries.BatteryAggregator
33+
import org.opendc.simulator.compute.power.batteries.SimBattery
34+
import org.opendc.simulator.compute.power.batteries.policy.SingleThresholdBatteryPolicy
3135
import org.opendc.simulator.engine.engine.FlowEngine
3236
import org.opendc.simulator.engine.graph.FlowDistributor
3337

@@ -57,15 +61,50 @@ public class HostsProvisioningStep internal constructor(
5761
for (cluster in clusterSpecs) {
5862
// Create the Power Source to which hosts are connected
5963

64+
// Create Power Source
65+
val simPowerSource = SimPowerSource(graph, cluster.powerSource.totalPower.toDouble())
66+
simPowerSources.add(simPowerSource)
67+
service.addPowerSource(simPowerSource)
68+
69+
val hostDistributor = FlowDistributor(graph)
70+
6071
val carbonFragments = getCarbonFragments(cluster.powerSource.carbonTracePath)
6172

62-
val simPowerSource = SimPowerSource(graph, cluster.powerSource.totalPower.toDouble(), carbonFragments, startTime)
73+
var carbonModel: CarbonModel? = null
74+
// Create Carbon Model
75+
if (carbonFragments != null) {
76+
carbonModel = CarbonModel(graph, carbonFragments, startTime)
77+
carbonModel.addReceiver(simPowerSource)
78+
}
6379

64-
service.addPowerSource(simPowerSource)
65-
simPowerSources.add(simPowerSource)
80+
if (cluster.battery != null) {
81+
// Create Battery Distributor
82+
val batteryDistributor = FlowDistributor(graph)
83+
graph.addEdge(batteryDistributor, simPowerSource)
6684

67-
val powerDistributor = FlowDistributor(graph)
68-
graph.addEdge(powerDistributor, simPowerSource)
85+
// Create Battery
86+
val battery =
87+
SimBattery(graph, cluster.battery!!.capacity, cluster.battery!!.chargingSpeed, cluster.battery!!.initialCharge)
88+
graph.addEdge(battery, batteryDistributor)
89+
90+
// Create Aggregator
91+
val batteryAggregator = BatteryAggregator(graph, battery, batteryDistributor)
92+
93+
// Create BatteryPolicy
94+
val batteryPolicy =
95+
SingleThresholdBatteryPolicy(
96+
graph,
97+
battery,
98+
batteryAggregator,
99+
cluster.battery!!.batteryPolicy.carbonThreshold,
100+
)
101+
102+
carbonModel?.addReceiver(batteryPolicy)
103+
104+
graph.addEdge(hostDistributor, batteryAggregator)
105+
} else {
106+
graph.addEdge(hostDistributor, simPowerSource)
107+
}
69108

70109
// Create hosts, they are connected to the powerMux when SimMachine is created
71110
for (hostSpec in cluster.hostSpecs) {
@@ -78,7 +117,7 @@ public class HostsProvisioningStep internal constructor(
78117
graph,
79118
hostSpec.model,
80119
hostSpec.cpuPowerModel,
81-
powerDistributor,
120+
hostDistributor,
82121
)
83122

84123
require(simHosts.add(simHost)) { "Host with uid ${hostSpec.uid} already exists" }
@@ -92,7 +131,6 @@ public class HostsProvisioningStep internal constructor(
92131
}
93132

94133
for (simPowerSource in simPowerSources) {
95-
// TODO: add close function
96134
simPowerSource.close()
97135
}
98136
}

opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
package org.opendc.compute.topology
2626

27+
import org.opendc.compute.topology.specs.BatterySpec
2728
import org.opendc.compute.topology.specs.ClusterJSONSpec
2829
import org.opendc.compute.topology.specs.ClusterSpec
2930
import org.opendc.compute.topology.specs.HostJSONSpec
@@ -109,8 +110,21 @@ private fun ClusterJSONSpec.toClusterSpec(random: RandomGenerator): ClusterSpec
109110
totalPower = this.powerSource.totalPower,
110111
carbonTracePath = this.powerSource.carbonTracePath,
111112
)
113+
114+
var batterySpec: BatterySpec? = null
115+
if (this.battery != null) {
116+
batterySpec =
117+
BatterySpec(
118+
UUID(random.nextLong(), clusterId.toLong()),
119+
this.battery.capacity,
120+
this.battery.chargingSpeed,
121+
this.battery.batteryPolicy,
122+
this.battery.initialCharge,
123+
)
124+
}
125+
112126
clusterId++
113-
return ClusterSpec(this.name, hostSpecs, powerSourceSpec)
127+
return ClusterSpec(this.name, hostSpecs, powerSourceSpec, batterySpec)
114128
}
115129

116130
/**
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2025 AtLarge Research
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
package org.opendc.compute.topology.specs
24+
25+
import java.util.UUID
26+
27+
public data class BatterySpec(
28+
val uid: UUID,
29+
val capacity: Double,
30+
val chargingSpeed: Double,
31+
val batteryPolicy: BatteryPolicyJSONSpec,
32+
val initialCharge: Double,
33+
)

opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/ClusterSpec.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ public data class ClusterSpec(
2626
val name: String,
2727
val hostSpecs: List<HostSpec>,
2828
val powerSource: PowerSourceSpec,
29+
val battery: BatterySpec? = null,
2930
)

opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public data class ClusterJSONSpec(
5151
val count: Int = 1,
5252
val hosts: List<HostJSONSpec>,
5353
val powerSource: PowerSourceJSONSpec = PowerSourceJSONSpec.DFLT,
54+
val battery: BatteryJSONSpec? = null,
5455
val location: String = "NL",
5556
)
5657

@@ -155,3 +156,29 @@ public data class PowerSourceJSONSpec(
155156
)
156157
}
157158
}
159+
160+
/**
161+
* Definition of a power source used for JSON input.
162+
*
163+
* @property vendor
164+
* @property modelName
165+
* @property arch
166+
* @property totalPower
167+
*/
168+
@Serializable
169+
public data class BatteryJSONSpec(
170+
var capacity: Double,
171+
val chargingSpeed: Double,
172+
val batteryPolicy: BatteryPolicyJSONSpec,
173+
var initialCharge: Double = 0.0,
174+
) {
175+
init {
176+
this.capacity *= 3600000
177+
this.initialCharge *= 3600000
178+
}
179+
}
180+
181+
@Serializable
182+
public data class BatteryPolicyJSONSpec(
183+
val carbonThreshold: Double,
184+
)

0 commit comments

Comments
 (0)