diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2022-08-25 15:14:57 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2022-10-21 22:13:04 +0200 |
| commit | c1f67a872e2d7ce63ac96f8ca80cbe8b25c62e3b (patch) | |
| tree | 3518a6552c0f47c4218abcd06162743d6dc000fc /opendc-simulator/opendc-simulator-power/src/main/java/org | |
| parent | 7f7b6226e6f50da698080177f6298bf8baac32b9 (diff) | |
refactor(sim/power): Re-implement power sim using flow2
This change updates the `opendc-simulator-power` module to use the new
flow simulation framework in OpenDC (named flow2 for now).
Diffstat (limited to 'opendc-simulator/opendc-simulator-power/src/main/java/org')
5 files changed, 493 insertions, 0 deletions
diff --git a/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPdu.java b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPdu.java new file mode 100644 index 00000000..8790a2d7 --- /dev/null +++ b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPdu.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2022 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.power; + +import org.jetbrains.annotations.NotNull; +import org.opendc.simulator.flow2.FlowGraph; +import org.opendc.simulator.flow2.Inlet; +import org.opendc.simulator.flow2.Outlet; +import org.opendc.simulator.flow2.mux.FlowMultiplexer; +import org.opendc.simulator.flow2.mux.MaxMinFlowMultiplexer; +import org.opendc.simulator.flow2.util.FlowTransform; +import org.opendc.simulator.flow2.util.FlowTransformer; + +/** + * A model of a Power Distribution Unit (PDU). + */ +public final class SimPdu extends SimPowerInlet { + /** + * The {@link FlowMultiplexer} that distributes the electricity over the PDU outlets. + */ + private final MaxMinFlowMultiplexer mux; + + /** + * A {@link FlowTransformer} that applies the power loss to the PDU's power inlet. + */ + private final FlowTransformer transformer; + + /** + * Construct a {@link SimPdu} instance. + * + * @param graph The underlying {@link FlowGraph} to which the PDU belongs. + * @param idlePower The idle power consumption of the PDU independent of the load on the PDU. + * @param lossCoefficient The coefficient for the power loss of the PDU proportional to the square load. + */ + public SimPdu(FlowGraph graph, float idlePower, float lossCoefficient) { + this.mux = new MaxMinFlowMultiplexer(graph); + this.transformer = new FlowTransformer(graph, new FlowTransform() { + @Override + public float apply(float value) { + // See https://download.schneider-electric.com/files?p_Doc_Ref=SPD_NRAN-66CK3D_EN + return value * (lossCoefficient * value + 1) + idlePower; + } + + @Override + public float applyInverse(float value) { + float c = lossCoefficient; + if (c != 0.f) { + return (float) (1 + Math.sqrt(4 * value * c - 4 * idlePower * c + 1)) / (2 * c); + } else { + return value - idlePower; + } + } + }); + + graph.connect(mux.newOutput(), transformer.getInput()); + } + + /** + * Construct a {@link SimPdu} instance without any loss. + * + * @param graph The underlying {@link FlowGraph} to which the PDU belongs. + */ + public SimPdu(FlowGraph graph) { + this(graph, 0.f, 0.f); + } + + /** + * Create a new PDU outlet. + */ + public PowerOutlet newOutlet() { + return new PowerOutlet(mux); + } + + @NotNull + @Override + public Outlet getFlowOutlet() { + return transformer.getOutput(); + } + + @Override + public String toString() { + return "SimPdu"; + } + + /** + * A PDU outlet. + */ + public static final class PowerOutlet extends SimPowerOutlet implements AutoCloseable { + private final FlowMultiplexer mux; + private final Inlet inlet; + private boolean isClosed; + + private PowerOutlet(FlowMultiplexer mux) { + this.mux = mux; + this.inlet = mux.newInput(); + } + + /** + * Remove the outlet from the PDU. + */ + @Override + public void close() { + isClosed = true; + mux.releaseInput(inlet); + } + + @Override + public String toString() { + return "SimPdu.Outlet"; + } + + @NotNull + @Override + protected Inlet getFlowInlet() { + if (isClosed) { + throw new IllegalStateException("Outlet is closed"); + } + return inlet; + } + } +} diff --git a/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerInlet.java b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerInlet.java new file mode 100644 index 00000000..a6e167c2 --- /dev/null +++ b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerInlet.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022 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.power; + +import org.opendc.simulator.flow2.Outlet; + +/** + * An abstract inlet that consumes electricity from a power outlet. + */ +public abstract class SimPowerInlet { + SimPowerOutlet outlet; + + /** + * Determine whether the inlet is connected to a {@link SimPowerOutlet}. + * + * @return <code>true</code> if the inlet is connected to an outlet, <code>false</code> otherwise. + */ + public boolean isConnected() { + return outlet != null; + } + + /** + * Return the {@link SimPowerOutlet} to which the inlet is connected. + */ + public SimPowerOutlet getOutlet() { + return outlet; + } + + /** + * Return the flow {@link Outlet} that models the consumption of a power inlet as flow output. + */ + protected abstract Outlet getFlowOutlet(); +} diff --git a/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerOutlet.java b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerOutlet.java new file mode 100644 index 00000000..e33d35d0 --- /dev/null +++ b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerOutlet.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022 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.power; + +import org.opendc.simulator.flow2.Inlet; +import org.opendc.simulator.flow2.Outlet; + +/** + * An abstract outlet that provides a source of electricity for datacenter components. + */ +public abstract class SimPowerOutlet { + private SimPowerInlet inlet; + + /** + * Determine whether the outlet is connected to a {@link SimPowerInlet}. + * + * @return <code>true</code> if the outlet is connected to an inlet, <code>false</code> otherwise. + */ + public boolean isConnected() { + return inlet != null; + } + + /** + * Return the {@link SimPowerInlet} to which the outlet is connected. + */ + public SimPowerInlet getInlet() { + return inlet; + } + + /** + * Connect the specified power [inlet] to this outlet. + * + * @param inlet The inlet to connect to the outlet. + */ + public void connect(SimPowerInlet inlet) { + if (isConnected()) { + throw new IllegalStateException("Outlet already connected"); + } + if (inlet.isConnected()) { + throw new IllegalStateException("Inlet already connected"); + } + + this.inlet = inlet; + this.inlet.outlet = this; + + final Inlet flowInlet = getFlowInlet(); + final Outlet flowOutlet = inlet.getFlowOutlet(); + + flowInlet.getGraph().connect(flowOutlet, flowInlet); + } + + /** + * Disconnect the connected power outlet from this inlet + */ + public void disconnect() { + SimPowerInlet inlet = this.inlet; + if (inlet != null) { + this.inlet = null; + assert inlet.outlet == this : "Inlet state incorrect"; + inlet.outlet = null; + + final Inlet flowInlet = getFlowInlet(); + flowInlet.getGraph().disconnect(flowInlet); + } + } + + /** + * Return the flow {@link Inlet} that models the consumption of a power outlet as flow input. + */ + protected abstract Inlet getFlowInlet(); +} diff --git a/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerSource.java b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerSource.java new file mode 100644 index 00000000..a2d62c48 --- /dev/null +++ b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimPowerSource.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 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.power; + +import org.opendc.simulator.flow2.FlowGraph; +import org.opendc.simulator.flow2.Inlet; +import org.opendc.simulator.flow2.sink.SimpleFlowSink; + +/** + * A {@link SimPowerOutlet} that represents a source of electricity with a maximum capacity. + */ +public final class SimPowerSource extends SimPowerOutlet { + /** + * The resource source that drives this power source. + */ + private final SimpleFlowSink sink; + + /** + * Construct a {@link SimPowerSource} instance. + * + * @param graph The underlying {@link FlowGraph} to which the power source belongs. + * @param capacity The maximum amount of power provided by the source. + */ + public SimPowerSource(FlowGraph graph, float capacity) { + this.sink = new SimpleFlowSink(graph, capacity); + } + + /** + * Return the capacity of the power source. + */ + public float getCapacity() { + return sink.getCapacity(); + } + + /** + * Return the power draw at this instant. + */ + public float getPowerDraw() { + return sink.getRate(); + } + + @Override + protected Inlet getFlowInlet() { + return sink.getInput(); + } + + @Override + public String toString() { + return "SimPowerSource"; + } +} diff --git a/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimUps.java b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimUps.java new file mode 100644 index 00000000..df7508d9 --- /dev/null +++ b/opendc-simulator/opendc-simulator-power/src/main/java/org/opendc/simulator/power/SimUps.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022 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.power; + +import org.jetbrains.annotations.NotNull; +import org.opendc.simulator.flow2.FlowGraph; +import org.opendc.simulator.flow2.Inlet; +import org.opendc.simulator.flow2.Outlet; +import org.opendc.simulator.flow2.mux.FlowMultiplexer; +import org.opendc.simulator.flow2.mux.MaxMinFlowMultiplexer; +import org.opendc.simulator.flow2.util.FlowTransform; +import org.opendc.simulator.flow2.util.FlowTransformer; + +/** + * A model of an Uninterruptible Power Supply (UPS). + * <p> + * This model aggregates multiple power sources into a single source in order to ensure that power is always available. + */ +public final class SimUps extends SimPowerOutlet { + /** + * The {@link FlowMultiplexer} that distributes the electricity over the PDU outlets. + */ + private final MaxMinFlowMultiplexer mux; + + /** + * A {@link FlowTransformer} that applies the power loss to the PDU's power inlet. + */ + private final FlowTransformer transformer; + + /** + * Construct a {@link SimUps} instance. + * + * @param graph The underlying {@link FlowGraph} to which the UPS belongs. + * @param idlePower The idle power consumption of the UPS independent of the load. + * @param lossCoefficient The coefficient for the power loss of the UPS proportional to the load. + */ + public SimUps(FlowGraph graph, float idlePower, float lossCoefficient) { + this.mux = new MaxMinFlowMultiplexer(graph); + this.transformer = new FlowTransformer(graph, new FlowTransform() { + @Override + public float apply(float value) { + // See https://download.schneider-electric.com/files?p_Doc_Ref=SPD_NRAN-66CK3D_EN + return value * (lossCoefficient + 1) + idlePower; + } + + @Override + public float applyInverse(float value) { + return (value - idlePower) / (lossCoefficient + 1); + } + }); + + graph.connect(transformer.getOutput(), mux.newInput()); + } + + /** + * Construct a {@link SimUps} instance without any loss. + * + * @param graph The underlying {@link FlowGraph} to which the UPS belongs. + */ + public SimUps(FlowGraph graph) { + this(graph, 0.f, 0.f); + } + + /** + * Create a new UPS inlet. + */ + public PowerInlet newInlet() { + return new PowerInlet(mux); + } + + @Override + protected Inlet getFlowInlet() { + return transformer.getInput(); + } + + @Override + public String toString() { + return "SimUps"; + } + + /** + * A UPS inlet. + */ + public static final class PowerInlet extends SimPowerInlet implements AutoCloseable { + private final FlowMultiplexer mux; + private final Outlet outlet; + private boolean isClosed; + + private PowerInlet(FlowMultiplexer mux) { + this.mux = mux; + this.outlet = mux.newOutput(); + } + + /** + * Remove the inlet from the PDU. + */ + @Override + public void close() { + isClosed = true; + mux.releaseOutput(outlet); + } + + @Override + public String toString() { + return "SimPdu.Inlet"; + } + + @NotNull + @Override + protected Outlet getFlowOutlet() { + if (isClosed) { + throw new IllegalStateException("Inlet is closed"); + } + return outlet; + } + } +} |
