From 07071baa884dfd5825a8183e8c6d009d7544cec2 Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Wed, 12 Jan 2022 10:48:24 +0100 Subject: [PATCH 001/123] Add config possibility for transformer control groups --- CHANGELOG.md | 5 +- build.gradle | 2 +- .../vn_146_lv_small/vn_146_lv_small.conf | 4 +- input/samples/vn_simona/vn_simona.conf | 22 ++- ...plate.conf => simona-config-template.conf} | 17 +++ .../ie3/simona/config/ConfigFailFast.scala | 63 +++++++-- .../ie3/simona/config/RefSystemParser.scala | 4 +- .../edu/ie3/simona/config/SimonaConfig.scala | 111 ++++++++++++++- .../control/TransformerControlGroup.scala | 75 ++++++++++ .../model/participant/SystemParticipant.scala | 6 +- .../simona/config/ConfigFailFastSpec.scala | 111 ++++++++++----- .../simona/config/RefSystemParserSpec.scala | 48 +++++-- .../control/TransformerControlGroupSpec.scala | 132 ++++++++++++++++++ 13 files changed, 524 insertions(+), 76 deletions(-) rename src/main/resources/config/{config-template.conf => simona-config-template.conf} (94%) create mode 100644 src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala create mode 100644 src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala diff --git a/CHANGELOG.md b/CHANGELOG.md index c47d5ac600..06328de446 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Config possibility for transformer control groups + ### Changed - Improving code readability in EvcsAgent by moving FreeLotsRequest to separate methods -[Unreleased]: https://github.com/ie3-institute/simona +[Unreleased]: https://github.com/ie3-institute/simona/compare/a14a093239f58fca9b2b974712686b33e5e5f939...HEAD diff --git a/build.gradle b/build.gradle index 846faff953..d3fa53145d 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ ext { scalaVersion = '2.13' scalaBinaryVersion = '2.13.7' akkaVersion = '2.6.18' - tscfgVersion = '0.9.996' + tscfgVersion = '0.9.995' scriptsLocation = 'gradle' + File.separator + 'scripts' + File.separator // location of script plugins } diff --git a/input/samples/vn_146_lv_small/vn_146_lv_small.conf b/input/samples/vn_146_lv_small/vn_146_lv_small.conf index 9d86cffc3b..b12b6c5776 100644 --- a/input/samples/vn_146_lv_small/vn_146_lv_small.conf +++ b/input/samples/vn_146_lv_small/vn_146_lv_small.conf @@ -93,8 +93,8 @@ simona.event.listener = [] simona.gridConfig.refSystems = [ - {sNom="100 kVA", vNom="0.4 kV", voltLvls = ["{NS, 0.4 kV}"]}, - {sNom="500 MVA", vNom="20 kV", voltLvls = ["{MS, 20 kV}"]} + {sNom="100 kVA", vNom="0.4 kV", voltLvls = [{id = "NS", vNom = "0.4 kV"}]}, + {sNom="500 MVA", vNom="20 kV", voltLvls = [{id = "MS", vNom = "20 kV"}]} ] ################################################################## diff --git a/input/samples/vn_simona/vn_simona.conf b/input/samples/vn_simona/vn_simona.conf index f259b25306..3ac3f20448 100644 --- a/input/samples/vn_simona/vn_simona.conf +++ b/input/samples/vn_simona/vn_simona.conf @@ -144,10 +144,10 @@ simona.event.listener = [] ################################################################## simona.gridConfig.refSystems = [ - {sNom = "100 kVA", vNom = "0.4 kV", voltLvls = ["{NS, 0.4 kV}"]}, - {sNom = "60 MVA", vNom = "20 kV", voltLvls = ["{MS, 20 kV}"]}, - {sNom = "600 MVA", vNom = "110 kV", voltLvls = ["{HS, 110 kV}"]}, - {sNom = "1000 MVA", vNom = "380 kV", voltLvls = ["{HoeS, 380 kV}"]} + {sNom = "100 kVA", vNom = "0.4 kV", voltLvls = [{id = "NS", vNom = "0.4 kV"}]}, + {sNom = "60 MVA", vNom = "20 kV", voltLvls = [{id = "MS", vNom = "20 kV"}]}, + {sNom = "600 MVA", vNom = "110 kV", voltLvls = [{id = "HS", vNom = "110 kV"}]}, + {sNom = "1000 MVA", vNom = "380 kV", voltLvls = [{id = "HoeS", vNom = "380 kV"}]} ] ################################################################## @@ -157,3 +157,17 @@ simona.powerflow.maxSweepPowerDeviation = 1E-5 // the maximum allowed deviation simona.powerflow.newtonraphson.epsilon = [1E-12] simona.powerflow.newtonraphson.iterations = 50 simona.powerflow.resolution = "3600s" + +simona.control.transformer = [ + { + transformers = ["31a2b9bf-e785-4475-aa44-1c34646e8c79"], + measurements = ["923f2d69-3093-4198-86e4-13d2d1c220f8"], + vMin = 0.98, + vMax = 1.02 + }, { + transformers = ["1132dbf4-e8a1-44ae-8415-f42d4497aa1d"], + measurements = ["7686b818-a0ba-465c-8e4e-f7d3c4e171fc"], + vMin = 0.98, + vMax = 1.02 + } +] diff --git a/src/main/resources/config/config-template.conf b/src/main/resources/config/simona-config-template.conf similarity index 94% rename from src/main/resources/config/config-template.conf rename to src/main/resources/config/simona-config-template.conf index 8e6952e8f0..19c349a525 100644 --- a/src/main/resources/config/config-template.conf +++ b/src/main/resources/config/simona-config-template.conf @@ -69,6 +69,15 @@ GridOutputConfig { transformers3w: boolean | false } +#@define +TransformerControlGroup { + transformers: [string] + measurements: [string] + # TODO: Currently, only limit prevention is configurable. Should be an interface, when it is allowed by tscfg + vMin: Double + vMax: Double +} + ################################################################## # Agentsim ################################################################## @@ -263,3 +272,11 @@ simona.event.listener = [ eventsToProcess = [string] } ] + +################################################################## +# Configuration of Control Schemes +################################################################## +#@optional +simona.control = { + transformer = [TransformerControlGroup] +} diff --git a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala index ddc7c37704..61b6c10eed 100644 --- a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala +++ b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala @@ -9,7 +9,12 @@ package edu.ie3.simona.config import com.typesafe.config.{Config, ConfigException} import com.typesafe.scalalogging.LazyLogging import edu.ie3.simona.config.SimonaConfig.Simona.Output.Sink.InfluxDb1x -import edu.ie3.simona.config.SimonaConfig.{BaseOutputConfig, RefSystemConfig} +import edu.ie3.simona.config.SimonaConfig.{ + BaseOutputConfig, + RefSystemConfig, + Simona, + TransformerControlGroup +} import edu.ie3.simona.exceptions.InvalidConfigParameterException import edu.ie3.simona.io.result.ResultSinkType import edu.ie3.simona.model.participant.load.{LoadModelBehaviour, LoadReference} @@ -128,6 +133,9 @@ case object ConfigFailFast extends LazyLogging { /* Check power flow resolution configuration */ checkPowerFlowResolutionConfiguration(simonaConfig.simona.powerflow) + + /* Check control scheme definitions */ + simonaConfig.simona.control.foreach(checkControlSchemes) } /** Checks for valid sink configuration @@ -395,15 +403,6 @@ case object ConfigFailFast extends LazyLogging { s"Provided refSystem is: $refSystem." ) - voltLvls.foreach { voltLvl => - { - if (!ConfigConventions.voltLvlRegex.matches(voltLvl)) - throw new InvalidConfigParameterException( - s"The definition string for voltLvl '$voltLvl' does not comply with the definition {, }!" - ) - } - } - gridIds.foreach { case gridIdRange @ ConfigConventions.gridIdDotRange(from, to) => rangeCheck(from.toInt, to.toInt, gridIdRange) @@ -537,6 +536,50 @@ case object ConfigFailFast extends LazyLogging { } } + /** Check the validity of control scheme definitions + * + * @param control + * Control scheme definitions + */ + private def checkControlSchemes(control: Simona.Control): Unit = { + control.transformer.foreach(checkTransformerControl) + } + + /** Check the suitability of transformer control group definition. + * + * One important check cannot be performed at this place, as input data is + * not available, yet: Do the measurements belong to a region, that can be + * influenced by the transformer? + * + * @param transformerControlGroup + * Transformer control group definition + */ + private def checkTransformerControl( + transformerControlGroup: TransformerControlGroup + ): Unit = transformerControlGroup match { + case TransformerControlGroup(measurements, transformers, vMax, vMin) => + if (measurements.isEmpty) + throw new InvalidConfigParameterException( + "A transformer control group cannot have no measurements assigned." + ) + if (transformers.isEmpty) + throw new InvalidConfigParameterException( + "A transformer control group cannot have no transformers assigned." + ) + if (vMin < 0) + throw new InvalidConfigParameterException( + "The minimum permissible voltage magnitude of a transformer control group has to be positive." + ) + if (vMax < 0) + throw new InvalidConfigParameterException( + "The maximum permissible voltage magnitude of a transformer control group has to be positive." + ) + if (vMax < vMin) + throw new InvalidConfigParameterException( + "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." + ) + } + /** Check the default config * * @param config diff --git a/src/main/scala/edu/ie3/simona/config/RefSystemParser.scala b/src/main/scala/edu/ie3/simona/config/RefSystemParser.scala index 9bf9f5e1b2..2b8a8477b0 100644 --- a/src/main/scala/edu/ie3/simona/config/RefSystemParser.scala +++ b/src/main/scala/edu/ie3/simona/config/RefSystemParser.scala @@ -108,11 +108,11 @@ object RefSystemParser { voltLvls.foldLeft(Vector.empty[(VoltageLevel, RefSystem)])( (voltLvlRefSystems, voltLvlDef) => { val voltLvl = voltLvlDef match { - case ConfigConventions.voltLvlRegex(id, vNom) => + case SimonaConfig.VoltLvlConfig(id, vNom) => VoltLvlParser.parse(id, vNom) case invalid => throw new InvalidConfigParameterException( - s"Got invalid voltage level string $invalid. Has to look like this: {MV, 10 kV}" + s"Got invalid voltage level definition $invalid. Double-check your entry!" ) } voltLvlRefSystems :+ (voltLvl, refSystem) diff --git a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala index 6283055bbc..f6774a0c81 100644 --- a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala +++ b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala @@ -1,5 +1,5 @@ /* - * © 2021. TU Dortmund University, + * © 2022. TU Dortmund University, * Institute of Energy Systems, Energy Efficiency and Energy Economics, * Research group Distribution grid planning and operation */ @@ -377,7 +377,7 @@ object SimonaConfig { gridIds: scala.Option[scala.List[java.lang.String]], sNom: java.lang.String, vNom: java.lang.String, - voltLvls: scala.Option[scala.List[java.lang.String]] + voltLvls: scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] ) object RefSystemConfig { def apply( @@ -397,11 +397,31 @@ object SimonaConfig { voltLvls = if (c.hasPathOrNull("voltLvls")) scala.Some( - $_L$_str(c.getList("voltLvls"), parentPath, $tsCfgValidator) + $_LSimonaConfig_VoltLvlConfig( + c.getList("voltLvls"), + parentPath, + $tsCfgValidator + ) ) else None ) } + private def $_LSimonaConfig_VoltLvlConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.VoltLvlConfig] = { + import scala.jdk.CollectionConverters._ + cl.asScala + .map(cv => + SimonaConfig.VoltLvlConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList + } private def $_reqStr( parentPath: java.lang.String, c: com.typesafe.config.Config, @@ -420,6 +440,45 @@ object SimonaConfig { } + final case class TransformerControlGroup( + measurements: scala.List[java.lang.String], + transformers: scala.List[java.lang.String], + vMax: scala.Double, + vMin: scala.Double + ) + object TransformerControlGroup { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.TransformerControlGroup = { + SimonaConfig.TransformerControlGroup( + measurements = + $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), + transformers = + $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), + vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), + vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) + ) + } + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { + if (c == null) 0 + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } + } + + } + final case class VoltLvlConfig( id: java.lang.String, vNom: java.lang.String @@ -514,6 +573,7 @@ object SimonaConfig { } final case class Simona( + control: scala.Option[SimonaConfig.Simona.Control], event: SimonaConfig.Simona.Event, gridConfig: SimonaConfig.Simona.GridConfig, input: SimonaConfig.Simona.Input, @@ -524,6 +584,41 @@ object SimonaConfig { time: SimonaConfig.Simona.Time ) object Simona { + final case class Control( + transformer: scala.List[SimonaConfig.TransformerControlGroup] + ) + object Control { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Control = { + SimonaConfig.Simona.Control( + transformer = $_LSimonaConfig_TransformerControlGroup( + c.getList("transformer"), + parentPath, + $tsCfgValidator + ) + ) + } + private def $_LSimonaConfig_TransformerControlGroup( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.TransformerControlGroup] = { + import scala.jdk.CollectionConverters._ + cl.asScala + .map(cv => + SimonaConfig.TransformerControlGroup( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList + } + } + final case class Event( listener: scala.Option[ scala.List[SimonaConfig.Simona.Event.Listener$Elm] @@ -2133,6 +2228,16 @@ object SimonaConfig { $tsCfgValidator: $TsCfgValidator ): SimonaConfig.Simona = { SimonaConfig.Simona( + control = + if (c.hasPathOrNull("control")) + scala.Some( + SimonaConfig.Simona.Control( + c.getConfig("control"), + parentPath + "control.", + $tsCfgValidator + ) + ) + else None, event = SimonaConfig.Simona.Event( if (c.hasPathOrNull("event")) c.getConfig("event") else com.typesafe.config.ConfigFactory.parseString("event{}"), diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala new file mode 100644 index 0000000000..652b40b4e1 --- /dev/null +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala @@ -0,0 +1,75 @@ +/* + * © 2021. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.model.control + +import breeze.math.Complex +import edu.ie3.powerflow.model.NodeData.StateData +import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult +import edu.ie3.simona.model.control.TransformerControlGroup.RegulationCriterion +import tech.units.indriya.ComparableQuantity + +import java.util.UUID +import javax.measure.quantity.Dimensionless + +/** Business logic for a transformer control group. It's main purpose is to + * determine, if there is any regulation need and if yes, in what circumference + * (here: voltage raise or reduction to achieve) + * + * @param nodalRegulationCriterion + * Mapping from nodal index to a partial function, that determines the + * regulation need at this node + * @param harmonizeRegulationNeeds + * Partial function to harmonize different, possible contradictory regulation + * needs + */ +final case class TransformerControlGroup( + nodalRegulationCriterion: Map[UUID, RegulationCriterion], + harmonizeRegulationNeeds: Array[ + ComparableQuantity[Dimensionless] + ] => Option[ComparableQuantity[Dimensionless]] +) { + + /** Based on the given successful power flow result, determine the difference + * in voltage magnitude, that needs to be achieved by regulating the + * transformer tap position + * + * @param result + * Power flow result to account for + * @param uuidToIndex + * Mapping from node's uuid to nodal index + * @return + * Optional voltage magnitude, that a transformer tap regulation needs to + * achieve + */ + def determineRegulationNeed( + result: SuccessFullPowerFlowResult, + uuidToIndex: Map[UUID, Int] + ): Option[ComparableQuantity[Dimensionless]] = { + val regulationNeeds = result.nodeData.flatMap { + case StateData(resultNodeIndex, _, voltage, _) => + /* Find possible matching criterion and evaluate it */ + nodalRegulationCriterion + .find { case (uuid, _) => + val index = uuidToIndex(uuid) + index == resultNodeIndex + } + .map { case (_, criterion) => + criterion(voltage) + } + }.flatten + Option + .when(regulationNeeds.nonEmpty)( + harmonizeRegulationNeeds(regulationNeeds) + ) + .flatten + } +} + +object TransformerControlGroup { + type RegulationCriterion = + Complex => Option[ComparableQuantity[Dimensionless]] +} diff --git a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala index 3331b2280d..8eb4e6b966 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala @@ -105,11 +105,7 @@ abstract class SystemParticipant[CD <: CalcRelevantData]( def activeToReactivePowerFunc( nodalVoltage: ComparableQuantity[Dimensionless] ): ComparableQuantity[Power] => ComparableQuantity[Power] = - qControl.activeToReactivePowerFunc( - sRated.multiply(scalingFactor), - cosPhiRated, - nodalVoltage - ) + qControl.activeToReactivePowerFunc(sRated, cosPhiRated, nodalVoltage) /** Calculate the reactive power of the model * diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index decc6d59cd..fd2bcc8026 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -15,6 +15,7 @@ import edu.ie3.simona.config.SimonaConfig.Simona.Output.Sink import edu.ie3.simona.config.SimonaConfig.Simona.Output.Sink.{Csv, InfluxDb1x} import edu.ie3.simona.config.SimonaConfig.Simona.Powerflow.Newtonraphson import edu.ie3.simona.config.SimonaConfig.Simona.{Powerflow, Time} +import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.InvalidConfigParameterException import edu.ie3.simona.test.common.{ConfigTestData, UnitSpec} import edu.ie3.simona.util.ConfigUtil.{CsvConfigUtil, NotifierIdentifier} @@ -69,8 +70,8 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { List(10, 30), 100 ), - Duration.of(3600, ChronoUnit.SECONDS), - Duration.of(3600, ChronoUnit.SECONDS) + resolution = Duration.of(3600, ChronoUnit.SECONDS), + sweepTimeout = Duration.of(3600, ChronoUnit.SECONDS) ) ) } @@ -112,31 +113,6 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { } - "throw an InvalidConfigParametersException when the voltLevel is malformed (e.g. a number)" in { - val refSystemConfigAllEmpty = - ConfigFactory.parseString("""simona.gridConfig.refSystems = [ - | { - | sNom="100 MVA", - | vNom="0.4 kV", - | voltLvls = ["1"] - | } - |]""".stripMargin) - val faultyConfig = - refSystemConfigAllEmpty.withFallback(typesafeConfig).resolve() - val faultySimonaConfig = SimonaConfig(faultyConfig) - - // get the private method for validation - val checkRefSystem = - PrivateMethod[Unit](Symbol("checkRefSystem")) - - intercept[InvalidConfigParameterException] { - faultySimonaConfig.simona.gridConfig.refSystems.foreach(refSystem => - ConfigFailFast invokePrivate checkRefSystem(refSystem) - ) - }.getMessage shouldBe "The definition string for voltLvl '1' does not comply with the definition {, }!" - - } - "throw an InvalidConfigParametersException when the gridId is malformed" in { val malformedGridIds = List("10--100", "MS", "10..100") @@ -176,7 +152,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { | { | sNom="100", | vNom="0.4 kV", - | voltLvls = ["{MS, 10 kV}","{HS, 110 kV}"] + | voltLvls = [{id = "MS", vNom = "10 kV"},{id = "HS", vNom = "110 kV"}] | } |]""".stripMargin ) @@ -192,7 +168,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { faultySimonaConfig.simona.gridConfig.refSystems.foreach(refSystem => ConfigFailFast invokePrivate checkRefSystem(refSystem) ) - }.getMessage shouldBe "Invalid value for sNom from provided refSystem RefSystemConfig(None,100,0.4 kV,Some(List({MS, 10 kV}, {HS, 110 kV}))). Is a valid unit provided?" + }.getMessage shouldBe "Invalid value for sNom from provided refSystem RefSystemConfig(None,100,0.4 kV,Some(List(VoltLvlConfig(MS,10 kV), VoltLvlConfig(HS,110 kV)))). Is a valid unit provided?" } @@ -204,7 +180,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { | { | sNom="100 MVA", | vNom="0.4", - | voltLvls = ["{MS, 10 kV}","{HS, 110 kV}"] + | voltLvls = [{id = "MS", vNom = "10 kV"},{id = "HS", vNom = "110 kV"}] | } |]""".stripMargin ) @@ -220,7 +196,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { faultySimonaConfig.simona.gridConfig.refSystems.foreach(refSystem => ConfigFailFast invokePrivate checkRefSystem(refSystem) ) - }.getMessage shouldBe "Invalid value for vNom from provided refSystem RefSystemConfig(None,100 MVA,0.4,Some(List({MS, 10 kV}, {HS, 110 kV}))). Is a valid unit provided?" + }.getMessage shouldBe "Invalid value for vNom from provided refSystem RefSystemConfig(None,100 MVA,0.4,Some(List(VoltLvlConfig(MS,10 kV), VoltLvlConfig(HS,110 kV)))). Is a valid unit provided?" } @@ -231,13 +207,13 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { | { | sNom="100 MVA", | vNom="0.4 kV", - | voltLvls = ["{MS, 10 kV}","{HS, 110 kV}"] + | voltLvls = [{id = "MS", vNom = "10 kV"},{id = "HS", vNom = "110 kV"}] | gridIds = ["1","1-10","10...100"] | }, | { | sNom="1000 MVA", | vNom="10kV", - | voltLvls = ["{HS, 110 kV}","{HoeS, 380 kV}"] + | voltLvls = [{id = "HS", vNom = "110 kV"},{id = "HoeS", vNom = "380 kV"}] | gridIds = ["1-3","3...6","10...100"] | } |]""".stripMargin @@ -877,7 +853,76 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { ) }.getMessage shouldBe "The weather data scheme 'this won't work' is not supported. Supported schemes:\n\ticon\n\tpsdm" } + } + + "checking the transformer control groups" should { + val checkTransformerControl = + PrivateMethod[Unit](Symbol("checkTransformerControl")) + "throw an exception, if the measurements are empty" in { + val dut = TransformerControlGroup( + List.empty[String], + List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), + 1.02, + 0.98 + ) + + intercept[InvalidConfigParameterException] { + ConfigFailFast invokePrivate checkTransformerControl(dut) + }.getMessage shouldBe "A transformer control group cannot have no measurements assigned." + } + + "throw an exception, if the transformers are empty" in { + val dut = TransformerControlGroup( + List("6888c53a-7629-4563-ac8e-840f80b03106"), + List.empty[String], + 1.02, + 0.98 + ) + + intercept[InvalidConfigParameterException] { + ConfigFailFast invokePrivate checkTransformerControl(dut) + }.getMessage shouldBe "A transformer control group cannot have no transformers assigned." + } + + "throw an exception, if vMax is smaller than vMin" in { + val dut = TransformerControlGroup( + List("6888c53a-7629-4563-ac8e-840f80b03106"), + List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), + 0.98, + 1.02 + ) + + intercept[InvalidConfigParameterException] { + ConfigFailFast invokePrivate checkTransformerControl(dut) + }.getMessage shouldBe "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." + } + + "throw an exception, if vMin is negative" in { + val dut = TransformerControlGroup( + List("6888c53a-7629-4563-ac8e-840f80b03106"), + List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), + 1.02, + -0.98 + ) + + intercept[InvalidConfigParameterException] { + ConfigFailFast invokePrivate checkTransformerControl(dut) + }.getMessage shouldBe "The minimum permissible voltage magnitude of a transformer control group has to be positive." + } + + "throw an exception, if vMax is negative" in { + val dut = TransformerControlGroup( + List("6888c53a-7629-4563-ac8e-840f80b03106"), + List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), + -1.02, + 0.98 + ) + + intercept[InvalidConfigParameterException] { + ConfigFailFast invokePrivate checkTransformerControl(dut) + }.getMessage shouldBe "The maximum permissible voltage magnitude of a transformer control group has to be positive." + } } } diff --git a/src/test/scala/edu/ie3/simona/config/RefSystemParserSpec.scala b/src/test/scala/edu/ie3/simona/config/RefSystemParserSpec.scala index a757cc2e1c..be5d9b95c4 100644 --- a/src/test/scala/edu/ie3/simona/config/RefSystemParserSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/RefSystemParserSpec.scala @@ -6,11 +6,8 @@ package edu.ie3.simona.config -import edu.ie3.datamodel.models.voltagelevels.{ - CommonVoltageLevel, - GermanVoltageLevelUtils -} -import edu.ie3.simona.config.SimonaConfig.RefSystemConfig +import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils +import edu.ie3.simona.config.SimonaConfig.{RefSystemConfig, VoltLvlConfig} import edu.ie3.simona.exceptions.InvalidConfigParameterException import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.test.common.UnitSpec @@ -25,13 +22,20 @@ class RefSystemParserSpec extends UnitSpec { gridIds = Some(List("1", "2-10", "15...20")), sNom = "100 MVA", vNom = "10 kV", - voltLvls = Some(List("{MS, 10 kV}", "{MS, 20 kV}")) + voltLvls = Some( + List(VoltLvlConfig("MS", "10 kV"), VoltLvlConfig("MS", "20 kV")) + ) ), new RefSystemConfig( gridIds = Some(List("100")), sNom = "5000 MVA", vNom = "110 kV", - voltLvls = Some(List("{HS, 110 kV}", "{HoeS, 380 kV}")) + voltLvls = Some( + List( + VoltLvlConfig("HS", "110 kV"), + VoltLvlConfig("HoeS", "380 kV") + ) + ) ), new RefSystemConfig( gridIds = None, @@ -90,7 +94,9 @@ class RefSystemParserSpec extends UnitSpec { gridIds = Some(List("1", "2", "2-10", "15...20")), sNom = "100 MVA", vNom = "10 kV", - voltLvls = Some(List("{MS, 10 kV}", "{MS, 20 kV}")) + voltLvls = Some( + List(VoltLvlConfig("MS", "10 kV"), VoltLvlConfig("MS", "20 kV")) + ) ) ) intercept[InvalidConfigParameterException] { @@ -107,13 +113,17 @@ class RefSystemParserSpec extends UnitSpec { gridIds = None, sNom = "100 MVA", vNom = "10 kV", - voltLvls = Some(List("{MS, 10 kV}", "{MS, 20 kV}")) + voltLvls = Some( + List(VoltLvlConfig("MS", "10 kV"), VoltLvlConfig("MS", "20 kV")) + ) ), new RefSystemConfig( gridIds = None, sNom = "100 MVA", vNom = "10 kV", - voltLvls = Some(List("{MS, 10 kV}", "{MS, 20 kV}")) + voltLvls = Some( + List(VoltLvlConfig("MS", "10 kV"), VoltLvlConfig("MS", "20 kV")) + ) ) ) intercept[InvalidConfigParameterException] { @@ -130,18 +140,22 @@ class RefSystemParserSpec extends UnitSpec { gridIds = Some(List("asd")), sNom = "100 MVA", vNom = "10 kV", - voltLvls = Some(List("{MS, 10 kV}", "{MS, 20 kV}")) + voltLvls = Some( + List(VoltLvlConfig("MS", "10 kV"), VoltLvlConfig("MS", "20 kV")) + ) ), new RefSystemConfig( gridIds = None, sNom = "100 MVA", vNom = "10 kV", - voltLvls = Some(List("{MS, 10 kV}", "{MS, 20 kV}")) + voltLvls = Some( + List(VoltLvlConfig("MS", "10 kV"), VoltLvlConfig("MS", "20 kV")) + ) ) ) intercept[InvalidConfigParameterException] { RefSystemParser.parse(validRefSystems) - }.getMessage shouldBe "Unknown gridId format asd provided for refSystem RefSystemConfig(Some(List(asd)),100 MVA,10 kV,Some(List({MS, 10 kV}, {MS, 20 kV})))" + }.getMessage shouldBe "Unknown gridId format asd provided for refSystem RefSystemConfig(Some(List(asd)),100 MVA,10 kV,Some(List(VoltLvlConfig(MS,10 kV), VoltLvlConfig(MS,20 kV))))" } @@ -155,13 +169,17 @@ class RefSystemParserSpec extends UnitSpec { gridIds = Some(List("1", "2-10", "15...20")), sNom = "100 MVA", vNom = "10 kV", - voltLvls = Some(List("{MS, 10 kV}", "{MS, 20 kV}")) + voltLvls = Some( + List(VoltLvlConfig("MS", "10 kV"), VoltLvlConfig("MS", "20 kV")) + ) ), new RefSystemConfig( gridIds = Some(List("100")), sNom = "5000 MVA", vNom = "110 kV", - voltLvls = Some(List("{HS, 110 kV}", "{HoeS, 380 kV}")) + voltLvls = Some( + List(VoltLvlConfig("HS", "110 kV"), VoltLvlConfig("HoeS", "380 kV")) + ) ) ) diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala new file mode 100644 index 0000000000..8def596ce6 --- /dev/null +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala @@ -0,0 +1,132 @@ +/* + * © 2021. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.model.control + +import breeze.linalg.DenseMatrix +import breeze.math.Complex +import edu.ie3.powerflow.model.NodeData.StateData +import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult +import edu.ie3.powerflow.model.enums.NodeType +import edu.ie3.simona.model.grid.GridModel +import edu.ie3.simona.test.common.UnitSpec +import edu.ie3.simona.test.matchers.QuantityMatchers +import edu.ie3.util.quantities.PowerSystemUnits +import tech.units.indriya.quantity.Quantities + +import java.util.UUID + +class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { + "Checking the function of transformer control groups" should { + val buildTransformerControlModels = PrivateMethod[TransformerControlGroup]( + Symbol("buildTransformerControlModels") + ) + + val dut = GridModel invokePrivate buildTransformerControlModels( + Set( + UUID.fromString( + "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" + ), + UUID.fromString( + "08b8d2ca-993d-45cd-9456-f009ecb47bc0" + ), + UUID.fromString( + "324f49e5-1c35-4c49-afb1-3cf41696bf93" + ) + ), + 1.1, + 0.9 + ) + + val uuidToIndex = Map( + UUID.fromString( + "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" + ) -> 0, + UUID.fromString( + "08b8d2ca-993d-45cd-9456-f009ecb47bc0" + ) -> 1, + UUID.fromString( + "324f49e5-1c35-4c49-afb1-3cf41696bf93" + ) -> 2 + ) + + "return no regulation need, if everything is fine" in { + val result = ValidNewtonRaphsonPFResult( + 0, + Array( + StateData(0, NodeType.SL, Complex.one, Complex.zero), + StateData(1, NodeType.PQ, Complex.one, Complex.zero), + StateData(2, NodeType.PQ, Complex.one, Complex.zero) + ), + DenseMatrix.zeros(1, 1) + ) + + val actual = dut.determineRegulationNeed(result, uuidToIndex) + + actual shouldBe None + } + + "return no regulation need, if requests are contradictory" in { + val result = ValidNewtonRaphsonPFResult( + 0, + Array( + StateData(0, NodeType.SL, Complex.one, Complex.zero), + StateData(1, NodeType.PQ, Complex.one * 0.88, Complex.zero), + StateData(2, NodeType.PQ, Complex.one * 1.11, Complex.zero) + ), + DenseMatrix.zeros(1, 1) + ) + + val actual = dut.determineRegulationNeed(result, uuidToIndex) + + actual shouldBe None + } + + "return the biggest positive regulation need" in { + val result = ValidNewtonRaphsonPFResult( + 0, + Array( + StateData(0, NodeType.SL, Complex.one, Complex.zero), + StateData(1, NodeType.PQ, Complex.one * 0.85, Complex.zero), + StateData(2, NodeType.PQ, Complex.one * 0.88, Complex.zero) + ), + DenseMatrix.zeros(1, 1) + ) + + val actual = dut.determineRegulationNeed(result, uuidToIndex) + + actual match { + case Some(regulationNeed) => + regulationNeed should equalWithTolerance( + Quantities.getQuantity(0.05, PowerSystemUnits.PU) + ) + case None => fail("Did expect to receive a regulation need.") + } + } + + "return the biggest negative regulation need" in { + val result = ValidNewtonRaphsonPFResult( + 0, + Array( + StateData(0, NodeType.SL, Complex.one, Complex.zero), + StateData(1, NodeType.PQ, Complex.one * 1.15, Complex.zero), + StateData(2, NodeType.PQ, Complex.one * 1.11, Complex.zero) + ), + DenseMatrix.zeros(1, 1) + ) + + val actual = dut.determineRegulationNeed(result, uuidToIndex) + + actual match { + case Some(regulationNeed) => + regulationNeed should equalWithTolerance( + Quantities.getQuantity(-0.05, PowerSystemUnits.PU) + ) + case None => fail("Did expect to receive a regulation need.") + } + } + } +} From 9fd51abf215de68284193e825e00a9087f18e9fb Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Wed, 12 Jan 2022 10:53:17 +0100 Subject: [PATCH 002/123] Build measurement and control models --- CHANGELOG.md | 1 + .../edu/ie3/simona/agent/grid/GridAgent.scala | 3 +- .../edu/ie3/simona/model/grid/GridModel.scala | 189 +++++++++++++++++- .../java/testutils/TestObjectFactory.java | 4 +- .../edu/ie3/simona/model/grid/GridSpec.scala | 116 +++++++++-- .../model/grid/TransformerModelSpec.scala | 3 +- 6 files changed, 289 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06328de446..b997d3fdf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - Config possibility for transformer control groups +- Models for measurements within the grid structure ### Changed - Improving code readability in EvcsAgent by moving FreeLotsRequest to separate methods diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 0ed6a265f0..6d3e125a72 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -165,7 +165,8 @@ class GridAgent( .toZonedDateTime(simonaConfig.simona.time.startDateTime), TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.endDateTime - ) + ), + simonaConfig.simona.control ) // we have to wait until the assets are ready diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 865f123c55..f6364a03e2 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -8,26 +8,34 @@ package edu.ie3.simona.model.grid import java.time.ZonedDateTime import java.util.UUID - import breeze.linalg.DenseMatrix import breeze.math.Complex import edu.ie3.datamodel.exceptions.InvalidGridException -import edu.ie3.datamodel.models.input.NodeInput +import edu.ie3.datamodel.models.input.{MeasurementUnitInput, NodeInput} import edu.ie3.datamodel.models.input.connector._ import edu.ie3.datamodel.models.input.container.SubGridContainer +import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.SystemComponent -import edu.ie3.simona.model.grid.GridModel.GridComponents +import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseA, PowerFlowCaseB, PowerFlowCaseC } +import edu.ie3.simona.model.control.{ + TransformerControlGroup => ControlGroupModel +} import edu.ie3.simona.util.CollectionUtils +import edu.ie3.util.quantities.PowerSystemUnits import org.jgrapht.Graph import org.jgrapht.alg.connectivity.ConnectivityInspector import org.jgrapht.graph.{DefaultEdge, SimpleGraph} +import tech.units.indriya.ComparableQuantity +import tech.units.indriya.quantity.Quantities +import javax.measure.quantity.Dimensionless import scala.collection.immutable.ListSet import scala.jdk.CollectionConverters._ @@ -38,7 +46,8 @@ import scala.jdk.CollectionConverters._ final case class GridModel( subnetNo: Int, mainRefSystem: RefSystem, - gridComponents: GridComponents + gridComponents: GridComponents, + gridControls: GridControls ) { // init nodeUuidToIndexMap @@ -66,10 +75,15 @@ case object GridModel { subGridContainer: SubGridContainer, refSystem: RefSystem, startDate: ZonedDateTime, - endDate: ZonedDateTime - ): GridModel = { - buildAndValidate(subGridContainer, refSystem, startDate, endDate) - } + endDate: ZonedDateTime, + controlConfig: Option[SimonaConfig.Simona.Control] + ): GridModel = buildAndValidate( + subGridContainer, + refSystem, + startDate, + endDate, + controlConfig + ) /** structure that represents all grid components that are needed by a grid * model @@ -82,6 +96,15 @@ case object GridModel { switches: Set[SwitchModel] ) + /** Collection of grid-related control strategies + * + * @param transformerControlGroups + * Transformer control groups + */ + final case class GridControls( + transformerControlGroups: Set[ControlGroupModel] + ) + /** Checks the availability of node calculation models, that are connected by * the given [[ConnectorInput]]. If not both models can be found, * [[InvalidGridException]] s are thrown @@ -491,7 +514,8 @@ case object GridModel { subGridContainer: SubGridContainer, refSystem: RefSystem, startDate: ZonedDateTime, - endDate: ZonedDateTime + endDate: ZonedDateTime, + maybeControlConfig: Option[SimonaConfig.Simona.Control] ): GridModel = { // build @@ -581,8 +605,26 @@ case object GridModel { switches ) + /* Build transformer control groups */ + val transformerControlGroups = maybeControlConfig + .map { controlConfig => + buildTransformerControlGroups( + controlConfig.transformer, + subGridContainer.getRawGrid.getMeasurementUnits + ) + } + .getOrElse(Set.empty[ControlGroupModel]) + + /* Build grid related control strategies */ + val gridControls = GridControls(transformerControlGroups) + val gridModel = - GridModel(subGridContainer.getSubnet, refSystem, gridComponents) + GridModel( + subGridContainer.getSubnet, + refSystem, + gridComponents, + gridControls + ) // validate validateConsistency(gridModel) @@ -592,6 +634,133 @@ case object GridModel { gridModel } + /** Build business models for transformer control groups + * + * @param config + * List of configs for control groups + * @param measurementUnitInput + * Set of [[MeasurementUnitInput]] s + * @return + * A set of control group business models + */ + private def buildTransformerControlGroups( + config: List[SimonaConfig.TransformerControlGroup], + measurementUnitInput: java.util.Set[MeasurementUnitInput] + ): Set[ControlGroupModel] = config.map { + case TransformerControlGroup(measurements, _, vMax, vMin) => + buildTransformerControlGroupModel( + measurementUnitInput, + measurements, + vMax, + vMin + ) + }.toSet + + /** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param measurementUnitInput + * Collection of all known [[MeasurementUnitInput]] s + * @param measurementConfigs + * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] + * s does belong to this control group + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[ControlGroupModel]] + */ + private def buildTransformerControlGroupModel( + measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementConfigs: List[String], + vMax: Double, + vMin: Double + ): ControlGroupModel = { + val nodeUuids = + determineNodeUuids(measurementUnitInput, measurementConfigs) + buildTransformerControlModels(nodeUuids, vMax, vMin) + } + + /** Determine the uuids of the nodes to control + * + * @param measurementUnitInput + * Collection of all known [[MeasurementUnitInput]] s + * @param measurementConfigs + * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] + * s does belong to this control group + * @return + * A set of relevant nodal uuids + */ + private def determineNodeUuids( + measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementConfigs: List[String] + ): Set[UUID] = Set.from( + measurementUnitInput.asScala + .filter(input => + measurementConfigs.contains(input.getUuid.toString) && input.getVMag + ) + .map(_.getNode.getUuid) + ) + + /** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param nodeUuids + * Collection of all relevant node uuids + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[ControlGroupModel]] + */ + private def buildTransformerControlModels( + nodeUuids: Set[UUID], + vMax: Double, + vMin: Double + ): ControlGroupModel = { + /* Determine the voltage regulation criterion for each of the available nodes */ + val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => + uuid -> { (complexVoltage: Complex) => + { + val vMag = complexVoltage.abs + if (vMag > vMax) + Some(vMax - vMag) + else if (vMag < vMin) + Some(vMin - vMag) + else + None + }.map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + } + }.toMap + + val harmonizationFunction = + (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { + val negativeRequests = regulationRequests.filter( + _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) + val positiveRequests = regulationRequests.filter( + _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) + + if (negativeRequests.nonEmpty && positiveRequests.nonEmpty) { + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + } else if (negativeRequests.nonEmpty) { + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + } else { + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + } + } + + ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) + } + /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to * account for changes on switches (open / close) It is highly recommended (= * mandatory) to call this method every time a node admittance matrix is diff --git a/src/test/java/testutils/TestObjectFactory.java b/src/test/java/testutils/TestObjectFactory.java index 5c33b6dd9e..2a1b3579bc 100644 --- a/src/test/java/testutils/TestObjectFactory.java +++ b/src/test/java/testutils/TestObjectFactory.java @@ -38,7 +38,7 @@ public static NodeInput buildNodeInput( boolean isSlack, CommonVoltageLevel voltageLvl, int subnet) { return new NodeInput( UUID.randomUUID(), - "TEST_NODE_" + TEST_OBJECT_COUNTER, + "TEST_NODE_" + TEST_OBJECT_COUNTER++, OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), Quantities.getQuantity(1d, PU), @@ -104,7 +104,7 @@ public static LineTypeInput buildLineTypeInput(VoltageLevel voltageLvl) { public static SwitchInput buildSwitchInput(NodeInput nodeA, NodeInput nodeB) { return new SwitchInput( UUID.randomUUID(), - "TEST_SWITCH" + TEST_OBJECT_COUNTER, + "TEST_SWITCH" + TEST_OBJECT_COUNTER++, OperatorInput.NO_OPERATOR_ASSIGNED, OperationTime.notLimited(), nodeA, diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 5ede9135a8..ca6aa14129 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -7,13 +7,15 @@ package edu.ie3.simona.model.grid import java.util.UUID - import breeze.linalg.DenseMatrix import breeze.math.Complex import breeze.numerics.abs import edu.ie3.datamodel.exceptions.InvalidGridException +import edu.ie3.datamodel.models.input.MeasurementUnitInput +import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException -import edu.ie3.simona.model.grid.GridModel.GridComponents +import edu.ie3.simona.model.control.TransformerControlGroup +import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} import edu.ie3.simona.test.common.model.grid.{ BasicGrid, @@ -21,6 +23,9 @@ import edu.ie3.simona.test.common.model.grid.{ FiveLinesWithNodes } import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} +import testutils.TestObjectFactory + +import scala.jdk.CollectionConverters.SetHasAsJava class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { @@ -117,7 +122,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // get the private method for validation val validateConnectivity: PrivateMethod[Unit] = @@ -145,7 +151,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], Set.empty[SwitchModel] - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // get the private method for validation @@ -190,7 +197,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // get the private method for validation @@ -229,7 +237,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -272,7 +281,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -357,7 +367,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -425,7 +436,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], Set.empty[SwitchModel] - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -446,9 +458,88 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { gridModel.nodeUuidToIndexMap.keySet.toVector.sorted should be( nodes.map(node => node.uuid).toVector.sorted ) - } + } + + "build correct transformer control models" should { + /* Testing of distinct transformer control group building can be found in the spec for transformer control groups */ + + "determine node uuids correctly" in { + val determineNodeUuids = + PrivateMethod[Set[UUID]](Symbol("determineNodeUuids")) + val node0 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1 + ) + val node1 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1 + ) + val node2 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1 + ) + val node3 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1 + ) + + val measurementUnits = Set( + new MeasurementUnitInput( + UUID.fromString("3ad9e076-c02b-4cf9-8720-18e2bb541ede"), + "measurement_unit_0", + node0, + true, + false, + false, + false + ), + new MeasurementUnitInput( + UUID.fromString("ab66fbb0-ece1-44b9-9341-86a884233ec4"), + "measurement_unit_1", + node1, + true, + false, + false, + false + ), + new MeasurementUnitInput( + UUID.fromString("93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d"), + "measurement_unit_2", + node2, + true, + false, + false, + false + ), + new MeasurementUnitInput( + UUID.fromString("8e84eb8a-2940-4900-b0ce-0eeb6bca8bae"), + "measurement_unit_3", + node3, + false, + false, + false, + false + ) + ).asJava + val selectedMeasurements = List( + "ab66fbb0-ece1-44b9-9341-86a884233ec4", + "93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d", + "8e84eb8a-2940-4900-b0ce-0eeb6bca8bae" + ) + val expectedUuids = Set(node1, node2).map(_.getUuid) + + val actual = GridModel invokePrivate determineNodeUuids( + measurementUnits, + selectedMeasurements + ) + actual should contain theSameElementsAs expectedUuids + } } "process a valid GridInputModel without an Exception" in new GridInputTestData { @@ -456,10 +547,9 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { validTestGridInputModel, gridInputModelTestDataRefSystem, defaultSimulationStart, - defaultSimulationEnd + defaultSimulationEnd, + controlConfig = None ) - } } - } diff --git a/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala index 2911e6c244..a4795f3834 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala @@ -403,7 +403,8 @@ class TransformerModelSpec extends UnitSpec with TableDrivenPropertyChecks { grid, refSystem, defaultSimulationStart, - defaultSimulationEnd + defaultSimulationEnd, + controlConfig = None ) gridModel.gridComponents.transformers From c739e3b7c76c48741da4f4af399c2c8094eb1b2d Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 20 May 2022 11:49:43 +0200 Subject: [PATCH 003/123] CherryPick from #92 --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 3 +- .../edu/ie3/simona/model/grid/GridModel.scala | 189 +++++++++++++++++- .../simona/scheduler/SchedulerHelper.scala | 45 ++--- .../edu/ie3/simona/model/grid/GridSpec.scala | 33 ++- .../model/grid/TransformerModelSpec.scala | 3 +- 5 files changed, 224 insertions(+), 49 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 38026c8e53..948bf6a81b 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -137,7 +137,8 @@ class GridAgent( .toZonedDateTime(simonaConfig.simona.time.startDateTime), TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.endDateTime - ) + ), + simonaConfig.simona.control ) /* Reassure, that there are also calculation models for the given uuids */ diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 865f123c55..f6364a03e2 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -8,26 +8,34 @@ package edu.ie3.simona.model.grid import java.time.ZonedDateTime import java.util.UUID - import breeze.linalg.DenseMatrix import breeze.math.Complex import edu.ie3.datamodel.exceptions.InvalidGridException -import edu.ie3.datamodel.models.input.NodeInput +import edu.ie3.datamodel.models.input.{MeasurementUnitInput, NodeInput} import edu.ie3.datamodel.models.input.connector._ import edu.ie3.datamodel.models.input.container.SubGridContainer +import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.SystemComponent -import edu.ie3.simona.model.grid.GridModel.GridComponents +import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseA, PowerFlowCaseB, PowerFlowCaseC } +import edu.ie3.simona.model.control.{ + TransformerControlGroup => ControlGroupModel +} import edu.ie3.simona.util.CollectionUtils +import edu.ie3.util.quantities.PowerSystemUnits import org.jgrapht.Graph import org.jgrapht.alg.connectivity.ConnectivityInspector import org.jgrapht.graph.{DefaultEdge, SimpleGraph} +import tech.units.indriya.ComparableQuantity +import tech.units.indriya.quantity.Quantities +import javax.measure.quantity.Dimensionless import scala.collection.immutable.ListSet import scala.jdk.CollectionConverters._ @@ -38,7 +46,8 @@ import scala.jdk.CollectionConverters._ final case class GridModel( subnetNo: Int, mainRefSystem: RefSystem, - gridComponents: GridComponents + gridComponents: GridComponents, + gridControls: GridControls ) { // init nodeUuidToIndexMap @@ -66,10 +75,15 @@ case object GridModel { subGridContainer: SubGridContainer, refSystem: RefSystem, startDate: ZonedDateTime, - endDate: ZonedDateTime - ): GridModel = { - buildAndValidate(subGridContainer, refSystem, startDate, endDate) - } + endDate: ZonedDateTime, + controlConfig: Option[SimonaConfig.Simona.Control] + ): GridModel = buildAndValidate( + subGridContainer, + refSystem, + startDate, + endDate, + controlConfig + ) /** structure that represents all grid components that are needed by a grid * model @@ -82,6 +96,15 @@ case object GridModel { switches: Set[SwitchModel] ) + /** Collection of grid-related control strategies + * + * @param transformerControlGroups + * Transformer control groups + */ + final case class GridControls( + transformerControlGroups: Set[ControlGroupModel] + ) + /** Checks the availability of node calculation models, that are connected by * the given [[ConnectorInput]]. If not both models can be found, * [[InvalidGridException]] s are thrown @@ -491,7 +514,8 @@ case object GridModel { subGridContainer: SubGridContainer, refSystem: RefSystem, startDate: ZonedDateTime, - endDate: ZonedDateTime + endDate: ZonedDateTime, + maybeControlConfig: Option[SimonaConfig.Simona.Control] ): GridModel = { // build @@ -581,8 +605,26 @@ case object GridModel { switches ) + /* Build transformer control groups */ + val transformerControlGroups = maybeControlConfig + .map { controlConfig => + buildTransformerControlGroups( + controlConfig.transformer, + subGridContainer.getRawGrid.getMeasurementUnits + ) + } + .getOrElse(Set.empty[ControlGroupModel]) + + /* Build grid related control strategies */ + val gridControls = GridControls(transformerControlGroups) + val gridModel = - GridModel(subGridContainer.getSubnet, refSystem, gridComponents) + GridModel( + subGridContainer.getSubnet, + refSystem, + gridComponents, + gridControls + ) // validate validateConsistency(gridModel) @@ -592,6 +634,133 @@ case object GridModel { gridModel } + /** Build business models for transformer control groups + * + * @param config + * List of configs for control groups + * @param measurementUnitInput + * Set of [[MeasurementUnitInput]] s + * @return + * A set of control group business models + */ + private def buildTransformerControlGroups( + config: List[SimonaConfig.TransformerControlGroup], + measurementUnitInput: java.util.Set[MeasurementUnitInput] + ): Set[ControlGroupModel] = config.map { + case TransformerControlGroup(measurements, _, vMax, vMin) => + buildTransformerControlGroupModel( + measurementUnitInput, + measurements, + vMax, + vMin + ) + }.toSet + + /** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param measurementUnitInput + * Collection of all known [[MeasurementUnitInput]] s + * @param measurementConfigs + * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] + * s does belong to this control group + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[ControlGroupModel]] + */ + private def buildTransformerControlGroupModel( + measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementConfigs: List[String], + vMax: Double, + vMin: Double + ): ControlGroupModel = { + val nodeUuids = + determineNodeUuids(measurementUnitInput, measurementConfigs) + buildTransformerControlModels(nodeUuids, vMax, vMin) + } + + /** Determine the uuids of the nodes to control + * + * @param measurementUnitInput + * Collection of all known [[MeasurementUnitInput]] s + * @param measurementConfigs + * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] + * s does belong to this control group + * @return + * A set of relevant nodal uuids + */ + private def determineNodeUuids( + measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementConfigs: List[String] + ): Set[UUID] = Set.from( + measurementUnitInput.asScala + .filter(input => + measurementConfigs.contains(input.getUuid.toString) && input.getVMag + ) + .map(_.getNode.getUuid) + ) + + /** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param nodeUuids + * Collection of all relevant node uuids + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[ControlGroupModel]] + */ + private def buildTransformerControlModels( + nodeUuids: Set[UUID], + vMax: Double, + vMin: Double + ): ControlGroupModel = { + /* Determine the voltage regulation criterion for each of the available nodes */ + val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => + uuid -> { (complexVoltage: Complex) => + { + val vMag = complexVoltage.abs + if (vMag > vMax) + Some(vMax - vMag) + else if (vMag < vMin) + Some(vMin - vMag) + else + None + }.map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + } + }.toMap + + val harmonizationFunction = + (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { + val negativeRequests = regulationRequests.filter( + _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) + val positiveRequests = regulationRequests.filter( + _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) + + if (negativeRequests.nonEmpty && positiveRequests.nonEmpty) { + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + } else if (negativeRequests.nonEmpty) { + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + } else { + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + } + } + + ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) + } + /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to * account for changes on switches (open / close) It is highly recommended (= * mandatory) to call this method every time a node admittance matrix is diff --git a/src/main/scala/edu/ie3/simona/scheduler/SchedulerHelper.scala b/src/main/scala/edu/ie3/simona/scheduler/SchedulerHelper.scala index a684fd2def..86c3338622 100644 --- a/src/main/scala/edu/ie3/simona/scheduler/SchedulerHelper.scala +++ b/src/main/scala/edu/ie3/simona/scheduler/SchedulerHelper.scala @@ -20,9 +20,7 @@ import edu.ie3.simona.logging.SimonaActorLogging import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.ontology.messages.SchedulerMessage._ import edu.ie3.simona.ontology.trigger.{ScheduledTrigger, Trigger} -import edu.ie3.simona.ontology.trigger.Trigger.InitializeTrigger import edu.ie3.simona.scheduler.SimSchedulerStateData.SchedulerStateData -import edu.ie3.simona.sim.SimonaSim import edu.ie3.simona.util.SimonaConstants import edu.ie3.util.TimeUtil @@ -57,17 +55,18 @@ trait SchedulerHelper extends SimonaActorLogging { private val schedulerReadyCheckWindow = simonaTimeConfig.schedulerReadyCheckWindow - /** Sends out all triggers of type [[InitializeTrigger]] inside the trigger - * queue in the provided state data. This method modifies the mutual trigger - * data inside of the provided [[SimSchedulerStateData]]. To indicate this - * behavior, the provided state data is returned again, because the return - * value is a modified, but not a copied version of the provided state data! + /** Sends out all triggers with tick [[SimonaConstants.INIT_SIM_TICK]] inside + * the trigger queue in the provided state data. This method modifies the + * mutual trigger data inside of the provided [[SimSchedulerStateData]]. To + * indicate this behavior, the provided state data is returned again, because + * the return value is a modified, but not a copied version of the provided + * state data! * * @param stateData * the state data that should be processed * @return - * a modified version of the provided state data with all - * [[InitializeTrigger]] send out and updated + * a modified version of the provided state data with all triggers with + * tick [[SimonaConstants.INIT_SIM_TICK]] sent out and updated * [[SimSchedulerStateData.SchedulerStateData.trigger.awaitingResponseMap]] * and * [[SimSchedulerStateData.SchedulerStateData.trigger.triggerIdToScheduledTriggerMap accordingly]] @@ -87,10 +86,7 @@ trait SchedulerHelper extends SimonaActorLogging { val initTriggers = triggerQueue.stream .toScala(Accumulator) .filter(schedTrigger => - schedTrigger.triggerWithIdMessage.trigger match { - case _: InitializeTrigger => true - case _ => false - } + schedTrigger.triggerWithIdMessage.trigger.tick == SimonaConstants.INIT_SIM_TICK ) .map(schedTrigger => { /* actual init process */ @@ -809,9 +805,10 @@ trait SchedulerHelper extends SimonaActorLogging { } /** Checks if initialization of the simulation is complete. It is complete, if - * two conditions are fulfilled:
  1. there is no [[InitializeTrigger]] - * inside the provided trigger queue left
  2. there is no sent out - * [[InitializeTrigger]], which is not completed, yet
+ * two conditions are fulfilled:
  1. there is no trigger with tick + * [[SimonaConstants.INIT_SIM_TICK]] inside the provided trigger queue + * left
  2. there is no sent out trigger with tick + * [[SimonaConstants.INIT_SIM_TICK]], which is not completed, yet
* * @param awaitingResponseMap * a map containing a tick to scheduled trigger mapping @@ -824,22 +821,16 @@ trait SchedulerHelper extends SimonaActorLogging { awaitingResponseMap: TreeMultimap[java.lang.Long, ScheduledTrigger], triggerQueue: java.util.PriorityQueue[ScheduledTrigger] ): Boolean = { - val initAwait = awaitingResponseMap + val initAwait = !awaitingResponseMap .get(SimonaConstants.INIT_SIM_TICK) - .asScala - .iterator - .exists(_.triggerWithIdMessage.trigger match { - case _: InitializeTrigger => true - case _ => false - }) + .isEmpty val initTriggerInQueue = triggerQueue .iterator() .asScala - .exists(_.triggerWithIdMessage.trigger match { - case _: InitializeTrigger => true - case _ => false - }) + .exists( + _.triggerWithIdMessage.trigger.tick == SimonaConstants.INIT_SIM_TICK + ) !initAwait && !initTriggerInQueue } diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 5ede9135a8..26e198f0d7 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -7,13 +7,15 @@ package edu.ie3.simona.model.grid import java.util.UUID - import breeze.linalg.DenseMatrix import breeze.math.Complex import breeze.numerics.abs import edu.ie3.datamodel.exceptions.InvalidGridException +import edu.ie3.datamodel.models.input.MeasurementUnitInput +import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException -import edu.ie3.simona.model.grid.GridModel.GridComponents +import edu.ie3.simona.model.control.TransformerControlGroup +import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} import edu.ie3.simona.test.common.model.grid.{ BasicGrid, @@ -21,6 +23,9 @@ import edu.ie3.simona.test.common.model.grid.{ FiveLinesWithNodes } import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} +import testutils.TestObjectFactory + +import scala.jdk.CollectionConverters.SetHasAsJava class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { @@ -117,7 +122,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // get the private method for validation val validateConnectivity: PrivateMethod[Unit] = @@ -145,7 +151,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], Set.empty[SwitchModel] - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // get the private method for validation @@ -190,7 +197,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // get the private method for validation @@ -229,7 +237,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -272,7 +281,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -357,7 +367,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], switches - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -425,7 +436,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set(transformer2wModel), Set.empty[Transformer3wModel], Set.empty[SwitchModel] - ) + ), + GridControls(Set.empty[TransformerControlGroup]) ) // update the uuidToIndexMap @@ -456,7 +468,8 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { validTestGridInputModel, gridInputModelTestDataRefSystem, defaultSimulationStart, - defaultSimulationEnd + defaultSimulationEnd, + controlConfig = None ) } diff --git a/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala index 2911e6c244..a4795f3834 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala @@ -403,7 +403,8 @@ class TransformerModelSpec extends UnitSpec with TableDrivenPropertyChecks { grid, refSystem, defaultSimulationStart, - defaultSimulationEnd + defaultSimulationEnd, + controlConfig = None ) gridModel.gridComponents.transformers From 103c788189baa31759dc88e857b7965b628a2b2b Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 2 Jun 2022 11:00:36 +0200 Subject: [PATCH 004/123] Review feedback class description --- .../edu/ie3/simona/model/control/TransformerControlGroup.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala index 652b40b4e1..dad17e5f7e 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala @@ -16,7 +16,7 @@ import java.util.UUID import javax.measure.quantity.Dimensionless /** Business logic for a transformer control group. It's main purpose is to - * determine, if there is any regulation need and if yes, in what circumference + * determine, if there is any regulation need and if yes, to what extent * (here: voltage raise or reduction to achieve) * * @param nodalRegulationCriterion From b9de2434fc65dc7495f32924ad56f889edf3ee08 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 3 Jun 2022 11:11:32 +0200 Subject: [PATCH 005/123] check Boundaries of Control Group --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 67 ++++++++++++++----- .../control/TransformerControlGroup.scala | 4 +- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 948bf6a81b..d300e5b6dc 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -7,35 +7,23 @@ package edu.ie3.simona.agent.grid import akka.actor.{ActorRef, Props, Stash} -import edu.ie3.simona.agent.grid.GridAgentData.{ - GridAgentBaseData, - GridAgentInitData, - GridAgentUninitializedData -} +import edu.ie3.simona.agent.grid.GridAgentData.{GridAgentBaseData, GridAgentInitData, GridAgentUninitializedData} import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage -import edu.ie3.simona.ontology.messages.SchedulerMessage.{ - CompletionMessage, - ScheduleTriggerMessage, - TriggerWithIdMessage -} +import edu.ie3.simona.ontology.messages.SchedulerMessage.{CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage} import edu.ie3.simona.ontology.messages.StopMessage -import edu.ie3.simona.ontology.trigger.Trigger.{ - ActivityStartTrigger, - InitializeGridAgentTrigger, - StartGridSimulationTrigger -} +import edu.ie3.simona.ontology.trigger.Trigger.{ActivityStartTrigger, InitializeGridAgentTrigger, StartGridSimulationTrigger} import edu.ie3.util.TimeUtil import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.UUID -import scala.concurrent.ExecutionContext import scala.concurrent.duration._ import scala.language.postfixOps @@ -223,8 +211,10 @@ class GridAgent( // everything else whenUnhandled(myUnhandled()) - private def failFast(gridAgentInitData: GridAgentInitData): Unit = { + + /** Check if there is InitData for superior or inferior GridGates + */ if ( gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty ) @@ -232,5 +222,48 @@ class GridAgent( s"$actorName has neither superior nor inferior grids! This can either " + s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" ) + + /** Check of Control Boundaries + */ + if (simonaConfig.simona.control.isDefined) { + val transformerControlGroup = simonaConfig.simona.control match { + case Some(control) => control.transformer + } + checkBoundariesofControlGroup(transformerControlGroup, gridAgentInitData) + } + } + + private def checkBoundariesofControlGroup( + transformerControlGroup: List[TransformerControlGroup], + gridAgentInitData: GridAgentInitData + ): Unit = { + val vNom = gridAgentInitData.refSystem.nominalVoltage + val lowerBoundary = vNom.multiply(0.8).getValue.doubleValue() + val upperBoundary = vNom.multiply(1.2).getValue.doubleValue() + + for (controlGroup <- transformerControlGroup) + controlGroup match { + case TransformerControlGroup(measurements, transformers, vMax, vMin) => + if (lowerBoundary > vMin) + throw new GridAgentInitializationException( + s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where the lower Boundary is higher than vMin!" + ) + if (lowerBoundary > vMax) + throw new GridAgentInitializationException( + s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where the lower Boundary is higher than vMax!" + ) + if (upperBoundary < vMin) + throw new GridAgentInitializationException( + s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where the upper Boundary is lower than vMin!" + ) + if (upperBoundary < vMax) + throw new GridAgentInitializationException( + s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where the upper Boundary is lower than vMax!" + ) + } } } diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala index dad17e5f7e..bf9bc582b8 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala @@ -16,8 +16,8 @@ import java.util.UUID import javax.measure.quantity.Dimensionless /** Business logic for a transformer control group. It's main purpose is to - * determine, if there is any regulation need and if yes, to what extent - * (here: voltage raise or reduction to achieve) + * determine, if there is any regulation need and if yes, to what extent (here: + * voltage raise or reduction to achieve) * * @param nodalRegulationCriterion * Mapping from nodal index to a partial function, that determines the From b55ea2d9e5b71ee5d3b8814deca0ba40d5e2e6cc Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 3 Jun 2022 16:54:23 +0200 Subject: [PATCH 006/123] methods moved into object --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 124 +++++++++--------- 1 file changed, 65 insertions(+), 59 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index d300e5b6dc..39dc1bb4be 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -7,7 +7,11 @@ package edu.ie3.simona.agent.grid import akka.actor.{ActorRef, Props, Stash} -import edu.ie3.simona.agent.grid.GridAgentData.{GridAgentBaseData, GridAgentInitData, GridAgentUninitializedData} +import edu.ie3.simona.agent.grid.GridAgentData.{ + GridAgentBaseData, + GridAgentInitData, + GridAgentUninitializedData +} import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} @@ -16,15 +20,22 @@ import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage -import edu.ie3.simona.ontology.messages.SchedulerMessage.{CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage} +import edu.ie3.simona.ontology.messages.SchedulerMessage.{ + CompletionMessage, + ScheduleTriggerMessage, + TriggerWithIdMessage +} import edu.ie3.simona.ontology.messages.StopMessage -import edu.ie3.simona.ontology.trigger.Trigger.{ActivityStartTrigger, InitializeGridAgentTrigger, StartGridSimulationTrigger} +import edu.ie3.simona.ontology.trigger.Trigger.{ + ActivityStartTrigger, + InitializeGridAgentTrigger, + StartGridSimulationTrigger +} import edu.ie3.util.TimeUtil import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.UUID -import scala.concurrent.duration._ import scala.language.postfixOps object GridAgent { @@ -40,6 +51,55 @@ object GridAgent { listener ) ) + + private def failFast( + simonaConfig: SimonaConfig, + gridAgentInitData: GridAgentInitData + ): Unit = { + + /** Check if there is InitData for superior or inferior GridGates + */ + if ( + gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty + ) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + + s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" + ) + + /** Check of Control Boundaries + */ + simonaConfig.simona.control.foreach(control => + checkBoundariesOfControlGroup(control.transformer, gridAgentInitData) + ) + } + + private def checkBoundariesOfControlGroup( + transformerControlGroup: Seq[TransformerControlGroup], + gridAgentInitData: GridAgentInitData + ): Unit = { + val vNom = gridAgentInitData.refSystem.nominalVoltage + // TODO transfer lowerBoundary Voltage from RefSystem to per Unit + // val lowerBoundary = vNom.multiply(0.8).getValue.doubleValue() + val lowerBoundary = 0.8 + // TODO transfer lowerBoundary Voltage from RefSystem to per Unit + // val upperBoundary = vNom.multiply(1.2).getValue.doubleValue() + val upperBoundary = 1.2 + + transformerControlGroup.foreach { + case TransformerControlGroup(_, _, vMax, vMin) => + if (vMin < lowerBoundary) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" + ) + if (vMax > upperBoundary) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" + ) + } + } } class GridAgent( @@ -97,7 +157,7 @@ class GridAgent( _ ) => // fail fast sanity checks - failFast(gridAgentInitData) + GridAgent.failFast(simonaConfig, gridAgentInitData) log.debug( s"Inferior Subnets: {}; Inferior Subnet Nodes: {}", @@ -211,59 +271,5 @@ class GridAgent( // everything else whenUnhandled(myUnhandled()) - private def failFast(gridAgentInitData: GridAgentInitData): Unit = { - - /** Check if there is InitData for superior or inferior GridGates - */ - if ( - gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty - ) - throw new GridAgentInitializationException( - s"$actorName has neither superior nor inferior grids! This can either " + - s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" - ) - - /** Check of Control Boundaries - */ - if (simonaConfig.simona.control.isDefined) { - val transformerControlGroup = simonaConfig.simona.control match { - case Some(control) => control.transformer - } - checkBoundariesofControlGroup(transformerControlGroup, gridAgentInitData) - } - } - private def checkBoundariesofControlGroup( - transformerControlGroup: List[TransformerControlGroup], - gridAgentInitData: GridAgentInitData - ): Unit = { - val vNom = gridAgentInitData.refSystem.nominalVoltage - val lowerBoundary = vNom.multiply(0.8).getValue.doubleValue() - val upperBoundary = vNom.multiply(1.2).getValue.doubleValue() - - for (controlGroup <- transformerControlGroup) - controlGroup match { - case TransformerControlGroup(measurements, transformers, vMax, vMin) => - if (lowerBoundary > vMin) - throw new GridAgentInitializationException( - s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where the lower Boundary is higher than vMin!" - ) - if (lowerBoundary > vMax) - throw new GridAgentInitializationException( - s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where the lower Boundary is higher than vMax!" - ) - if (upperBoundary < vMin) - throw new GridAgentInitializationException( - s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where the upper Boundary is lower than vMin!" - ) - if (upperBoundary < vMax) - throw new GridAgentInitializationException( - s"$actorName has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where the upper Boundary is lower than vMax!" - ) - } - } } From 185ce9985cdfc8b1f29ecefea86c737d3dafcbe0 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 3 Jun 2022 16:54:53 +0200 Subject: [PATCH 007/123] test for check of boundaries of control group --- .../agent/grid/GridAgentControlSpec.scala | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala new file mode 100644 index 0000000000..310a19f73b --- /dev/null +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala @@ -0,0 +1,87 @@ +/* + * © 2020. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.agent.grid + +import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData +import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup +import edu.ie3.simona.exceptions.agent.GridAgentInitializationException +import edu.ie3.simona.model.grid.RefSystem +import edu.ie3.simona.test.common.UnitSpec +import edu.ie3.simona.test.common.input.GridInputTestData + +class GridAgentControlSpec extends UnitSpec with GridInputTestData { + + "GridAgentControl" should { + val checkBoundariesOfControlGroup = PrivateMethod[Unit]( + Symbol("checkBoundariesOfControlGroup") + ) + + + val gridAgentInitData = GridAgentInitData( + validTestGridInputModel, + Map.empty, + RefSystem("400 kVA", "400 V") + ) + + "throw Exception when vMin is lower then -21% of nominal Voltage" in { + val transformerControlGroup = Seq( + TransformerControlGroup( + List.empty[String], + List.empty[String], + 1.1, + 0.79 + ) + ) + + intercept[GridAgentInitializationException] { + GridAgent invokePrivate checkBoundariesOfControlGroup( + transformerControlGroup, + gridAgentInitData + ) + }.getMessage shouldBe "TestGrid has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + "by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" + + } + + "throw Exception when vMax is higher then +21% of nominal Voltage" in { + val transformerControlGroup = Seq( + TransformerControlGroup( + List.empty[String], + List.empty[String], + 1.21, + 0.9 + ) + ) + + intercept[GridAgentInitializationException] { + GridAgent invokePrivate checkBoundariesOfControlGroup( + transformerControlGroup, + gridAgentInitData + ) + }.getMessage shouldBe "TestGrid has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + "by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" + + } + + "should run through when vMin and vMax are within the boundaries of +-20% of nominal Voltage" in { + val transformerControlGroup = Seq( + TransformerControlGroup( + List.empty[String], + List.empty[String], + 1.1, + 0.9 + ) + ) + + GridAgent invokePrivate checkBoundariesOfControlGroup( + transformerControlGroup, + gridAgentInitData + ) + } + + } +} From 0dd1acb9af8e80cb3ba94c3606248544520e0d13 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 7 Jun 2022 10:52:16 +0200 Subject: [PATCH 008/123] removed boundary checks of control group back to ConfigFailFast --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 57 ++----------------- .../ie3/simona/config/ConfigFailFast.scala | 17 +++++- 2 files changed, 21 insertions(+), 53 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 39dc1bb4be..403ceb4dd6 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -7,30 +7,17 @@ package edu.ie3.simona.agent.grid import akka.actor.{ActorRef, Props, Stash} -import edu.ie3.simona.agent.grid.GridAgentData.{ - GridAgentBaseData, - GridAgentInitData, - GridAgentUninitializedData -} +import edu.ie3.simona.agent.grid.GridAgentData.{GridAgentBaseData, GridAgentInitData, GridAgentUninitializedData} import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} import edu.ie3.simona.config.SimonaConfig -import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage -import edu.ie3.simona.ontology.messages.SchedulerMessage.{ - CompletionMessage, - ScheduleTriggerMessage, - TriggerWithIdMessage -} +import edu.ie3.simona.ontology.messages.SchedulerMessage.{CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage} import edu.ie3.simona.ontology.messages.StopMessage -import edu.ie3.simona.ontology.trigger.Trigger.{ - ActivityStartTrigger, - InitializeGridAgentTrigger, - StartGridSimulationTrigger -} +import edu.ie3.simona.ontology.trigger.Trigger.{ActivityStartTrigger, InitializeGridAgentTrigger, StartGridSimulationTrigger} import edu.ie3.util.TimeUtil import java.time.ZonedDateTime @@ -53,8 +40,7 @@ object GridAgent { ) private def failFast( - simonaConfig: SimonaConfig, - gridAgentInitData: GridAgentInitData + gridAgentInitData: GridAgentInitData ): Unit = { /** Check if there is InitData for superior or inferior GridGates @@ -66,39 +52,6 @@ object GridAgent { s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" ) - - /** Check of Control Boundaries - */ - simonaConfig.simona.control.foreach(control => - checkBoundariesOfControlGroup(control.transformer, gridAgentInitData) - ) - } - - private def checkBoundariesOfControlGroup( - transformerControlGroup: Seq[TransformerControlGroup], - gridAgentInitData: GridAgentInitData - ): Unit = { - val vNom = gridAgentInitData.refSystem.nominalVoltage - // TODO transfer lowerBoundary Voltage from RefSystem to per Unit - // val lowerBoundary = vNom.multiply(0.8).getValue.doubleValue() - val lowerBoundary = 0.8 - // TODO transfer lowerBoundary Voltage from RefSystem to per Unit - // val upperBoundary = vNom.multiply(1.2).getValue.doubleValue() - val upperBoundary = 1.2 - - transformerControlGroup.foreach { - case TransformerControlGroup(_, _, vMax, vMin) => - if (vMin < lowerBoundary) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" - ) - if (vMax > upperBoundary) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" - ) - } } } @@ -157,7 +110,7 @@ class GridAgent( _ ) => // fail fast sanity checks - GridAgent.failFast(simonaConfig, gridAgentInitData) + GridAgent.failFast(gridAgentInitData) log.debug( s"Inferior Subnets: {}; Inferior Subnet Nodes: {}", diff --git a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala index 3863ae92c2..5b6b24195c 100644 --- a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala +++ b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala @@ -569,7 +569,10 @@ case object ConfigFailFast extends LazyLogging { */ private def checkTransformerControl( transformerControlGroup: TransformerControlGroup - ): Unit = transformerControlGroup match { + ): Unit = { + val lowerBoundary = 0.8 + val upperBoundary = 1.2 + transformerControlGroup match { case TransformerControlGroup(measurements, transformers, vMax, vMin) => if (measurements.isEmpty) throw new InvalidConfigParameterException( @@ -591,8 +594,20 @@ case object ConfigFailFast extends LazyLogging { throw new InvalidConfigParameterException( "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." ) + if (vMin < lowerBoundary) + throw new InvalidConfigParameterException( + s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" + ) + if (vMax > upperBoundary) + throw new InvalidConfigParameterException( + s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" + ) + } } + /** Check the default config * * @param config From 39a42daa2cc8de5b155fbab924b38261422a94be Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 7 Jun 2022 10:53:31 +0200 Subject: [PATCH 009/123] removed unnecessary checks --- .../ie3/simona/config/ConfigFailFast.scala | 57 ++++++++----------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala index 5b6b24195c..e3eea5f1e3 100644 --- a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala +++ b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala @@ -573,41 +573,32 @@ case object ConfigFailFast extends LazyLogging { val lowerBoundary = 0.8 val upperBoundary = 1.2 transformerControlGroup match { - case TransformerControlGroup(measurements, transformers, vMax, vMin) => - if (measurements.isEmpty) - throw new InvalidConfigParameterException( - "A transformer control group cannot have no measurements assigned." - ) - if (transformers.isEmpty) - throw new InvalidConfigParameterException( - "A transformer control group cannot have no transformers assigned." - ) - if (vMin < 0) - throw new InvalidConfigParameterException( - "The minimum permissible voltage magnitude of a transformer control group has to be positive." - ) - if (vMax < 0) - throw new InvalidConfigParameterException( - "The maximum permissible voltage magnitude of a transformer control group has to be positive." - ) - if (vMax < vMin) - throw new InvalidConfigParameterException( - "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." - ) - if (vMin < lowerBoundary) - throw new InvalidConfigParameterException( - s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" - ) - if (vMax > upperBoundary) - throw new InvalidConfigParameterException( - s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - s"by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" - ) - } + case TransformerControlGroup(measurements, transformers, vMax, vMin) => + if (measurements.isEmpty) + throw new InvalidConfigParameterException( + "A transformer control group cannot have no measurements assigned." + ) + if (transformers.isEmpty) + throw new InvalidConfigParameterException( + "A transformer control group cannot have no transformers assigned." + ) + if (vMax < vMin) + throw new InvalidConfigParameterException( + "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." + ) + if (vMin < lowerBoundary) + throw new InvalidConfigParameterException( + s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" + ) + if (vMax > upperBoundary) + throw new InvalidConfigParameterException( + s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" + ) + } } - /** Check the default config * * @param config From 8a1027d0debdb09a6bf40c0befc6a927cefaa7a0 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 7 Jun 2022 10:53:43 +0200 Subject: [PATCH 010/123] spotless --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 20 +++++++++++++++---- .../agent/grid/GridAgentControlSpec.scala | 13 ++++++------ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 403ceb4dd6..387b96f373 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -7,7 +7,11 @@ package edu.ie3.simona.agent.grid import akka.actor.{ActorRef, Props, Stash} -import edu.ie3.simona.agent.grid.GridAgentData.{GridAgentBaseData, GridAgentInitData, GridAgentUninitializedData} +import edu.ie3.simona.agent.grid.GridAgentData.{ + GridAgentBaseData, + GridAgentInitData, + GridAgentUninitializedData +} import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} @@ -15,9 +19,17 @@ import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage -import edu.ie3.simona.ontology.messages.SchedulerMessage.{CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage} +import edu.ie3.simona.ontology.messages.SchedulerMessage.{ + CompletionMessage, + ScheduleTriggerMessage, + TriggerWithIdMessage +} import edu.ie3.simona.ontology.messages.StopMessage -import edu.ie3.simona.ontology.trigger.Trigger.{ActivityStartTrigger, InitializeGridAgentTrigger, StartGridSimulationTrigger} +import edu.ie3.simona.ontology.trigger.Trigger.{ + ActivityStartTrigger, + InitializeGridAgentTrigger, + StartGridSimulationTrigger +} import edu.ie3.util.TimeUtil import java.time.ZonedDateTime @@ -40,7 +52,7 @@ object GridAgent { ) private def failFast( - gridAgentInitData: GridAgentInitData + gridAgentInitData: GridAgentInitData ): Unit = { /** Check if there is InitData for superior or inferior GridGates diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala index 310a19f73b..54159667d1 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala @@ -20,7 +20,6 @@ class GridAgentControlSpec extends UnitSpec with GridInputTestData { Symbol("checkBoundariesOfControlGroup") ) - val gridAgentInitData = GridAgentInitData( validTestGridInputModel, Map.empty, @@ -69,13 +68,13 @@ class GridAgentControlSpec extends UnitSpec with GridInputTestData { "should run through when vMin and vMax are within the boundaries of +-20% of nominal Voltage" in { val transformerControlGroup = Seq( - TransformerControlGroup( - List.empty[String], - List.empty[String], - 1.1, - 0.9 + TransformerControlGroup( + List.empty[String], + List.empty[String], + 1.1, + 0.9 + ) ) - ) GridAgent invokePrivate checkBoundariesOfControlGroup( transformerControlGroup, From 3939ffcb3bb8a6324bda18c5e4ed1a6e0e5a270f Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 7 Jun 2022 11:28:53 +0200 Subject: [PATCH 011/123] moved test from GridAgentControlSpec to ConfigFailFastSpec --- .../agent/grid/GridAgentControlSpec.scala | 86 ------------------- .../simona/config/ConfigFailFastSpec.scala | 14 +-- 2 files changed, 8 insertions(+), 92 deletions(-) delete mode 100644 src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala deleted file mode 100644 index 54159667d1..0000000000 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentControlSpec.scala +++ /dev/null @@ -1,86 +0,0 @@ -/* - * © 2020. TU Dortmund University, - * Institute of Energy Systems, Energy Efficiency and Energy Economics, - * Research group Distribution grid planning and operation - */ - -package edu.ie3.simona.agent.grid - -import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup -import edu.ie3.simona.exceptions.agent.GridAgentInitializationException -import edu.ie3.simona.model.grid.RefSystem -import edu.ie3.simona.test.common.UnitSpec -import edu.ie3.simona.test.common.input.GridInputTestData - -class GridAgentControlSpec extends UnitSpec with GridInputTestData { - - "GridAgentControl" should { - val checkBoundariesOfControlGroup = PrivateMethod[Unit]( - Symbol("checkBoundariesOfControlGroup") - ) - - val gridAgentInitData = GridAgentInitData( - validTestGridInputModel, - Map.empty, - RefSystem("400 kVA", "400 V") - ) - - "throw Exception when vMin is lower then -21% of nominal Voltage" in { - val transformerControlGroup = Seq( - TransformerControlGroup( - List.empty[String], - List.empty[String], - 1.1, - 0.79 - ) - ) - - intercept[GridAgentInitializationException] { - GridAgent invokePrivate checkBoundariesOfControlGroup( - transformerControlGroup, - gridAgentInitData - ) - }.getMessage shouldBe "TestGrid has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - "by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" - - } - - "throw Exception when vMax is higher then +21% of nominal Voltage" in { - val transformerControlGroup = Seq( - TransformerControlGroup( - List.empty[String], - List.empty[String], - 1.21, - 0.9 - ) - ) - - intercept[GridAgentInitializationException] { - GridAgent invokePrivate checkBoundariesOfControlGroup( - transformerControlGroup, - gridAgentInitData - ) - }.getMessage shouldBe "TestGrid has a control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + - "by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" - - } - - "should run through when vMin and vMax are within the boundaries of +-20% of nominal Voltage" in { - val transformerControlGroup = Seq( - TransformerControlGroup( - List.empty[String], - List.empty[String], - 1.1, - 0.9 - ) - ) - - GridAgent invokePrivate checkBoundariesOfControlGroup( - transformerControlGroup, - gridAgentInitData - ) - } - - } -} diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 4323c80ba1..cf0143040e 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -916,30 +916,32 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { }.getMessage shouldBe "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." } - "throw an exception, if vMin is negative" in { + "throw Exception when vMin is lower then -21% of nominal Voltage" in { val dut = TransformerControlGroup( List("6888c53a-7629-4563-ac8e-840f80b03106"), List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), 1.02, - -0.98 + 0.79 ) intercept[InvalidConfigParameterException] { ConfigFailFast invokePrivate checkTransformerControl(dut) - }.getMessage shouldBe "The minimum permissible voltage magnitude of a transformer control group has to be positive." + }.getMessage shouldBe "A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + "by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" } - "throw an exception, if vMax is negative" in { + "throw Exception when vMax is higher then +21% of nominal Voltage" in { val dut = TransformerControlGroup( List("6888c53a-7629-4563-ac8e-840f80b03106"), List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), - -1.02, + 1.21, 0.98 ) intercept[InvalidConfigParameterException] { ConfigFailFast invokePrivate checkTransformerControl(dut) - }.getMessage shouldBe "The maximum permissible voltage magnitude of a transformer control group has to be positive." + }.getMessage shouldBe "A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + "by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" } } } From c2c456eff79670c681b1d7decd027a54210dbb26 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 7 Jun 2022 13:56:00 +0200 Subject: [PATCH 012/123] change order of attributes in config-template --- .../config/simona-config-template.conf | 4 +- .../edu/ie3/simona/config/SimonaConfig.scala | 2625 +++++------------ 2 files changed, 757 insertions(+), 1872 deletions(-) diff --git a/src/main/resources/config/simona-config-template.conf b/src/main/resources/config/simona-config-template.conf index 107816194e..0fd4082ea0 100644 --- a/src/main/resources/config/simona-config-template.conf +++ b/src/main/resources/config/simona-config-template.conf @@ -89,11 +89,11 @@ GridOutputConfig { #@define TransformerControlGroup { - transformers: [string] measurements: [string] + transformers: [string] # TODO: Currently, only limit prevention is configurable. Should be an interface, when it is allowed by tscfg - vMin: Double vMax: Double + vMin: Double } ################################################################## diff --git a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala index dada716baf..b519da4699 100644 --- a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala +++ b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala @@ -1,2356 +1,1241 @@ -/* - * © 2022. TU Dortmund University, - * Institute of Energy Systems, Energy Efficiency and Energy Economics, - * Research group Distribution grid planning and operation - */ +// generated by tscfg 0.9.998 on Tue Jun 07 13:54:10 CEST 2022 +// source: src/main/resources/config/simona-config-template.conf package edu.ie3.simona.config final case class SimonaConfig( - simona: SimonaConfig.Simona + simona : SimonaConfig.Simona ) object SimonaConfig { final case class BaseCsvParams( - override val csvSep: java.lang.String, - override val directoryPath: java.lang.String, - override val isHierarchic: scala.Boolean - ) extends CsvParams(csvSep, directoryPath, isHierarchic) + override val csvSep : java.lang.String, + override val directoryPath : java.lang.String, + override val isHierarchic : scala.Boolean + ) extends CsvParams(csvSep,directoryPath,isHierarchic) object BaseCsvParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.BaseCsvParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.BaseCsvParams = { SimonaConfig.BaseCsvParams( csvSep = $_reqStr(parentPath, c, "csvSep", $tsCfgValidator), - directoryPath = - $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), + directoryPath = $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), isHierarchic = $_reqBln(parentPath, c, "isHierarchic", $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class BaseOutputConfig( - notifier: java.lang.String, - powerRequestReply: scala.Boolean, - simulationResult: scala.Boolean + notifier : java.lang.String, + powerRequestReply : scala.Boolean, + simulationResult : scala.Boolean ) object BaseOutputConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.BaseOutputConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.BaseOutputConfig = { SimonaConfig.BaseOutputConfig( - notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), - powerRequestReply = - $_reqBln(parentPath, c, "powerRequestReply", $tsCfgValidator), - simulationResult = - $_reqBln(parentPath, c, "simulationResult", $tsCfgValidator) + notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), + powerRequestReply = $_reqBln(parentPath, c, "powerRequestReply", $tsCfgValidator), + simulationResult = $_reqBln(parentPath, c, "simulationResult", $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - sealed abstract class BaseRuntimeConfig( - val calculateMissingReactivePowerWithModel: scala.Boolean, - val scaling: scala.Double, - val uuids: scala.List[java.lang.String] + + sealed abstract class BaseRuntimeConfig ( + val calculateMissingReactivePowerWithModel : scala.Boolean, + val scaling : scala.Double, + val uuids : scala.List[java.lang.String] ) extends java.io.Serializable - - sealed abstract class CsvParams( - val csvSep: java.lang.String, - val directoryPath: java.lang.String, - val isHierarchic: scala.Boolean + + sealed abstract class CsvParams ( + val csvSep : java.lang.String, + val directoryPath : java.lang.String, + val isHierarchic : scala.Boolean ) - + final case class EvcsRuntimeConfig( - override val calculateMissingReactivePowerWithModel: scala.Boolean, - override val scaling: scala.Double, - override val uuids: scala.List[java.lang.String] - ) extends BaseRuntimeConfig( - calculateMissingReactivePowerWithModel, - scaling, - uuids - ) + override val calculateMissingReactivePowerWithModel : scala.Boolean, + override val scaling : scala.Double, + override val uuids : scala.List[java.lang.String] + ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) object EvcsRuntimeConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.EvcsRuntimeConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.EvcsRuntimeConfig = { SimonaConfig.EvcsRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln( - parentPath, - c, - "calculateMissingReactivePowerWithModel", - $tsCfgValidator - ), + calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Double = { + + private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getDouble(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class FixedFeedInRuntimeConfig( - override val calculateMissingReactivePowerWithModel: scala.Boolean, - override val scaling: scala.Double, - override val uuids: scala.List[java.lang.String] - ) extends BaseRuntimeConfig( - calculateMissingReactivePowerWithModel, - scaling, - uuids - ) + override val calculateMissingReactivePowerWithModel : scala.Boolean, + override val scaling : scala.Double, + override val uuids : scala.List[java.lang.String] + ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) object FixedFeedInRuntimeConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.FixedFeedInRuntimeConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.FixedFeedInRuntimeConfig = { SimonaConfig.FixedFeedInRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln( - parentPath, - c, - "calculateMissingReactivePowerWithModel", - $tsCfgValidator - ), + calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Double = { + + private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getDouble(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class GridOutputConfig( - lines: scala.Boolean, - nodes: scala.Boolean, - notifier: java.lang.String, - switches: scala.Boolean, - transformers2w: scala.Boolean, - transformers3w: scala.Boolean + lines : scala.Boolean, + nodes : scala.Boolean, + notifier : java.lang.String, + switches : scala.Boolean, + transformers2w : scala.Boolean, + transformers3w : scala.Boolean ) object GridOutputConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.GridOutputConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.GridOutputConfig = { SimonaConfig.GridOutputConfig( - lines = c.hasPathOrNull("lines") && c.getBoolean("lines"), - nodes = c.hasPathOrNull("nodes") && c.getBoolean("nodes"), - notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), - switches = c.hasPathOrNull("switches") && c.getBoolean("switches"), - transformers2w = - c.hasPathOrNull("transformers2w") && c.getBoolean("transformers2w"), - transformers3w = - c.hasPathOrNull("transformers3w") && c.getBoolean("transformers3w") + lines = c.hasPathOrNull("lines") && c.getBoolean("lines"), + nodes = c.hasPathOrNull("nodes") && c.getBoolean("nodes"), + notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), + switches = c.hasPathOrNull("switches") && c.getBoolean("switches"), + transformers2w = c.hasPathOrNull("transformers2w") && c.getBoolean("transformers2w"), + transformers3w = c.hasPathOrNull("transformers3w") && c.getBoolean("transformers3w") ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class LoadRuntimeConfig( - override val calculateMissingReactivePowerWithModel: scala.Boolean, - override val scaling: scala.Double, - override val uuids: scala.List[java.lang.String], - modelBehaviour: java.lang.String, - reference: java.lang.String - ) extends BaseRuntimeConfig( - calculateMissingReactivePowerWithModel, - scaling, - uuids - ) + override val calculateMissingReactivePowerWithModel : scala.Boolean, + override val scaling : scala.Double, + override val uuids : scala.List[java.lang.String], + modelBehaviour : java.lang.String, + reference : java.lang.String + ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) object LoadRuntimeConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.LoadRuntimeConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.LoadRuntimeConfig = { SimonaConfig.LoadRuntimeConfig( - modelBehaviour = - $_reqStr(parentPath, c, "modelBehaviour", $tsCfgValidator), - reference = $_reqStr(parentPath, c, "reference", $tsCfgValidator), - calculateMissingReactivePowerWithModel = $_reqBln( - parentPath, - c, - "calculateMissingReactivePowerWithModel", - $tsCfgValidator - ), - scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), - uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) + modelBehaviour = $_reqStr(parentPath, c, "modelBehaviour", $tsCfgValidator), + reference = $_reqStr(parentPath, c, "reference", $tsCfgValidator), + calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), + scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), + uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Double = { + + private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getDouble(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class PrimaryDataCsvParams( - override val csvSep: java.lang.String, - override val directoryPath: java.lang.String, - override val isHierarchic: scala.Boolean, - timePattern: java.lang.String - ) extends CsvParams(csvSep, directoryPath, isHierarchic) + override val csvSep : java.lang.String, + override val directoryPath : java.lang.String, + override val isHierarchic : scala.Boolean, + timePattern : java.lang.String + ) extends CsvParams(csvSep,directoryPath,isHierarchic) object PrimaryDataCsvParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.PrimaryDataCsvParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.PrimaryDataCsvParams = { SimonaConfig.PrimaryDataCsvParams( - timePattern = - if (c.hasPathOrNull("timePattern")) c.getString("timePattern") - else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - csvSep = $_reqStr(parentPath, c, "csvSep", $tsCfgValidator), - directoryPath = - $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), + timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + csvSep = $_reqStr(parentPath, c, "csvSep", $tsCfgValidator), + directoryPath = $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), isHierarchic = $_reqBln(parentPath, c, "isHierarchic", $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class PvRuntimeConfig( - override val calculateMissingReactivePowerWithModel: scala.Boolean, - override val scaling: scala.Double, - override val uuids: scala.List[java.lang.String] - ) extends BaseRuntimeConfig( - calculateMissingReactivePowerWithModel, - scaling, - uuids - ) + override val calculateMissingReactivePowerWithModel : scala.Boolean, + override val scaling : scala.Double, + override val uuids : scala.List[java.lang.String] + ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) object PvRuntimeConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.PvRuntimeConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.PvRuntimeConfig = { SimonaConfig.PvRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln( - parentPath, - c, - "calculateMissingReactivePowerWithModel", - $tsCfgValidator - ), + calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Double = { + + private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getDouble(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class RefSystemConfig( - gridIds: scala.Option[scala.List[java.lang.String]], - sNom: java.lang.String, - vNom: java.lang.String, - voltLvls: scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] + gridIds : scala.Option[scala.List[java.lang.String]], + sNom : java.lang.String, + vNom : java.lang.String, + voltLvls : scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] ) object RefSystemConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.RefSystemConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.RefSystemConfig = { SimonaConfig.RefSystemConfig( - gridIds = - if (c.hasPathOrNull("gridIds")) - scala.Some( - $_L$_str(c.getList("gridIds"), parentPath, $tsCfgValidator) - ) - else None, - sNom = $_reqStr(parentPath, c, "sNom", $tsCfgValidator), - vNom = $_reqStr(parentPath, c, "vNom", $tsCfgValidator), - voltLvls = - if (c.hasPathOrNull("voltLvls")) - scala.Some( - $_LSimonaConfig_VoltLvlConfig( - c.getList("voltLvls"), - parentPath, - $tsCfgValidator - ) - ) - else None + gridIds = if(c.hasPathOrNull("gridIds")) scala.Some($_L$_str(c.getList("gridIds"), parentPath, $tsCfgValidator)) else None, + sNom = $_reqStr(parentPath, c, "sNom", $tsCfgValidator), + vNom = $_reqStr(parentPath, c, "vNom", $tsCfgValidator), + voltLvls = if(c.hasPathOrNull("voltLvls")) scala.Some($_LSimonaConfig_VoltLvlConfig(c.getList("voltLvls"), parentPath, $tsCfgValidator)) else None ) } - private def $_LSimonaConfig_VoltLvlConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.VoltLvlConfig] = { + private def $_LSimonaConfig_VoltLvlConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.VoltLvlConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.VoltLvlConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.VoltLvlConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class TransformerControlGroup( - measurements: scala.List[java.lang.String], - transformers: scala.List[java.lang.String], - vMax: scala.Double, - vMin: scala.Double + measurements : scala.List[java.lang.String], + transformers : scala.List[java.lang.String], + vMax : scala.Double, + vMin : scala.Double ) object TransformerControlGroup { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.TransformerControlGroup = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.TransformerControlGroup = { SimonaConfig.TransformerControlGroup( - measurements = - $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), - transformers = - $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), - vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), - vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) + measurements = $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), + transformers = $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), + vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), + vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) ) } - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Double = { + private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getDouble(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class VoltLvlConfig( - id: java.lang.String, - vNom: java.lang.String + id : java.lang.String, + vNom : java.lang.String ) object VoltLvlConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.VoltLvlConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.VoltLvlConfig = { SimonaConfig.VoltLvlConfig( - id = $_reqStr(parentPath, c, "id", $tsCfgValidator), + id = $_reqStr(parentPath, c, "id", $tsCfgValidator), vNom = $_reqStr(parentPath, c, "vNom", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class WecRuntimeConfig( - override val calculateMissingReactivePowerWithModel: scala.Boolean, - override val scaling: scala.Double, - override val uuids: scala.List[java.lang.String] - ) extends BaseRuntimeConfig( - calculateMissingReactivePowerWithModel, - scaling, - uuids - ) + override val calculateMissingReactivePowerWithModel : scala.Boolean, + override val scaling : scala.Double, + override val uuids : scala.List[java.lang.String] + ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) object WecRuntimeConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.WecRuntimeConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.WecRuntimeConfig = { SimonaConfig.WecRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln( - parentPath, - c, - "calculateMissingReactivePowerWithModel", - $tsCfgValidator - ), + calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Boolean = { + private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { if (c == null) false - else - try c.getBoolean(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else try c.getBoolean(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Double = { + + private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getDouble(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class Simona( - control: scala.Option[SimonaConfig.Simona.Control], - event: SimonaConfig.Simona.Event, - gridConfig: SimonaConfig.Simona.GridConfig, - input: SimonaConfig.Simona.Input, - output: SimonaConfig.Simona.Output, - powerflow: SimonaConfig.Simona.Powerflow, - runtime: SimonaConfig.Simona.Runtime, - simulationName: java.lang.String, - time: SimonaConfig.Simona.Time + control : scala.Option[SimonaConfig.Simona.Control], + event : SimonaConfig.Simona.Event, + gridConfig : SimonaConfig.Simona.GridConfig, + input : SimonaConfig.Simona.Input, + output : SimonaConfig.Simona.Output, + powerflow : SimonaConfig.Simona.Powerflow, + runtime : SimonaConfig.Simona.Runtime, + simulationName : java.lang.String, + time : SimonaConfig.Simona.Time ) object Simona { final case class Control( - transformer: scala.List[SimonaConfig.TransformerControlGroup] + transformer : scala.List[SimonaConfig.TransformerControlGroup] ) object Control { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Control = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Control = { SimonaConfig.Simona.Control( - transformer = $_LSimonaConfig_TransformerControlGroup( - c.getList("transformer"), - parentPath, - $tsCfgValidator - ) + transformer = $_LSimonaConfig_TransformerControlGroup(c.getList("transformer"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_TransformerControlGroup( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.TransformerControlGroup] = { + private def $_LSimonaConfig_TransformerControlGroup(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.TransformerControlGroup] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.TransformerControlGroup( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.TransformerControlGroup(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class Event( - listener: scala.Option[ - scala.List[SimonaConfig.Simona.Event.Listener$Elm] - ] + listener : scala.Option[scala.List[SimonaConfig.Simona.Event.Listener$Elm]] ) object Event { final case class Listener$Elm( - eventsToProcess: scala.Option[scala.List[java.lang.String]], - fullClassPath: java.lang.String + eventsToProcess : scala.Option[scala.List[java.lang.String]], + fullClassPath : java.lang.String ) object Listener$Elm { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Event.Listener$Elm = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Event.Listener$Elm = { SimonaConfig.Simona.Event.Listener$Elm( - eventsToProcess = - if (c.hasPathOrNull("eventsToProcess")) - scala.Some( - $_L$_str( - c.getList("eventsToProcess"), - parentPath, - $tsCfgValidator - ) - ) - else None, - fullClassPath = - $_reqStr(parentPath, c, "fullClassPath", $tsCfgValidator) + eventsToProcess = if(c.hasPathOrNull("eventsToProcess")) scala.Some($_L$_str(c.getList("eventsToProcess"), parentPath, $tsCfgValidator)) else None, + fullClassPath = $_reqStr(parentPath, c, "fullClassPath", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Event = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Event = { SimonaConfig.Simona.Event( - listener = - if (c.hasPathOrNull("listener")) - scala.Some( - $_LSimonaConfig_Simona_Event_Listener$Elm( - c.getList("listener"), - parentPath, - $tsCfgValidator - ) - ) - else None + listener = if(c.hasPathOrNull("listener")) scala.Some($_LSimonaConfig_Simona_Event_Listener$Elm(c.getList("listener"), parentPath, $tsCfgValidator)) else None ) } - private def $_LSimonaConfig_Simona_Event_Listener$Elm( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.Simona.Event.Listener$Elm] = { + private def $_LSimonaConfig_Simona_Event_Listener$Elm(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.Simona.Event.Listener$Elm] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.Simona.Event.Listener$Elm( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.Simona.Event.Listener$Elm(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class GridConfig( - refSystems: scala.List[SimonaConfig.RefSystemConfig] + refSystems : scala.List[SimonaConfig.RefSystemConfig] ) object GridConfig { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.GridConfig = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.GridConfig = { SimonaConfig.Simona.GridConfig( - refSystems = $_LSimonaConfig_RefSystemConfig( - c.getList("refSystems"), - parentPath, - $tsCfgValidator - ) + refSystems = $_LSimonaConfig_RefSystemConfig(c.getList("refSystems"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_RefSystemConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.RefSystemConfig] = { + private def $_LSimonaConfig_RefSystemConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.RefSystemConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.RefSystemConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.RefSystemConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class Input( - grid: SimonaConfig.Simona.Input.Grid, - primary: SimonaConfig.Simona.Input.Primary, - weather: SimonaConfig.Simona.Input.Weather + grid : SimonaConfig.Simona.Input.Grid, + primary : SimonaConfig.Simona.Input.Primary, + weather : SimonaConfig.Simona.Input.Weather ) object Input { final case class Grid( - datasource: SimonaConfig.Simona.Input.Grid.Datasource + datasource : SimonaConfig.Simona.Input.Grid.Datasource ) object Grid { final case class Datasource( - csvParams: scala.Option[SimonaConfig.BaseCsvParams], - id: java.lang.String + csvParams : scala.Option[SimonaConfig.BaseCsvParams], + id : java.lang.String ) object Datasource { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Grid.Datasource = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Grid.Datasource = { SimonaConfig.Simona.Input.Grid.Datasource( - csvParams = - if (c.hasPathOrNull("csvParams")) - scala.Some( - SimonaConfig.BaseCsvParams( - c.getConfig("csvParams"), - parentPath + "csvParams.", - $tsCfgValidator - ) - ) - else None, - id = $_reqStr(parentPath, c, "id", $tsCfgValidator) + csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.BaseCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, + id = $_reqStr(parentPath, c, "id", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Grid = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Grid = { SimonaConfig.Simona.Input.Grid( - datasource = SimonaConfig.Simona.Input.Grid.Datasource( - if (c.hasPathOrNull("datasource")) c.getConfig("datasource") - else - com.typesafe.config.ConfigFactory.parseString("datasource{}"), - parentPath + "datasource.", - $tsCfgValidator - ) + datasource = SimonaConfig.Simona.Input.Grid.Datasource(if(c.hasPathOrNull("datasource")) c.getConfig("datasource") else com.typesafe.config.ConfigFactory.parseString("datasource{}"), parentPath + "datasource.", $tsCfgValidator) ) } } - + final case class Primary( - couchbaseParams: scala.Option[ - SimonaConfig.Simona.Input.Primary.CouchbaseParams - ], - csvParams: scala.Option[SimonaConfig.PrimaryDataCsvParams], - influxDb1xParams: scala.Option[ - SimonaConfig.Simona.Input.Primary.InfluxDb1xParams - ], - sqlParams: scala.Option[SimonaConfig.Simona.Input.Primary.SqlParams] + couchbaseParams : scala.Option[SimonaConfig.Simona.Input.Primary.CouchbaseParams], + csvParams : scala.Option[SimonaConfig.PrimaryDataCsvParams], + influxDb1xParams : scala.Option[SimonaConfig.Simona.Input.Primary.InfluxDb1xParams], + sqlParams : scala.Option[SimonaConfig.Simona.Input.Primary.SqlParams] ) object Primary { final case class CouchbaseParams( - bucketName: java.lang.String, - coordinateColumnName: java.lang.String, - keyPrefix: java.lang.String, - password: java.lang.String, - timePattern: java.lang.String, - url: java.lang.String, - userName: java.lang.String + bucketName : java.lang.String, + coordinateColumnName : java.lang.String, + keyPrefix : java.lang.String, + password : java.lang.String, + timePattern : java.lang.String, + url : java.lang.String, + userName : java.lang.String ) object CouchbaseParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Primary.CouchbaseParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary.CouchbaseParams = { SimonaConfig.Simona.Input.Primary.CouchbaseParams( - bucketName = - $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), - coordinateColumnName = $_reqStr( - parentPath, - c, - "coordinateColumnName", - $tsCfgValidator - ), - keyPrefix = $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - timePattern = - if (c.hasPathOrNull("timePattern")) c.getString("timePattern") - else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - url = $_reqStr(parentPath, c, "url", $tsCfgValidator), - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + bucketName = $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), + coordinateColumnName = $_reqStr(parentPath, c, "coordinateColumnName", $tsCfgValidator), + keyPrefix = $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + url = $_reqStr(parentPath, c, "url", $tsCfgValidator), + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class InfluxDb1xParams( - database: java.lang.String, - port: scala.Int, - timePattern: java.lang.String, - url: java.lang.String + database : java.lang.String, + port : scala.Int, + timePattern : java.lang.String, + url : java.lang.String ) object InfluxDb1xParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Primary.InfluxDb1xParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary.InfluxDb1xParams = { SimonaConfig.Simona.Input.Primary.InfluxDb1xParams( - database = $_reqStr(parentPath, c, "database", $tsCfgValidator), - port = $_reqInt(parentPath, c, "port", $tsCfgValidator), - timePattern = - if (c.hasPathOrNull("timePattern")) c.getString("timePattern") - else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - url = $_reqStr(parentPath, c, "url", $tsCfgValidator) + database = $_reqStr(parentPath, c, "database", $tsCfgValidator), + port = $_reqInt(parentPath, c, "port", $tsCfgValidator), + timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + url = $_reqStr(parentPath, c, "url", $tsCfgValidator) ) } - private def $_reqInt( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Int = { + private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { if (c == null) 0 - else - try c.getInt(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getInt(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class SqlParams( - jdbcUrl: java.lang.String, - password: java.lang.String, - schemaName: java.lang.String, - timePattern: java.lang.String, - userName: java.lang.String + jdbcUrl : java.lang.String, + password : java.lang.String, + schemaName : java.lang.String, + timePattern : java.lang.String, + userName : java.lang.String ) object SqlParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Primary.SqlParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary.SqlParams = { SimonaConfig.Simona.Input.Primary.SqlParams( - jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - schemaName = - if (c.hasPathOrNull("schemaName")) c.getString("schemaName") - else "public", - timePattern = - if (c.hasPathOrNull("timePattern")) c.getString("timePattern") - else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + schemaName = if(c.hasPathOrNull("schemaName")) c.getString("schemaName") else "public", + timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Primary = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary = { SimonaConfig.Simona.Input.Primary( - couchbaseParams = - if (c.hasPathOrNull("couchbaseParams")) - scala.Some( - SimonaConfig.Simona.Input.Primary.CouchbaseParams( - c.getConfig("couchbaseParams"), - parentPath + "couchbaseParams.", - $tsCfgValidator - ) - ) - else None, - csvParams = - if (c.hasPathOrNull("csvParams")) - scala.Some( - SimonaConfig.PrimaryDataCsvParams( - c.getConfig("csvParams"), - parentPath + "csvParams.", - $tsCfgValidator - ) - ) - else None, - influxDb1xParams = - if (c.hasPathOrNull("influxDb1xParams")) - scala.Some( - SimonaConfig.Simona.Input.Primary.InfluxDb1xParams( - c.getConfig("influxDb1xParams"), - parentPath + "influxDb1xParams.", - $tsCfgValidator - ) - ) - else None, - sqlParams = - if (c.hasPathOrNull("sqlParams")) - scala.Some( - SimonaConfig.Simona.Input.Primary.SqlParams( - c.getConfig("sqlParams"), - parentPath + "sqlParams.", - $tsCfgValidator - ) - ) - else None + couchbaseParams = if(c.hasPathOrNull("couchbaseParams")) scala.Some(SimonaConfig.Simona.Input.Primary.CouchbaseParams(c.getConfig("couchbaseParams"), parentPath + "couchbaseParams.", $tsCfgValidator)) else None, + csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.PrimaryDataCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, + influxDb1xParams = if(c.hasPathOrNull("influxDb1xParams")) scala.Some(SimonaConfig.Simona.Input.Primary.InfluxDb1xParams(c.getConfig("influxDb1xParams"), parentPath + "influxDb1xParams.", $tsCfgValidator)) else None, + sqlParams = if(c.hasPathOrNull("sqlParams")) scala.Some(SimonaConfig.Simona.Input.Primary.SqlParams(c.getConfig("sqlParams"), parentPath + "sqlParams.", $tsCfgValidator)) else None ) } } - + final case class Weather( - datasource: SimonaConfig.Simona.Input.Weather.Datasource + datasource : SimonaConfig.Simona.Input.Weather.Datasource ) object Weather { final case class Datasource( - coordinateSource: SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource, - couchbaseParams: scala.Option[ - SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams - ], - csvParams: scala.Option[SimonaConfig.BaseCsvParams], - influxDb1xParams: scala.Option[ - SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams - ], - resolution: scala.Option[scala.Long], - sampleParams: scala.Option[ - SimonaConfig.Simona.Input.Weather.Datasource.SampleParams - ], - scheme: java.lang.String, - sqlParams: scala.Option[ - SimonaConfig.Simona.Input.Weather.Datasource.SqlParams - ], - timestampPattern: scala.Option[java.lang.String] + coordinateSource : SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource, + couchbaseParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams], + csvParams : scala.Option[SimonaConfig.BaseCsvParams], + influxDb1xParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams], + resolution : scala.Option[scala.Long], + sampleParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.SampleParams], + scheme : java.lang.String, + sqlParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.SqlParams], + timestampPattern : scala.Option[java.lang.String] ) object Datasource { final case class CoordinateSource( - csvParams: scala.Option[SimonaConfig.BaseCsvParams], - gridModel: java.lang.String, - sampleParams: scala.Option[ - SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams - ] + csvParams : scala.Option[SimonaConfig.BaseCsvParams], + gridModel : java.lang.String, + sampleParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams] ) object CoordinateSource { final case class SampleParams( - use: scala.Boolean + use : scala.Boolean ) object SampleParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams = { - SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource - .SampleParams( - use = !c.hasPathOrNull("use") || c.getBoolean("use") - ) + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams = { + SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams( + use = !c.hasPathOrNull("use") || c.getBoolean("use") + ) } } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource = { SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource( - csvParams = - if (c.hasPathOrNull("csvParams")) - scala.Some( - SimonaConfig.BaseCsvParams( - c.getConfig("csvParams"), - parentPath + "csvParams.", - $tsCfgValidator - ) - ) - else None, - gridModel = - if (c.hasPathOrNull("gridModel")) c.getString("gridModel") - else "icon", - sampleParams = - if (c.hasPathOrNull("sampleParams")) - scala.Some( - SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource - .SampleParams( - c.getConfig("sampleParams"), - parentPath + "sampleParams.", - $tsCfgValidator - ) - ) - else None + csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.BaseCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, + gridModel = if(c.hasPathOrNull("gridModel")) c.getString("gridModel") else "icon", + sampleParams = if(c.hasPathOrNull("sampleParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams(c.getConfig("sampleParams"), parentPath + "sampleParams.", $tsCfgValidator)) else None ) } } - + final case class CouchbaseParams( - bucketName: java.lang.String, - coordinateColumnName: java.lang.String, - keyPrefix: java.lang.String, - password: java.lang.String, - url: java.lang.String, - userName: java.lang.String + bucketName : java.lang.String, + coordinateColumnName : java.lang.String, + keyPrefix : java.lang.String, + password : java.lang.String, + url : java.lang.String, + userName : java.lang.String ) object CouchbaseParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams = { SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams( - bucketName = - $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), - coordinateColumnName = $_reqStr( - parentPath, - c, - "coordinateColumnName", - $tsCfgValidator - ), - keyPrefix = - $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - url = $_reqStr(parentPath, c, "url", $tsCfgValidator), - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + bucketName = $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), + coordinateColumnName = $_reqStr(parentPath, c, "coordinateColumnName", $tsCfgValidator), + keyPrefix = $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + url = $_reqStr(parentPath, c, "url", $tsCfgValidator), + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class InfluxDb1xParams( - database: java.lang.String, - port: scala.Int, - url: java.lang.String + database : java.lang.String, + port : scala.Int, + url : java.lang.String ) object InfluxDb1xParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams = { SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams( database = $_reqStr(parentPath, c, "database", $tsCfgValidator), - port = $_reqInt(parentPath, c, "port", $tsCfgValidator), - url = $_reqStr(parentPath, c, "url", $tsCfgValidator) + port = $_reqInt(parentPath, c, "port", $tsCfgValidator), + url = $_reqStr(parentPath, c, "url", $tsCfgValidator) ) } - private def $_reqInt( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Int = { + private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { if (c == null) 0 - else - try c.getInt(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getInt(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class SampleParams( - use: scala.Boolean + use : scala.Boolean ) object SampleParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather.Datasource.SampleParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.SampleParams = { SimonaConfig.Simona.Input.Weather.Datasource.SampleParams( use = !c.hasPathOrNull("use") || c.getBoolean("use") ) } } - + final case class SqlParams( - jdbcUrl: java.lang.String, - password: java.lang.String, - schemaName: java.lang.String, - tableName: java.lang.String, - userName: java.lang.String + jdbcUrl : java.lang.String, + password : java.lang.String, + schemaName : java.lang.String, + tableName : java.lang.String, + userName : java.lang.String ) object SqlParams { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather.Datasource.SqlParams = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.SqlParams = { SimonaConfig.Simona.Input.Weather.Datasource.SqlParams( - jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - schemaName = - if (c.hasPathOrNull("schemaName")) c.getString("schemaName") - else "public", - tableName = - $_reqStr(parentPath, c, "tableName", $tsCfgValidator), - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + schemaName = if(c.hasPathOrNull("schemaName")) c.getString("schemaName") else "public", + tableName = $_reqStr(parentPath, c, "tableName", $tsCfgValidator), + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather.Datasource = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource = { SimonaConfig.Simona.Input.Weather.Datasource( - coordinateSource = - SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource( - if (c.hasPathOrNull("coordinateSource")) - c.getConfig("coordinateSource") - else - com.typesafe.config.ConfigFactory - .parseString("coordinateSource{}"), - parentPath + "coordinateSource.", - $tsCfgValidator - ), - couchbaseParams = - if (c.hasPathOrNull("couchbaseParams")) - scala.Some( - SimonaConfig.Simona.Input.Weather.Datasource - .CouchbaseParams( - c.getConfig("couchbaseParams"), - parentPath + "couchbaseParams.", - $tsCfgValidator - ) - ) - else None, - csvParams = - if (c.hasPathOrNull("csvParams")) - scala.Some( - SimonaConfig.BaseCsvParams( - c.getConfig("csvParams"), - parentPath + "csvParams.", - $tsCfgValidator - ) - ) - else None, - influxDb1xParams = - if (c.hasPathOrNull("influxDb1xParams")) - scala.Some( - SimonaConfig.Simona.Input.Weather.Datasource - .InfluxDb1xParams( - c.getConfig("influxDb1xParams"), - parentPath + "influxDb1xParams.", - $tsCfgValidator - ) - ) - else None, - resolution = - if (c.hasPathOrNull("resolution")) - Some(c.getLong("resolution").longValue()) - else None, - sampleParams = - if (c.hasPathOrNull("sampleParams")) - scala.Some( - SimonaConfig.Simona.Input.Weather.Datasource.SampleParams( - c.getConfig("sampleParams"), - parentPath + "sampleParams.", - $tsCfgValidator - ) - ) - else None, - scheme = - if (c.hasPathOrNull("scheme")) c.getString("scheme") - else "icon", - sqlParams = - if (c.hasPathOrNull("sqlParams")) - scala.Some( - SimonaConfig.Simona.Input.Weather.Datasource.SqlParams( - c.getConfig("sqlParams"), - parentPath + "sqlParams.", - $tsCfgValidator - ) - ) - else None, - timestampPattern = - if (c.hasPathOrNull("timestampPattern")) - Some(c.getString("timestampPattern")) - else None + coordinateSource = SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource(if(c.hasPathOrNull("coordinateSource")) c.getConfig("coordinateSource") else com.typesafe.config.ConfigFactory.parseString("coordinateSource{}"), parentPath + "coordinateSource.", $tsCfgValidator), + couchbaseParams = if(c.hasPathOrNull("couchbaseParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams(c.getConfig("couchbaseParams"), parentPath + "couchbaseParams.", $tsCfgValidator)) else None, + csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.BaseCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, + influxDb1xParams = if(c.hasPathOrNull("influxDb1xParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams(c.getConfig("influxDb1xParams"), parentPath + "influxDb1xParams.", $tsCfgValidator)) else None, + resolution = if(c.hasPathOrNull("resolution")) Some(c.getLong("resolution").longValue()) else None, + sampleParams = if(c.hasPathOrNull("sampleParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.SampleParams(c.getConfig("sampleParams"), parentPath + "sampleParams.", $tsCfgValidator)) else None, + scheme = if(c.hasPathOrNull("scheme")) c.getString("scheme") else "icon", + sqlParams = if(c.hasPathOrNull("sqlParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.SqlParams(c.getConfig("sqlParams"), parentPath + "sqlParams.", $tsCfgValidator)) else None, + timestampPattern = if(c.hasPathOrNull("timestampPattern")) Some(c.getString("timestampPattern")) else None ) } } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input.Weather = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather = { SimonaConfig.Simona.Input.Weather( - datasource = SimonaConfig.Simona.Input.Weather.Datasource( - if (c.hasPathOrNull("datasource")) c.getConfig("datasource") - else - com.typesafe.config.ConfigFactory.parseString("datasource{}"), - parentPath + "datasource.", - $tsCfgValidator - ) + datasource = SimonaConfig.Simona.Input.Weather.Datasource(if(c.hasPathOrNull("datasource")) c.getConfig("datasource") else com.typesafe.config.ConfigFactory.parseString("datasource{}"), parentPath + "datasource.", $tsCfgValidator) ) } } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Input = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input = { SimonaConfig.Simona.Input( - grid = SimonaConfig.Simona.Input.Grid( - if (c.hasPathOrNull("grid")) c.getConfig("grid") - else com.typesafe.config.ConfigFactory.parseString("grid{}"), - parentPath + "grid.", - $tsCfgValidator - ), - primary = SimonaConfig.Simona.Input.Primary( - if (c.hasPathOrNull("primary")) c.getConfig("primary") - else com.typesafe.config.ConfigFactory.parseString("primary{}"), - parentPath + "primary.", - $tsCfgValidator - ), - weather = SimonaConfig.Simona.Input.Weather( - if (c.hasPathOrNull("weather")) c.getConfig("weather") - else com.typesafe.config.ConfigFactory.parseString("weather{}"), - parentPath + "weather.", - $tsCfgValidator - ) + grid = SimonaConfig.Simona.Input.Grid(if(c.hasPathOrNull("grid")) c.getConfig("grid") else com.typesafe.config.ConfigFactory.parseString("grid{}"), parentPath + "grid.", $tsCfgValidator), + primary = SimonaConfig.Simona.Input.Primary(if(c.hasPathOrNull("primary")) c.getConfig("primary") else com.typesafe.config.ConfigFactory.parseString("primary{}"), parentPath + "primary.", $tsCfgValidator), + weather = SimonaConfig.Simona.Input.Weather(if(c.hasPathOrNull("weather")) c.getConfig("weather") else com.typesafe.config.ConfigFactory.parseString("weather{}"), parentPath + "weather.", $tsCfgValidator) ) } } - + final case class Output( - base: SimonaConfig.Simona.Output.Base, - grid: SimonaConfig.GridOutputConfig, - participant: SimonaConfig.Simona.Output.Participant, - sink: SimonaConfig.Simona.Output.Sink + base : SimonaConfig.Simona.Output.Base, + grid : SimonaConfig.GridOutputConfig, + participant : SimonaConfig.Simona.Output.Participant, + sink : SimonaConfig.Simona.Output.Sink ) object Output { final case class Base( - addTimestampToOutputDir: scala.Boolean, - dir: java.lang.String + addTimestampToOutputDir : scala.Boolean, + dir : java.lang.String ) object Base { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Output.Base = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Base = { SimonaConfig.Simona.Output.Base( - addTimestampToOutputDir = !c.hasPathOrNull( - "addTimestampToOutputDir" - ) || c.getBoolean("addTimestampToOutputDir"), - dir = $_reqStr(parentPath, c, "dir", $tsCfgValidator) + addTimestampToOutputDir = !c.hasPathOrNull("addTimestampToOutputDir") || c.getBoolean("addTimestampToOutputDir"), + dir = $_reqStr(parentPath, c, "dir", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class Participant( - defaultConfig: SimonaConfig.BaseOutputConfig, - individualConfigs: scala.List[SimonaConfig.BaseOutputConfig] + defaultConfig : SimonaConfig.BaseOutputConfig, + individualConfigs : scala.List[SimonaConfig.BaseOutputConfig] ) object Participant { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Output.Participant = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Participant = { SimonaConfig.Simona.Output.Participant( - defaultConfig = SimonaConfig.BaseOutputConfig( - if (c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") - else - com.typesafe.config.ConfigFactory - .parseString("defaultConfig{}"), - parentPath + "defaultConfig.", - $tsCfgValidator - ), - individualConfigs = $_LSimonaConfig_BaseOutputConfig( - c.getList("individualConfigs"), - parentPath, - $tsCfgValidator - ) + defaultConfig = SimonaConfig.BaseOutputConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), + individualConfigs = $_LSimonaConfig_BaseOutputConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_BaseOutputConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.BaseOutputConfig] = { + private def $_LSimonaConfig_BaseOutputConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.BaseOutputConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.BaseOutputConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.BaseOutputConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class Sink( - csv: scala.Option[SimonaConfig.Simona.Output.Sink.Csv], - influxDb1x: scala.Option[SimonaConfig.Simona.Output.Sink.InfluxDb1x] + csv : scala.Option[SimonaConfig.Simona.Output.Sink.Csv], + influxDb1x : scala.Option[SimonaConfig.Simona.Output.Sink.InfluxDb1x] ) object Sink { final case class Csv( - fileFormat: java.lang.String, - filePrefix: java.lang.String, - fileSuffix: java.lang.String, - isHierarchic: scala.Boolean + fileFormat : java.lang.String, + filePrefix : java.lang.String, + fileSuffix : java.lang.String, + isHierarchic : scala.Boolean ) object Csv { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Output.Sink.Csv = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Sink.Csv = { SimonaConfig.Simona.Output.Sink.Csv( - fileFormat = - if (c.hasPathOrNull("fileFormat")) c.getString("fileFormat") - else ".csv", - filePrefix = - if (c.hasPathOrNull("filePrefix")) c.getString("filePrefix") - else "", - fileSuffix = - if (c.hasPathOrNull("fileSuffix")) c.getString("fileSuffix") - else "", - isHierarchic = - c.hasPathOrNull("isHierarchic") && c.getBoolean("isHierarchic") + fileFormat = if(c.hasPathOrNull("fileFormat")) c.getString("fileFormat") else ".csv", + filePrefix = if(c.hasPathOrNull("filePrefix")) c.getString("filePrefix") else "", + fileSuffix = if(c.hasPathOrNull("fileSuffix")) c.getString("fileSuffix") else "", + isHierarchic = c.hasPathOrNull("isHierarchic") && c.getBoolean("isHierarchic") ) } } - + final case class InfluxDb1x( - database: java.lang.String, - port: scala.Int, - url: java.lang.String + database : java.lang.String, + port : scala.Int, + url : java.lang.String ) object InfluxDb1x { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Output.Sink.InfluxDb1x = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Sink.InfluxDb1x = { SimonaConfig.Simona.Output.Sink.InfluxDb1x( database = $_reqStr(parentPath, c, "database", $tsCfgValidator), - port = $_reqInt(parentPath, c, "port", $tsCfgValidator), - url = $_reqStr(parentPath, c, "url", $tsCfgValidator) + port = $_reqInt(parentPath, c, "port", $tsCfgValidator), + url = $_reqStr(parentPath, c, "url", $tsCfgValidator) ) } - private def $_reqInt( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Int = { + private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { if (c == null) 0 - else - try c.getInt(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getInt(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Output.Sink = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Sink = { SimonaConfig.Simona.Output.Sink( - csv = - if (c.hasPathOrNull("csv")) - scala.Some( - SimonaConfig.Simona.Output.Sink.Csv( - c.getConfig("csv"), - parentPath + "csv.", - $tsCfgValidator - ) - ) - else None, - influxDb1x = - if (c.hasPathOrNull("influxDb1x")) - scala.Some( - SimonaConfig.Simona.Output.Sink.InfluxDb1x( - c.getConfig("influxDb1x"), - parentPath + "influxDb1x.", - $tsCfgValidator - ) - ) - else None + csv = if(c.hasPathOrNull("csv")) scala.Some(SimonaConfig.Simona.Output.Sink.Csv(c.getConfig("csv"), parentPath + "csv.", $tsCfgValidator)) else None, + influxDb1x = if(c.hasPathOrNull("influxDb1x")) scala.Some(SimonaConfig.Simona.Output.Sink.InfluxDb1x(c.getConfig("influxDb1x"), parentPath + "influxDb1x.", $tsCfgValidator)) else None ) } } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Output = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output = { SimonaConfig.Simona.Output( - base = SimonaConfig.Simona.Output.Base( - if (c.hasPathOrNull("base")) c.getConfig("base") - else com.typesafe.config.ConfigFactory.parseString("base{}"), - parentPath + "base.", - $tsCfgValidator - ), - grid = SimonaConfig.GridOutputConfig( - if (c.hasPathOrNull("grid")) c.getConfig("grid") - else com.typesafe.config.ConfigFactory.parseString("grid{}"), - parentPath + "grid.", - $tsCfgValidator - ), - participant = SimonaConfig.Simona.Output.Participant( - if (c.hasPathOrNull("participant")) c.getConfig("participant") - else com.typesafe.config.ConfigFactory.parseString("participant{}"), - parentPath + "participant.", - $tsCfgValidator - ), - sink = SimonaConfig.Simona.Output.Sink( - if (c.hasPathOrNull("sink")) c.getConfig("sink") - else com.typesafe.config.ConfigFactory.parseString("sink{}"), - parentPath + "sink.", - $tsCfgValidator - ) + base = SimonaConfig.Simona.Output.Base(if(c.hasPathOrNull("base")) c.getConfig("base") else com.typesafe.config.ConfigFactory.parseString("base{}"), parentPath + "base.", $tsCfgValidator), + grid = SimonaConfig.GridOutputConfig(if(c.hasPathOrNull("grid")) c.getConfig("grid") else com.typesafe.config.ConfigFactory.parseString("grid{}"), parentPath + "grid.", $tsCfgValidator), + participant = SimonaConfig.Simona.Output.Participant(if(c.hasPathOrNull("participant")) c.getConfig("participant") else com.typesafe.config.ConfigFactory.parseString("participant{}"), parentPath + "participant.", $tsCfgValidator), + sink = SimonaConfig.Simona.Output.Sink(if(c.hasPathOrNull("sink")) c.getConfig("sink") else com.typesafe.config.ConfigFactory.parseString("sink{}"), parentPath + "sink.", $tsCfgValidator) ) } } - + final case class Powerflow( - maxSweepPowerDeviation: scala.Double, - newtonraphson: SimonaConfig.Simona.Powerflow.Newtonraphson, - resolution: java.time.Duration, - sweepTimeout: java.time.Duration + maxSweepPowerDeviation : scala.Double, + newtonraphson : SimonaConfig.Simona.Powerflow.Newtonraphson, + resolution : java.time.Duration, + sweepTimeout : java.time.Duration ) object Powerflow { final case class Newtonraphson( - epsilon: scala.List[scala.Double], - iterations: scala.Int + epsilon : scala.List[scala.Double], + iterations : scala.Int ) object Newtonraphson { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Powerflow.Newtonraphson = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Powerflow.Newtonraphson = { SimonaConfig.Simona.Powerflow.Newtonraphson( - epsilon = - $_L$_dbl(c.getList("epsilon"), parentPath, $tsCfgValidator), + epsilon = $_L$_dbl(c.getList("epsilon"), parentPath, $tsCfgValidator), iterations = $_reqInt(parentPath, c, "iterations", $tsCfgValidator) ) } - private def $_reqInt( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Int = { + private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { if (c == null) 0 - else - try c.getInt(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getInt(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Powerflow = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Powerflow = { SimonaConfig.Simona.Powerflow( - maxSweepPowerDeviation = - $_reqDbl(parentPath, c, "maxSweepPowerDeviation", $tsCfgValidator), - newtonraphson = SimonaConfig.Simona.Powerflow.Newtonraphson( - if (c.hasPathOrNull("newtonraphson")) c.getConfig("newtonraphson") - else - com.typesafe.config.ConfigFactory.parseString("newtonraphson{}"), - parentPath + "newtonraphson.", - $tsCfgValidator - ), - resolution = - if (c.hasPathOrNull("resolution")) c.getDuration("resolution") - else java.time.Duration.parse("PT1H"), - sweepTimeout = - if (c.hasPathOrNull("sweepTimeout")) c.getDuration("sweepTimeout") - else java.time.Duration.parse("PT30S") + maxSweepPowerDeviation = $_reqDbl(parentPath, c, "maxSweepPowerDeviation", $tsCfgValidator), + newtonraphson = SimonaConfig.Simona.Powerflow.Newtonraphson(if(c.hasPathOrNull("newtonraphson")) c.getConfig("newtonraphson") else com.typesafe.config.ConfigFactory.parseString("newtonraphson{}"), parentPath + "newtonraphson.", $tsCfgValidator), + resolution = if(c.hasPathOrNull("resolution")) c.getDuration("resolution") else java.time.Duration.parse("PT1H"), + sweepTimeout = if(c.hasPathOrNull("sweepTimeout")) c.getDuration("sweepTimeout") else java.time.Duration.parse("PT30S") ) } - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.Double = { + private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else try c.getDouble(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class Runtime( - participant: SimonaConfig.Simona.Runtime.Participant, - selected_subgrids: scala.Option[scala.List[scala.Int]], - selected_volt_lvls: scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] + participant : SimonaConfig.Simona.Runtime.Participant, + selected_subgrids : scala.Option[scala.List[scala.Int]], + selected_volt_lvls : scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] ) object Runtime { final case class Participant( - evcs: SimonaConfig.Simona.Runtime.Participant.Evcs, - fixedFeedIn: SimonaConfig.Simona.Runtime.Participant.FixedFeedIn, - load: SimonaConfig.Simona.Runtime.Participant.Load, - pv: SimonaConfig.Simona.Runtime.Participant.Pv, - requestVoltageDeviationThreshold: scala.Double, - wec: SimonaConfig.Simona.Runtime.Participant.Wec + evcs : SimonaConfig.Simona.Runtime.Participant.Evcs, + fixedFeedIn : SimonaConfig.Simona.Runtime.Participant.FixedFeedIn, + load : SimonaConfig.Simona.Runtime.Participant.Load, + pv : SimonaConfig.Simona.Runtime.Participant.Pv, + requestVoltageDeviationThreshold : scala.Double, + wec : SimonaConfig.Simona.Runtime.Participant.Wec ) object Participant { final case class Evcs( - defaultConfig: SimonaConfig.EvcsRuntimeConfig, - individualConfigs: scala.List[SimonaConfig.EvcsRuntimeConfig] + defaultConfig : SimonaConfig.EvcsRuntimeConfig, + individualConfigs : scala.List[SimonaConfig.EvcsRuntimeConfig] ) object Evcs { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Runtime.Participant.Evcs = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Evcs = { SimonaConfig.Simona.Runtime.Participant.Evcs( - defaultConfig = SimonaConfig.EvcsRuntimeConfig( - if (c.hasPathOrNull("defaultConfig")) - c.getConfig("defaultConfig") - else - com.typesafe.config.ConfigFactory - .parseString("defaultConfig{}"), - parentPath + "defaultConfig.", - $tsCfgValidator - ), - individualConfigs = $_LSimonaConfig_EvcsRuntimeConfig( - c.getList("individualConfigs"), - parentPath, - $tsCfgValidator - ) + defaultConfig = SimonaConfig.EvcsRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), + individualConfigs = $_LSimonaConfig_EvcsRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_EvcsRuntimeConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.EvcsRuntimeConfig] = { + private def $_LSimonaConfig_EvcsRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.EvcsRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.EvcsRuntimeConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.EvcsRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class FixedFeedIn( - defaultConfig: SimonaConfig.FixedFeedInRuntimeConfig, - individualConfigs: scala.List[SimonaConfig.FixedFeedInRuntimeConfig] + defaultConfig : SimonaConfig.FixedFeedInRuntimeConfig, + individualConfigs : scala.List[SimonaConfig.FixedFeedInRuntimeConfig] ) object FixedFeedIn { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Runtime.Participant.FixedFeedIn = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.FixedFeedIn = { SimonaConfig.Simona.Runtime.Participant.FixedFeedIn( - defaultConfig = SimonaConfig.FixedFeedInRuntimeConfig( - if (c.hasPathOrNull("defaultConfig")) - c.getConfig("defaultConfig") - else - com.typesafe.config.ConfigFactory - .parseString("defaultConfig{}"), - parentPath + "defaultConfig.", - $tsCfgValidator - ), - individualConfigs = $_LSimonaConfig_FixedFeedInRuntimeConfig( - c.getList("individualConfigs"), - parentPath, - $tsCfgValidator - ) + defaultConfig = SimonaConfig.FixedFeedInRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), + individualConfigs = $_LSimonaConfig_FixedFeedInRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_FixedFeedInRuntimeConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.FixedFeedInRuntimeConfig] = { + private def $_LSimonaConfig_FixedFeedInRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.FixedFeedInRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.FixedFeedInRuntimeConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.FixedFeedInRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class Load( - defaultConfig: SimonaConfig.LoadRuntimeConfig, - individualConfigs: scala.List[SimonaConfig.LoadRuntimeConfig] + defaultConfig : SimonaConfig.LoadRuntimeConfig, + individualConfigs : scala.List[SimonaConfig.LoadRuntimeConfig] ) object Load { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Runtime.Participant.Load = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Load = { SimonaConfig.Simona.Runtime.Participant.Load( - defaultConfig = SimonaConfig.LoadRuntimeConfig( - if (c.hasPathOrNull("defaultConfig")) - c.getConfig("defaultConfig") - else - com.typesafe.config.ConfigFactory - .parseString("defaultConfig{}"), - parentPath + "defaultConfig.", - $tsCfgValidator - ), - individualConfigs = $_LSimonaConfig_LoadRuntimeConfig( - c.getList("individualConfigs"), - parentPath, - $tsCfgValidator - ) + defaultConfig = SimonaConfig.LoadRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), + individualConfigs = $_LSimonaConfig_LoadRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_LoadRuntimeConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.LoadRuntimeConfig] = { + private def $_LSimonaConfig_LoadRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.LoadRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.LoadRuntimeConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.LoadRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class Pv( - defaultConfig: SimonaConfig.PvRuntimeConfig, - individualConfigs: scala.List[SimonaConfig.PvRuntimeConfig] + defaultConfig : SimonaConfig.PvRuntimeConfig, + individualConfigs : scala.List[SimonaConfig.PvRuntimeConfig] ) object Pv { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Runtime.Participant.Pv = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Pv = { SimonaConfig.Simona.Runtime.Participant.Pv( - defaultConfig = SimonaConfig.PvRuntimeConfig( - if (c.hasPathOrNull("defaultConfig")) - c.getConfig("defaultConfig") - else - com.typesafe.config.ConfigFactory - .parseString("defaultConfig{}"), - parentPath + "defaultConfig.", - $tsCfgValidator - ), - individualConfigs = $_LSimonaConfig_PvRuntimeConfig( - c.getList("individualConfigs"), - parentPath, - $tsCfgValidator - ) + defaultConfig = SimonaConfig.PvRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), + individualConfigs = $_LSimonaConfig_PvRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_PvRuntimeConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.PvRuntimeConfig] = { + private def $_LSimonaConfig_PvRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.PvRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.PvRuntimeConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.PvRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class Wec( - defaultConfig: SimonaConfig.WecRuntimeConfig, - individualConfigs: scala.List[SimonaConfig.WecRuntimeConfig] + defaultConfig : SimonaConfig.WecRuntimeConfig, + individualConfigs : scala.List[SimonaConfig.WecRuntimeConfig] ) object Wec { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Runtime.Participant.Wec = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Wec = { SimonaConfig.Simona.Runtime.Participant.Wec( - defaultConfig = SimonaConfig.WecRuntimeConfig( - if (c.hasPathOrNull("defaultConfig")) - c.getConfig("defaultConfig") - else - com.typesafe.config.ConfigFactory - .parseString("defaultConfig{}"), - parentPath + "defaultConfig.", - $tsCfgValidator - ), - individualConfigs = $_LSimonaConfig_WecRuntimeConfig( - c.getList("individualConfigs"), - parentPath, - $tsCfgValidator - ) + defaultConfig = SimonaConfig.WecRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), + individualConfigs = $_LSimonaConfig_WecRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) ) } - private def $_LSimonaConfig_WecRuntimeConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.WecRuntimeConfig] = { + private def $_LSimonaConfig_WecRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.WecRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.WecRuntimeConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.WecRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Runtime.Participant = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant = { SimonaConfig.Simona.Runtime.Participant( - evcs = SimonaConfig.Simona.Runtime.Participant.Evcs( - if (c.hasPathOrNull("evcs")) c.getConfig("evcs") - else com.typesafe.config.ConfigFactory.parseString("evcs{}"), - parentPath + "evcs.", - $tsCfgValidator - ), - fixedFeedIn = SimonaConfig.Simona.Runtime.Participant.FixedFeedIn( - if (c.hasPathOrNull("fixedFeedIn")) c.getConfig("fixedFeedIn") - else - com.typesafe.config.ConfigFactory.parseString("fixedFeedIn{}"), - parentPath + "fixedFeedIn.", - $tsCfgValidator - ), - load = SimonaConfig.Simona.Runtime.Participant.Load( - if (c.hasPathOrNull("load")) c.getConfig("load") - else com.typesafe.config.ConfigFactory.parseString("load{}"), - parentPath + "load.", - $tsCfgValidator - ), - pv = SimonaConfig.Simona.Runtime.Participant.Pv( - if (c.hasPathOrNull("pv")) c.getConfig("pv") - else com.typesafe.config.ConfigFactory.parseString("pv{}"), - parentPath + "pv.", - $tsCfgValidator - ), - requestVoltageDeviationThreshold = - if (c.hasPathOrNull("requestVoltageDeviationThreshold")) - c.getDouble("requestVoltageDeviationThreshold") - else 1e-14, - wec = SimonaConfig.Simona.Runtime.Participant.Wec( - if (c.hasPathOrNull("wec")) c.getConfig("wec") - else com.typesafe.config.ConfigFactory.parseString("wec{}"), - parentPath + "wec.", - $tsCfgValidator - ) + evcs = SimonaConfig.Simona.Runtime.Participant.Evcs(if(c.hasPathOrNull("evcs")) c.getConfig("evcs") else com.typesafe.config.ConfigFactory.parseString("evcs{}"), parentPath + "evcs.", $tsCfgValidator), + fixedFeedIn = SimonaConfig.Simona.Runtime.Participant.FixedFeedIn(if(c.hasPathOrNull("fixedFeedIn")) c.getConfig("fixedFeedIn") else com.typesafe.config.ConfigFactory.parseString("fixedFeedIn{}"), parentPath + "fixedFeedIn.", $tsCfgValidator), + load = SimonaConfig.Simona.Runtime.Participant.Load(if(c.hasPathOrNull("load")) c.getConfig("load") else com.typesafe.config.ConfigFactory.parseString("load{}"), parentPath + "load.", $tsCfgValidator), + pv = SimonaConfig.Simona.Runtime.Participant.Pv(if(c.hasPathOrNull("pv")) c.getConfig("pv") else com.typesafe.config.ConfigFactory.parseString("pv{}"), parentPath + "pv.", $tsCfgValidator), + requestVoltageDeviationThreshold = if(c.hasPathOrNull("requestVoltageDeviationThreshold")) c.getDouble("requestVoltageDeviationThreshold") else 1E-14, + wec = SimonaConfig.Simona.Runtime.Participant.Wec(if(c.hasPathOrNull("wec")) c.getConfig("wec") else com.typesafe.config.ConfigFactory.parseString("wec{}"), parentPath + "wec.", $tsCfgValidator) ) } } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Runtime = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime = { SimonaConfig.Simona.Runtime( - participant = SimonaConfig.Simona.Runtime.Participant( - if (c.hasPathOrNull("participant")) c.getConfig("participant") - else com.typesafe.config.ConfigFactory.parseString("participant{}"), - parentPath + "participant.", - $tsCfgValidator - ), - selected_subgrids = - if (c.hasPathOrNull("selected_subgrids")) - scala.Some( - $_L$_int( - c.getList("selected_subgrids"), - parentPath, - $tsCfgValidator - ) - ) - else None, - selected_volt_lvls = - if (c.hasPathOrNull("selected_volt_lvls")) - scala.Some( - $_LSimonaConfig_VoltLvlConfig( - c.getList("selected_volt_lvls"), - parentPath, - $tsCfgValidator - ) - ) - else None + participant = SimonaConfig.Simona.Runtime.Participant(if(c.hasPathOrNull("participant")) c.getConfig("participant") else com.typesafe.config.ConfigFactory.parseString("participant{}"), parentPath + "participant.", $tsCfgValidator), + selected_subgrids = if(c.hasPathOrNull("selected_subgrids")) scala.Some($_L$_int(c.getList("selected_subgrids"), parentPath, $tsCfgValidator)) else None, + selected_volt_lvls = if(c.hasPathOrNull("selected_volt_lvls")) scala.Some($_LSimonaConfig_VoltLvlConfig(c.getList("selected_volt_lvls"), parentPath, $tsCfgValidator)) else None ) } - private def $_LSimonaConfig_VoltLvlConfig( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[SimonaConfig.VoltLvlConfig] = { + private def $_LSimonaConfig_VoltLvlConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.VoltLvlConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala - .map(cv => - SimonaConfig.VoltLvlConfig( - cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, - parentPath, - $tsCfgValidator - ) - ) - .toList + cl.asScala.map(cv => SimonaConfig.VoltLvlConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList } } - + final case class Time( - endDateTime: java.lang.String, - schedulerReadyCheckWindow: scala.Option[scala.Int], - startDateTime: java.lang.String, - stopOnFailedPowerFlow: scala.Boolean + endDateTime : java.lang.String, + schedulerReadyCheckWindow : scala.Option[scala.Int], + startDateTime : java.lang.String, + stopOnFailedPowerFlow : scala.Boolean ) object Time { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona.Time = { + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Time = { SimonaConfig.Simona.Time( - endDateTime = - if (c.hasPathOrNull("endDateTime")) c.getString("endDateTime") - else "2011-05-01 01:00:00", - schedulerReadyCheckWindow = - if (c.hasPathOrNull("schedulerReadyCheckWindow")) - Some(c.getInt("schedulerReadyCheckWindow")) - else None, - startDateTime = - if (c.hasPathOrNull("startDateTime")) c.getString("startDateTime") - else "2011-05-01 00:00:00", - stopOnFailedPowerFlow = - c.hasPathOrNull("stopOnFailedPowerFlow") && c.getBoolean( - "stopOnFailedPowerFlow" - ) + endDateTime = if(c.hasPathOrNull("endDateTime")) c.getString("endDateTime") else "2011-05-01 01:00:00", + schedulerReadyCheckWindow = if(c.hasPathOrNull("schedulerReadyCheckWindow")) Some(c.getInt("schedulerReadyCheckWindow")) else None, + startDateTime = if(c.hasPathOrNull("startDateTime")) c.getString("startDateTime") else "2011-05-01 00:00:00", + stopOnFailedPowerFlow = c.hasPathOrNull("stopOnFailedPowerFlow") && c.getBoolean("stopOnFailedPowerFlow") ) } } - - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): SimonaConfig.Simona = { + + def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona = { SimonaConfig.Simona( - control = - if (c.hasPathOrNull("control")) - scala.Some( - SimonaConfig.Simona.Control( - c.getConfig("control"), - parentPath + "control.", - $tsCfgValidator - ) - ) - else None, - event = SimonaConfig.Simona.Event( - if (c.hasPathOrNull("event")) c.getConfig("event") - else com.typesafe.config.ConfigFactory.parseString("event{}"), - parentPath + "event.", - $tsCfgValidator - ), - gridConfig = SimonaConfig.Simona.GridConfig( - if (c.hasPathOrNull("gridConfig")) c.getConfig("gridConfig") - else com.typesafe.config.ConfigFactory.parseString("gridConfig{}"), - parentPath + "gridConfig.", - $tsCfgValidator - ), - input = SimonaConfig.Simona.Input( - if (c.hasPathOrNull("input")) c.getConfig("input") - else com.typesafe.config.ConfigFactory.parseString("input{}"), - parentPath + "input.", - $tsCfgValidator - ), - output = SimonaConfig.Simona.Output( - if (c.hasPathOrNull("output")) c.getConfig("output") - else com.typesafe.config.ConfigFactory.parseString("output{}"), - parentPath + "output.", - $tsCfgValidator - ), - powerflow = SimonaConfig.Simona.Powerflow( - if (c.hasPathOrNull("powerflow")) c.getConfig("powerflow") - else com.typesafe.config.ConfigFactory.parseString("powerflow{}"), - parentPath + "powerflow.", - $tsCfgValidator - ), - runtime = SimonaConfig.Simona.Runtime( - if (c.hasPathOrNull("runtime")) c.getConfig("runtime") - else com.typesafe.config.ConfigFactory.parseString("runtime{}"), - parentPath + "runtime.", - $tsCfgValidator - ), - simulationName = - $_reqStr(parentPath, c, "simulationName", $tsCfgValidator), - time = SimonaConfig.Simona.Time( - if (c.hasPathOrNull("time")) c.getConfig("time") - else com.typesafe.config.ConfigFactory.parseString("time{}"), - parentPath + "time.", - $tsCfgValidator - ) + control = if(c.hasPathOrNull("control")) scala.Some(SimonaConfig.Simona.Control(c.getConfig("control"), parentPath + "control.", $tsCfgValidator)) else None, + event = SimonaConfig.Simona.Event(if(c.hasPathOrNull("event")) c.getConfig("event") else com.typesafe.config.ConfigFactory.parseString("event{}"), parentPath + "event.", $tsCfgValidator), + gridConfig = SimonaConfig.Simona.GridConfig(if(c.hasPathOrNull("gridConfig")) c.getConfig("gridConfig") else com.typesafe.config.ConfigFactory.parseString("gridConfig{}"), parentPath + "gridConfig.", $tsCfgValidator), + input = SimonaConfig.Simona.Input(if(c.hasPathOrNull("input")) c.getConfig("input") else com.typesafe.config.ConfigFactory.parseString("input{}"), parentPath + "input.", $tsCfgValidator), + output = SimonaConfig.Simona.Output(if(c.hasPathOrNull("output")) c.getConfig("output") else com.typesafe.config.ConfigFactory.parseString("output{}"), parentPath + "output.", $tsCfgValidator), + powerflow = SimonaConfig.Simona.Powerflow(if(c.hasPathOrNull("powerflow")) c.getConfig("powerflow") else com.typesafe.config.ConfigFactory.parseString("powerflow{}"), parentPath + "powerflow.", $tsCfgValidator), + runtime = SimonaConfig.Simona.Runtime(if(c.hasPathOrNull("runtime")) c.getConfig("runtime") else com.typesafe.config.ConfigFactory.parseString("runtime{}"), parentPath + "runtime.", $tsCfgValidator), + simulationName = $_reqStr(parentPath, c, "simulationName", $tsCfgValidator), + time = SimonaConfig.Simona.Time(if(c.hasPathOrNull("time")) c.getConfig("time") else com.typesafe.config.ConfigFactory.parseString("time{}"), parentPath + "time.", $tsCfgValidator) ) } - private def $_reqStr( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): java.lang.String = { + private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { if (c == null) null - else - try c.getString(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else try c.getString(path) + catch { + case e:com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + def apply(c: com.typesafe.config.Config): SimonaConfig = { val $tsCfgValidator: $TsCfgValidator = new $TsCfgValidator() val parentPath: java.lang.String = "" val $result = SimonaConfig( - simona = SimonaConfig.Simona( - if (c.hasPathOrNull("simona")) c.getConfig("simona") - else com.typesafe.config.ConfigFactory.parseString("simona{}"), - parentPath + "simona.", - $tsCfgValidator - ) + simona = SimonaConfig.Simona(if(c.hasPathOrNull("simona")) c.getConfig("simona") else com.typesafe.config.ConfigFactory.parseString("simona{}"), parentPath + "simona.", $tsCfgValidator) ) $tsCfgValidator.validate() $result } - private def $_L$_dbl( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[scala.Double] = { + private def $_L$_dbl(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[scala.Double] = { import scala.jdk.CollectionConverters._ cl.asScala.map(cv => $_dbl(cv)).toList } - private def $_L$_int( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[scala.Int] = { + private def $_L$_int(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[scala.Int] = { import scala.jdk.CollectionConverters._ cl.asScala.map(cv => $_int(cv)).toList } - private def $_L$_str( - cl: com.typesafe.config.ConfigList, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator - ): scala.List[java.lang.String] = { + private def $_L$_str(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[java.lang.String] = { import scala.jdk.CollectionConverters._ cl.asScala.map(cv => $_str(cv)).toList } - private def $_dbl(cv: com.typesafe.config.ConfigValue): scala.Double = { + private def $_dbl(cv:com.typesafe.config.ConfigValue): scala.Double = { val u: Any = cv.unwrapped - if ( - (cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || - !u.isInstanceOf[java.lang.Number] - ) throw $_expE(cv, "double") + if ((cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || + !u.isInstanceOf[java.lang.Number]) throw $_expE(cv, "double") u.asInstanceOf[java.lang.Number].doubleValue() } - private def $_expE( - cv: com.typesafe.config.ConfigValue, - exp: java.lang.String - ) = { + private def $_expE(cv:com.typesafe.config.ConfigValue, exp:java.lang.String) = { val u: Any = cv.unwrapped - new java.lang.RuntimeException( - s"${cv.origin.lineNumber}: " + - "expecting: " + exp + " got: " + - (if (u.isInstanceOf[java.lang.String]) "\"" + u + "\"" else u) - ) + new java.lang.RuntimeException(s"${cv.origin.lineNumber}: " + + "expecting: " + exp + " got: " + + (if (u.isInstanceOf[java.lang.String]) "\"" + u + "\"" else u)) } - private def $_int(cv: com.typesafe.config.ConfigValue): scala.Int = { + private def $_int(cv:com.typesafe.config.ConfigValue): scala.Int = { val u: Any = cv.unwrapped - if ( - (cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || - !u.isInstanceOf[Integer] - ) throw $_expE(cv, "integer") + if ((cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || + !u.isInstanceOf[Integer]) throw $_expE(cv, "integer") u.asInstanceOf[Integer] } - private def $_str(cv: com.typesafe.config.ConfigValue): java.lang.String = { + private def $_str(cv:com.typesafe.config.ConfigValue): java.lang.String = { java.lang.String.valueOf(cv.unwrapped()) } final class $TsCfgValidator { - private val badPaths = - scala.collection.mutable.ArrayBuffer[java.lang.String]() + private val badPaths = scala.collection.mutable.ArrayBuffer[java.lang.String]() - def addBadPath( - path: java.lang.String, - e: com.typesafe.config.ConfigException - ): Unit = { + def addBadPath(path: java.lang.String, e: com.typesafe.config.ConfigException): Unit = { badPaths += s"'$path': ${e.getClass.getName}(${e.getMessage})" } - def addInvalidEnumValue( - path: java.lang.String, - value: java.lang.String, - enumName: java.lang.String - ): Unit = { + def addInvalidEnumValue(path: java.lang.String, value: java.lang.String, enumName: java.lang.String): Unit = { badPaths += s"'$path': invalid value $value for enumeration $enumName" } @@ -2358,7 +1243,7 @@ object SimonaConfig { if (badPaths.nonEmpty) { throw new com.typesafe.config.ConfigException( badPaths.mkString("Invalid configuration:\n ", "\n ", "") - ) {} + ){} } } } From 47054b8175a7023bc33e3039be56a26c6102b792 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 7 Jun 2022 13:56:43 +0200 Subject: [PATCH 013/123] fix file name of config template --- gradle/scripts/tscfg.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/scripts/tscfg.gradle b/gradle/scripts/tscfg.gradle index e81ad99320..1c8db401ac 100644 --- a/gradle/scripts/tscfg.gradle +++ b/gradle/scripts/tscfg.gradle @@ -15,7 +15,7 @@ task genConfigClass { args = [ "build/tscfg-${tscfgVersion}.jar", "--spec", - "src/main/resources/config/config-template.conf", + "src/main/resources/config/simona-config-template.conf", "--scala", "--durations", "--pn", From 0fef590e81aad7dede2ecbd018c01e72aa3a4572 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:21:55 +0200 Subject: [PATCH 014/123] adapt changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63f023e434..85da45cd96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Implement SQL source for primary data [#34](https://github.com/ie3-institute/simona/issues/34), [#101](https://github.com/ie3-institute/simona/issues/101) - Relevant scientific papers have been added to the documentation [#139](https://github.com/ie3-institute/simona/issues/139) - Add troubleshooting section to Users guide [#160](https://github.com/ie3-institute/simona/issues/160) -- Config possibility for transformer control groups -- Models for measurements within the grid structure +- Models for measurements within the grid structure [#89](https://github.com/ie3-institute/simona/issues/89) +- Config possibility for transformer control groups [#90](https://github.com/ie3-institute/simona/issues/90) + ### Changed - Re-organizing test resources into their respective packages [#105](https://github.com/ie3-institute/simona/issues/105) From 203d70a7730f2d4497da9387944721b51da83f48 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:25:31 +0200 Subject: [PATCH 015/123] spotless --- .../edu/ie3/simona/config/SimonaConfig.scala | 2625 ++++++++++++----- 1 file changed, 1870 insertions(+), 755 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala index b519da4699..dada716baf 100644 --- a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala +++ b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala @@ -1,1241 +1,2356 @@ -// generated by tscfg 0.9.998 on Tue Jun 07 13:54:10 CEST 2022 -// source: src/main/resources/config/simona-config-template.conf +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ package edu.ie3.simona.config final case class SimonaConfig( - simona : SimonaConfig.Simona + simona: SimonaConfig.Simona ) object SimonaConfig { final case class BaseCsvParams( - override val csvSep : java.lang.String, - override val directoryPath : java.lang.String, - override val isHierarchic : scala.Boolean - ) extends CsvParams(csvSep,directoryPath,isHierarchic) + override val csvSep: java.lang.String, + override val directoryPath: java.lang.String, + override val isHierarchic: scala.Boolean + ) extends CsvParams(csvSep, directoryPath, isHierarchic) object BaseCsvParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.BaseCsvParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.BaseCsvParams = { SimonaConfig.BaseCsvParams( csvSep = $_reqStr(parentPath, c, "csvSep", $tsCfgValidator), - directoryPath = $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), + directoryPath = + $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), isHierarchic = $_reqBln(parentPath, c, "isHierarchic", $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class BaseOutputConfig( - notifier : java.lang.String, - powerRequestReply : scala.Boolean, - simulationResult : scala.Boolean + notifier: java.lang.String, + powerRequestReply: scala.Boolean, + simulationResult: scala.Boolean ) object BaseOutputConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.BaseOutputConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.BaseOutputConfig = { SimonaConfig.BaseOutputConfig( - notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), - powerRequestReply = $_reqBln(parentPath, c, "powerRequestReply", $tsCfgValidator), - simulationResult = $_reqBln(parentPath, c, "simulationResult", $tsCfgValidator) + notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), + powerRequestReply = + $_reqBln(parentPath, c, "powerRequestReply", $tsCfgValidator), + simulationResult = + $_reqBln(parentPath, c, "simulationResult", $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - sealed abstract class BaseRuntimeConfig ( - val calculateMissingReactivePowerWithModel : scala.Boolean, - val scaling : scala.Double, - val uuids : scala.List[java.lang.String] + + sealed abstract class BaseRuntimeConfig( + val calculateMissingReactivePowerWithModel: scala.Boolean, + val scaling: scala.Double, + val uuids: scala.List[java.lang.String] ) extends java.io.Serializable - - sealed abstract class CsvParams ( - val csvSep : java.lang.String, - val directoryPath : java.lang.String, - val isHierarchic : scala.Boolean + + sealed abstract class CsvParams( + val csvSep: java.lang.String, + val directoryPath: java.lang.String, + val isHierarchic: scala.Boolean ) - + final case class EvcsRuntimeConfig( - override val calculateMissingReactivePowerWithModel : scala.Boolean, - override val scaling : scala.Double, - override val uuids : scala.List[java.lang.String] - ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) + override val calculateMissingReactivePowerWithModel: scala.Boolean, + override val scaling: scala.Double, + override val uuids: scala.List[java.lang.String] + ) extends BaseRuntimeConfig( + calculateMissingReactivePowerWithModel, + scaling, + uuids + ) object EvcsRuntimeConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.EvcsRuntimeConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.EvcsRuntimeConfig = { SimonaConfig.EvcsRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), + calculateMissingReactivePowerWithModel = $_reqBln( + parentPath, + c, + "calculateMissingReactivePowerWithModel", + $tsCfgValidator + ), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { + + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { if (c == null) 0 - else try c.getDouble(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class FixedFeedInRuntimeConfig( - override val calculateMissingReactivePowerWithModel : scala.Boolean, - override val scaling : scala.Double, - override val uuids : scala.List[java.lang.String] - ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) + override val calculateMissingReactivePowerWithModel: scala.Boolean, + override val scaling: scala.Double, + override val uuids: scala.List[java.lang.String] + ) extends BaseRuntimeConfig( + calculateMissingReactivePowerWithModel, + scaling, + uuids + ) object FixedFeedInRuntimeConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.FixedFeedInRuntimeConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.FixedFeedInRuntimeConfig = { SimonaConfig.FixedFeedInRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), + calculateMissingReactivePowerWithModel = $_reqBln( + parentPath, + c, + "calculateMissingReactivePowerWithModel", + $tsCfgValidator + ), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { + + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { if (c == null) 0 - else try c.getDouble(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class GridOutputConfig( - lines : scala.Boolean, - nodes : scala.Boolean, - notifier : java.lang.String, - switches : scala.Boolean, - transformers2w : scala.Boolean, - transformers3w : scala.Boolean + lines: scala.Boolean, + nodes: scala.Boolean, + notifier: java.lang.String, + switches: scala.Boolean, + transformers2w: scala.Boolean, + transformers3w: scala.Boolean ) object GridOutputConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.GridOutputConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.GridOutputConfig = { SimonaConfig.GridOutputConfig( - lines = c.hasPathOrNull("lines") && c.getBoolean("lines"), - nodes = c.hasPathOrNull("nodes") && c.getBoolean("nodes"), - notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), - switches = c.hasPathOrNull("switches") && c.getBoolean("switches"), - transformers2w = c.hasPathOrNull("transformers2w") && c.getBoolean("transformers2w"), - transformers3w = c.hasPathOrNull("transformers3w") && c.getBoolean("transformers3w") + lines = c.hasPathOrNull("lines") && c.getBoolean("lines"), + nodes = c.hasPathOrNull("nodes") && c.getBoolean("nodes"), + notifier = $_reqStr(parentPath, c, "notifier", $tsCfgValidator), + switches = c.hasPathOrNull("switches") && c.getBoolean("switches"), + transformers2w = + c.hasPathOrNull("transformers2w") && c.getBoolean("transformers2w"), + transformers3w = + c.hasPathOrNull("transformers3w") && c.getBoolean("transformers3w") ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class LoadRuntimeConfig( - override val calculateMissingReactivePowerWithModel : scala.Boolean, - override val scaling : scala.Double, - override val uuids : scala.List[java.lang.String], - modelBehaviour : java.lang.String, - reference : java.lang.String - ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) + override val calculateMissingReactivePowerWithModel: scala.Boolean, + override val scaling: scala.Double, + override val uuids: scala.List[java.lang.String], + modelBehaviour: java.lang.String, + reference: java.lang.String + ) extends BaseRuntimeConfig( + calculateMissingReactivePowerWithModel, + scaling, + uuids + ) object LoadRuntimeConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.LoadRuntimeConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.LoadRuntimeConfig = { SimonaConfig.LoadRuntimeConfig( - modelBehaviour = $_reqStr(parentPath, c, "modelBehaviour", $tsCfgValidator), - reference = $_reqStr(parentPath, c, "reference", $tsCfgValidator), - calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), - scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), - uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) + modelBehaviour = + $_reqStr(parentPath, c, "modelBehaviour", $tsCfgValidator), + reference = $_reqStr(parentPath, c, "reference", $tsCfgValidator), + calculateMissingReactivePowerWithModel = $_reqBln( + parentPath, + c, + "calculateMissingReactivePowerWithModel", + $tsCfgValidator + ), + scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), + uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { + + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { if (c == null) 0 - else try c.getDouble(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class PrimaryDataCsvParams( - override val csvSep : java.lang.String, - override val directoryPath : java.lang.String, - override val isHierarchic : scala.Boolean, - timePattern : java.lang.String - ) extends CsvParams(csvSep,directoryPath,isHierarchic) + override val csvSep: java.lang.String, + override val directoryPath: java.lang.String, + override val isHierarchic: scala.Boolean, + timePattern: java.lang.String + ) extends CsvParams(csvSep, directoryPath, isHierarchic) object PrimaryDataCsvParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.PrimaryDataCsvParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.PrimaryDataCsvParams = { SimonaConfig.PrimaryDataCsvParams( - timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - csvSep = $_reqStr(parentPath, c, "csvSep", $tsCfgValidator), - directoryPath = $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), + timePattern = + if (c.hasPathOrNull("timePattern")) c.getString("timePattern") + else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + csvSep = $_reqStr(parentPath, c, "csvSep", $tsCfgValidator), + directoryPath = + $_reqStr(parentPath, c, "directoryPath", $tsCfgValidator), isHierarchic = $_reqBln(parentPath, c, "isHierarchic", $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class PvRuntimeConfig( - override val calculateMissingReactivePowerWithModel : scala.Boolean, - override val scaling : scala.Double, - override val uuids : scala.List[java.lang.String] - ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) + override val calculateMissingReactivePowerWithModel: scala.Boolean, + override val scaling: scala.Double, + override val uuids: scala.List[java.lang.String] + ) extends BaseRuntimeConfig( + calculateMissingReactivePowerWithModel, + scaling, + uuids + ) object PvRuntimeConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.PvRuntimeConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.PvRuntimeConfig = { SimonaConfig.PvRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), + calculateMissingReactivePowerWithModel = $_reqBln( + parentPath, + c, + "calculateMissingReactivePowerWithModel", + $tsCfgValidator + ), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { + + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { if (c == null) 0 - else try c.getDouble(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class RefSystemConfig( - gridIds : scala.Option[scala.List[java.lang.String]], - sNom : java.lang.String, - vNom : java.lang.String, - voltLvls : scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] + gridIds: scala.Option[scala.List[java.lang.String]], + sNom: java.lang.String, + vNom: java.lang.String, + voltLvls: scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] ) object RefSystemConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.RefSystemConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.RefSystemConfig = { SimonaConfig.RefSystemConfig( - gridIds = if(c.hasPathOrNull("gridIds")) scala.Some($_L$_str(c.getList("gridIds"), parentPath, $tsCfgValidator)) else None, - sNom = $_reqStr(parentPath, c, "sNom", $tsCfgValidator), - vNom = $_reqStr(parentPath, c, "vNom", $tsCfgValidator), - voltLvls = if(c.hasPathOrNull("voltLvls")) scala.Some($_LSimonaConfig_VoltLvlConfig(c.getList("voltLvls"), parentPath, $tsCfgValidator)) else None + gridIds = + if (c.hasPathOrNull("gridIds")) + scala.Some( + $_L$_str(c.getList("gridIds"), parentPath, $tsCfgValidator) + ) + else None, + sNom = $_reqStr(parentPath, c, "sNom", $tsCfgValidator), + vNom = $_reqStr(parentPath, c, "vNom", $tsCfgValidator), + voltLvls = + if (c.hasPathOrNull("voltLvls")) + scala.Some( + $_LSimonaConfig_VoltLvlConfig( + c.getList("voltLvls"), + parentPath, + $tsCfgValidator + ) + ) + else None ) } - private def $_LSimonaConfig_VoltLvlConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.VoltLvlConfig] = { + private def $_LSimonaConfig_VoltLvlConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.VoltLvlConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.VoltLvlConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.VoltLvlConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class TransformerControlGroup( - measurements : scala.List[java.lang.String], - transformers : scala.List[java.lang.String], - vMax : scala.Double, - vMin : scala.Double + measurements: scala.List[java.lang.String], + transformers: scala.List[java.lang.String], + vMax: scala.Double, + vMin: scala.Double ) object TransformerControlGroup { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.TransformerControlGroup = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.TransformerControlGroup = { SimonaConfig.TransformerControlGroup( - measurements = $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), - transformers = $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), - vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), - vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) + measurements = + $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), + transformers = + $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), + vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), + vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) ) } - private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { if (c == null) 0 - else try c.getDouble(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class VoltLvlConfig( - id : java.lang.String, - vNom : java.lang.String + id: java.lang.String, + vNom: java.lang.String ) object VoltLvlConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.VoltLvlConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.VoltLvlConfig = { SimonaConfig.VoltLvlConfig( - id = $_reqStr(parentPath, c, "id", $tsCfgValidator), + id = $_reqStr(parentPath, c, "id", $tsCfgValidator), vNom = $_reqStr(parentPath, c, "vNom", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class WecRuntimeConfig( - override val calculateMissingReactivePowerWithModel : scala.Boolean, - override val scaling : scala.Double, - override val uuids : scala.List[java.lang.String] - ) extends BaseRuntimeConfig(calculateMissingReactivePowerWithModel,scaling,uuids) + override val calculateMissingReactivePowerWithModel: scala.Boolean, + override val scaling: scala.Double, + override val uuids: scala.List[java.lang.String] + ) extends BaseRuntimeConfig( + calculateMissingReactivePowerWithModel, + scaling, + uuids + ) object WecRuntimeConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.WecRuntimeConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.WecRuntimeConfig = { SimonaConfig.WecRuntimeConfig( - calculateMissingReactivePowerWithModel = $_reqBln(parentPath, c, "calculateMissingReactivePowerWithModel", $tsCfgValidator), + calculateMissingReactivePowerWithModel = $_reqBln( + parentPath, + c, + "calculateMissingReactivePowerWithModel", + $tsCfgValidator + ), scaling = $_reqDbl(parentPath, c, "scaling", $tsCfgValidator), uuids = $_L$_str(c.getList("uuids"), parentPath, $tsCfgValidator) ) } - private def $_reqBln(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Boolean = { + private def $_reqBln( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Boolean = { if (c == null) false - else try c.getBoolean(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - false - } + else + try c.getBoolean(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + false + } } - - private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { + + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { if (c == null) 0 - else try c.getDouble(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class Simona( - control : scala.Option[SimonaConfig.Simona.Control], - event : SimonaConfig.Simona.Event, - gridConfig : SimonaConfig.Simona.GridConfig, - input : SimonaConfig.Simona.Input, - output : SimonaConfig.Simona.Output, - powerflow : SimonaConfig.Simona.Powerflow, - runtime : SimonaConfig.Simona.Runtime, - simulationName : java.lang.String, - time : SimonaConfig.Simona.Time + control: scala.Option[SimonaConfig.Simona.Control], + event: SimonaConfig.Simona.Event, + gridConfig: SimonaConfig.Simona.GridConfig, + input: SimonaConfig.Simona.Input, + output: SimonaConfig.Simona.Output, + powerflow: SimonaConfig.Simona.Powerflow, + runtime: SimonaConfig.Simona.Runtime, + simulationName: java.lang.String, + time: SimonaConfig.Simona.Time ) object Simona { final case class Control( - transformer : scala.List[SimonaConfig.TransformerControlGroup] + transformer: scala.List[SimonaConfig.TransformerControlGroup] ) object Control { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Control = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Control = { SimonaConfig.Simona.Control( - transformer = $_LSimonaConfig_TransformerControlGroup(c.getList("transformer"), parentPath, $tsCfgValidator) + transformer = $_LSimonaConfig_TransformerControlGroup( + c.getList("transformer"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_TransformerControlGroup(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.TransformerControlGroup] = { + private def $_LSimonaConfig_TransformerControlGroup( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.TransformerControlGroup] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.TransformerControlGroup(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.TransformerControlGroup( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class Event( - listener : scala.Option[scala.List[SimonaConfig.Simona.Event.Listener$Elm]] + listener: scala.Option[ + scala.List[SimonaConfig.Simona.Event.Listener$Elm] + ] ) object Event { final case class Listener$Elm( - eventsToProcess : scala.Option[scala.List[java.lang.String]], - fullClassPath : java.lang.String + eventsToProcess: scala.Option[scala.List[java.lang.String]], + fullClassPath: java.lang.String ) object Listener$Elm { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Event.Listener$Elm = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Event.Listener$Elm = { SimonaConfig.Simona.Event.Listener$Elm( - eventsToProcess = if(c.hasPathOrNull("eventsToProcess")) scala.Some($_L$_str(c.getList("eventsToProcess"), parentPath, $tsCfgValidator)) else None, - fullClassPath = $_reqStr(parentPath, c, "fullClassPath", $tsCfgValidator) + eventsToProcess = + if (c.hasPathOrNull("eventsToProcess")) + scala.Some( + $_L$_str( + c.getList("eventsToProcess"), + parentPath, + $tsCfgValidator + ) + ) + else None, + fullClassPath = + $_reqStr(parentPath, c, "fullClassPath", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Event = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Event = { SimonaConfig.Simona.Event( - listener = if(c.hasPathOrNull("listener")) scala.Some($_LSimonaConfig_Simona_Event_Listener$Elm(c.getList("listener"), parentPath, $tsCfgValidator)) else None + listener = + if (c.hasPathOrNull("listener")) + scala.Some( + $_LSimonaConfig_Simona_Event_Listener$Elm( + c.getList("listener"), + parentPath, + $tsCfgValidator + ) + ) + else None ) } - private def $_LSimonaConfig_Simona_Event_Listener$Elm(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.Simona.Event.Listener$Elm] = { + private def $_LSimonaConfig_Simona_Event_Listener$Elm( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.Simona.Event.Listener$Elm] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.Simona.Event.Listener$Elm(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.Simona.Event.Listener$Elm( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class GridConfig( - refSystems : scala.List[SimonaConfig.RefSystemConfig] + refSystems: scala.List[SimonaConfig.RefSystemConfig] ) object GridConfig { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.GridConfig = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.GridConfig = { SimonaConfig.Simona.GridConfig( - refSystems = $_LSimonaConfig_RefSystemConfig(c.getList("refSystems"), parentPath, $tsCfgValidator) + refSystems = $_LSimonaConfig_RefSystemConfig( + c.getList("refSystems"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_RefSystemConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.RefSystemConfig] = { + private def $_LSimonaConfig_RefSystemConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.RefSystemConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.RefSystemConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.RefSystemConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class Input( - grid : SimonaConfig.Simona.Input.Grid, - primary : SimonaConfig.Simona.Input.Primary, - weather : SimonaConfig.Simona.Input.Weather + grid: SimonaConfig.Simona.Input.Grid, + primary: SimonaConfig.Simona.Input.Primary, + weather: SimonaConfig.Simona.Input.Weather ) object Input { final case class Grid( - datasource : SimonaConfig.Simona.Input.Grid.Datasource + datasource: SimonaConfig.Simona.Input.Grid.Datasource ) object Grid { final case class Datasource( - csvParams : scala.Option[SimonaConfig.BaseCsvParams], - id : java.lang.String + csvParams: scala.Option[SimonaConfig.BaseCsvParams], + id: java.lang.String ) object Datasource { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Grid.Datasource = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Grid.Datasource = { SimonaConfig.Simona.Input.Grid.Datasource( - csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.BaseCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, - id = $_reqStr(parentPath, c, "id", $tsCfgValidator) + csvParams = + if (c.hasPathOrNull("csvParams")) + scala.Some( + SimonaConfig.BaseCsvParams( + c.getConfig("csvParams"), + parentPath + "csvParams.", + $tsCfgValidator + ) + ) + else None, + id = $_reqStr(parentPath, c, "id", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Grid = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Grid = { SimonaConfig.Simona.Input.Grid( - datasource = SimonaConfig.Simona.Input.Grid.Datasource(if(c.hasPathOrNull("datasource")) c.getConfig("datasource") else com.typesafe.config.ConfigFactory.parseString("datasource{}"), parentPath + "datasource.", $tsCfgValidator) + datasource = SimonaConfig.Simona.Input.Grid.Datasource( + if (c.hasPathOrNull("datasource")) c.getConfig("datasource") + else + com.typesafe.config.ConfigFactory.parseString("datasource{}"), + parentPath + "datasource.", + $tsCfgValidator + ) ) } } - + final case class Primary( - couchbaseParams : scala.Option[SimonaConfig.Simona.Input.Primary.CouchbaseParams], - csvParams : scala.Option[SimonaConfig.PrimaryDataCsvParams], - influxDb1xParams : scala.Option[SimonaConfig.Simona.Input.Primary.InfluxDb1xParams], - sqlParams : scala.Option[SimonaConfig.Simona.Input.Primary.SqlParams] + couchbaseParams: scala.Option[ + SimonaConfig.Simona.Input.Primary.CouchbaseParams + ], + csvParams: scala.Option[SimonaConfig.PrimaryDataCsvParams], + influxDb1xParams: scala.Option[ + SimonaConfig.Simona.Input.Primary.InfluxDb1xParams + ], + sqlParams: scala.Option[SimonaConfig.Simona.Input.Primary.SqlParams] ) object Primary { final case class CouchbaseParams( - bucketName : java.lang.String, - coordinateColumnName : java.lang.String, - keyPrefix : java.lang.String, - password : java.lang.String, - timePattern : java.lang.String, - url : java.lang.String, - userName : java.lang.String + bucketName: java.lang.String, + coordinateColumnName: java.lang.String, + keyPrefix: java.lang.String, + password: java.lang.String, + timePattern: java.lang.String, + url: java.lang.String, + userName: java.lang.String ) object CouchbaseParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary.CouchbaseParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Primary.CouchbaseParams = { SimonaConfig.Simona.Input.Primary.CouchbaseParams( - bucketName = $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), - coordinateColumnName = $_reqStr(parentPath, c, "coordinateColumnName", $tsCfgValidator), - keyPrefix = $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - url = $_reqStr(parentPath, c, "url", $tsCfgValidator), - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + bucketName = + $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), + coordinateColumnName = $_reqStr( + parentPath, + c, + "coordinateColumnName", + $tsCfgValidator + ), + keyPrefix = $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + timePattern = + if (c.hasPathOrNull("timePattern")) c.getString("timePattern") + else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + url = $_reqStr(parentPath, c, "url", $tsCfgValidator), + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class InfluxDb1xParams( - database : java.lang.String, - port : scala.Int, - timePattern : java.lang.String, - url : java.lang.String + database: java.lang.String, + port: scala.Int, + timePattern: java.lang.String, + url: java.lang.String ) object InfluxDb1xParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary.InfluxDb1xParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Primary.InfluxDb1xParams = { SimonaConfig.Simona.Input.Primary.InfluxDb1xParams( - database = $_reqStr(parentPath, c, "database", $tsCfgValidator), - port = $_reqInt(parentPath, c, "port", $tsCfgValidator), - timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - url = $_reqStr(parentPath, c, "url", $tsCfgValidator) + database = $_reqStr(parentPath, c, "database", $tsCfgValidator), + port = $_reqInt(parentPath, c, "port", $tsCfgValidator), + timePattern = + if (c.hasPathOrNull("timePattern")) c.getString("timePattern") + else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + url = $_reqStr(parentPath, c, "url", $tsCfgValidator) ) } - private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { + private def $_reqInt( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Int = { if (c == null) 0 - else try c.getInt(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getInt(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class SqlParams( - jdbcUrl : java.lang.String, - password : java.lang.String, - schemaName : java.lang.String, - timePattern : java.lang.String, - userName : java.lang.String + jdbcUrl: java.lang.String, + password: java.lang.String, + schemaName: java.lang.String, + timePattern: java.lang.String, + userName: java.lang.String ) object SqlParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary.SqlParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Primary.SqlParams = { SimonaConfig.Simona.Input.Primary.SqlParams( - jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - schemaName = if(c.hasPathOrNull("schemaName")) c.getString("schemaName") else "public", - timePattern = if(c.hasPathOrNull("timePattern")) c.getString("timePattern") else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + schemaName = + if (c.hasPathOrNull("schemaName")) c.getString("schemaName") + else "public", + timePattern = + if (c.hasPathOrNull("timePattern")) c.getString("timePattern") + else "yyyy-MM-dd'T'HH:mm:ss[.S[S][S]]'Z'", + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Primary = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Primary = { SimonaConfig.Simona.Input.Primary( - couchbaseParams = if(c.hasPathOrNull("couchbaseParams")) scala.Some(SimonaConfig.Simona.Input.Primary.CouchbaseParams(c.getConfig("couchbaseParams"), parentPath + "couchbaseParams.", $tsCfgValidator)) else None, - csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.PrimaryDataCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, - influxDb1xParams = if(c.hasPathOrNull("influxDb1xParams")) scala.Some(SimonaConfig.Simona.Input.Primary.InfluxDb1xParams(c.getConfig("influxDb1xParams"), parentPath + "influxDb1xParams.", $tsCfgValidator)) else None, - sqlParams = if(c.hasPathOrNull("sqlParams")) scala.Some(SimonaConfig.Simona.Input.Primary.SqlParams(c.getConfig("sqlParams"), parentPath + "sqlParams.", $tsCfgValidator)) else None + couchbaseParams = + if (c.hasPathOrNull("couchbaseParams")) + scala.Some( + SimonaConfig.Simona.Input.Primary.CouchbaseParams( + c.getConfig("couchbaseParams"), + parentPath + "couchbaseParams.", + $tsCfgValidator + ) + ) + else None, + csvParams = + if (c.hasPathOrNull("csvParams")) + scala.Some( + SimonaConfig.PrimaryDataCsvParams( + c.getConfig("csvParams"), + parentPath + "csvParams.", + $tsCfgValidator + ) + ) + else None, + influxDb1xParams = + if (c.hasPathOrNull("influxDb1xParams")) + scala.Some( + SimonaConfig.Simona.Input.Primary.InfluxDb1xParams( + c.getConfig("influxDb1xParams"), + parentPath + "influxDb1xParams.", + $tsCfgValidator + ) + ) + else None, + sqlParams = + if (c.hasPathOrNull("sqlParams")) + scala.Some( + SimonaConfig.Simona.Input.Primary.SqlParams( + c.getConfig("sqlParams"), + parentPath + "sqlParams.", + $tsCfgValidator + ) + ) + else None ) } } - + final case class Weather( - datasource : SimonaConfig.Simona.Input.Weather.Datasource + datasource: SimonaConfig.Simona.Input.Weather.Datasource ) object Weather { final case class Datasource( - coordinateSource : SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource, - couchbaseParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams], - csvParams : scala.Option[SimonaConfig.BaseCsvParams], - influxDb1xParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams], - resolution : scala.Option[scala.Long], - sampleParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.SampleParams], - scheme : java.lang.String, - sqlParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.SqlParams], - timestampPattern : scala.Option[java.lang.String] + coordinateSource: SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource, + couchbaseParams: scala.Option[ + SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams + ], + csvParams: scala.Option[SimonaConfig.BaseCsvParams], + influxDb1xParams: scala.Option[ + SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams + ], + resolution: scala.Option[scala.Long], + sampleParams: scala.Option[ + SimonaConfig.Simona.Input.Weather.Datasource.SampleParams + ], + scheme: java.lang.String, + sqlParams: scala.Option[ + SimonaConfig.Simona.Input.Weather.Datasource.SqlParams + ], + timestampPattern: scala.Option[java.lang.String] ) object Datasource { final case class CoordinateSource( - csvParams : scala.Option[SimonaConfig.BaseCsvParams], - gridModel : java.lang.String, - sampleParams : scala.Option[SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams] + csvParams: scala.Option[SimonaConfig.BaseCsvParams], + gridModel: java.lang.String, + sampleParams: scala.Option[ + SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams + ] ) object CoordinateSource { final case class SampleParams( - use : scala.Boolean + use: scala.Boolean ) object SampleParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams = { - SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams( - use = !c.hasPathOrNull("use") || c.getBoolean("use") - ) + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams = { + SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource + .SampleParams( + use = !c.hasPathOrNull("use") || c.getBoolean("use") + ) } } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource = { SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource( - csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.BaseCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, - gridModel = if(c.hasPathOrNull("gridModel")) c.getString("gridModel") else "icon", - sampleParams = if(c.hasPathOrNull("sampleParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource.SampleParams(c.getConfig("sampleParams"), parentPath + "sampleParams.", $tsCfgValidator)) else None + csvParams = + if (c.hasPathOrNull("csvParams")) + scala.Some( + SimonaConfig.BaseCsvParams( + c.getConfig("csvParams"), + parentPath + "csvParams.", + $tsCfgValidator + ) + ) + else None, + gridModel = + if (c.hasPathOrNull("gridModel")) c.getString("gridModel") + else "icon", + sampleParams = + if (c.hasPathOrNull("sampleParams")) + scala.Some( + SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource + .SampleParams( + c.getConfig("sampleParams"), + parentPath + "sampleParams.", + $tsCfgValidator + ) + ) + else None ) } } - + final case class CouchbaseParams( - bucketName : java.lang.String, - coordinateColumnName : java.lang.String, - keyPrefix : java.lang.String, - password : java.lang.String, - url : java.lang.String, - userName : java.lang.String + bucketName: java.lang.String, + coordinateColumnName: java.lang.String, + keyPrefix: java.lang.String, + password: java.lang.String, + url: java.lang.String, + userName: java.lang.String ) object CouchbaseParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams = { SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams( - bucketName = $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), - coordinateColumnName = $_reqStr(parentPath, c, "coordinateColumnName", $tsCfgValidator), - keyPrefix = $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - url = $_reqStr(parentPath, c, "url", $tsCfgValidator), - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + bucketName = + $_reqStr(parentPath, c, "bucketName", $tsCfgValidator), + coordinateColumnName = $_reqStr( + parentPath, + c, + "coordinateColumnName", + $tsCfgValidator + ), + keyPrefix = + $_reqStr(parentPath, c, "keyPrefix", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + url = $_reqStr(parentPath, c, "url", $tsCfgValidator), + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class InfluxDb1xParams( - database : java.lang.String, - port : scala.Int, - url : java.lang.String + database: java.lang.String, + port: scala.Int, + url: java.lang.String ) object InfluxDb1xParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams = { SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams( database = $_reqStr(parentPath, c, "database", $tsCfgValidator), - port = $_reqInt(parentPath, c, "port", $tsCfgValidator), - url = $_reqStr(parentPath, c, "url", $tsCfgValidator) + port = $_reqInt(parentPath, c, "port", $tsCfgValidator), + url = $_reqStr(parentPath, c, "url", $tsCfgValidator) ) } - private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { + private def $_reqInt( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Int = { if (c == null) 0 - else try c.getInt(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getInt(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class SampleParams( - use : scala.Boolean + use: scala.Boolean ) object SampleParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.SampleParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather.Datasource.SampleParams = { SimonaConfig.Simona.Input.Weather.Datasource.SampleParams( use = !c.hasPathOrNull("use") || c.getBoolean("use") ) } } - + final case class SqlParams( - jdbcUrl : java.lang.String, - password : java.lang.String, - schemaName : java.lang.String, - tableName : java.lang.String, - userName : java.lang.String + jdbcUrl: java.lang.String, + password: java.lang.String, + schemaName: java.lang.String, + tableName: java.lang.String, + userName: java.lang.String ) object SqlParams { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource.SqlParams = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather.Datasource.SqlParams = { SimonaConfig.Simona.Input.Weather.Datasource.SqlParams( - jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), - password = $_reqStr(parentPath, c, "password", $tsCfgValidator), - schemaName = if(c.hasPathOrNull("schemaName")) c.getString("schemaName") else "public", - tableName = $_reqStr(parentPath, c, "tableName", $tsCfgValidator), - userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) + jdbcUrl = $_reqStr(parentPath, c, "jdbcUrl", $tsCfgValidator), + password = $_reqStr(parentPath, c, "password", $tsCfgValidator), + schemaName = + if (c.hasPathOrNull("schemaName")) c.getString("schemaName") + else "public", + tableName = + $_reqStr(parentPath, c, "tableName", $tsCfgValidator), + userName = $_reqStr(parentPath, c, "userName", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather.Datasource = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather.Datasource = { SimonaConfig.Simona.Input.Weather.Datasource( - coordinateSource = SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource(if(c.hasPathOrNull("coordinateSource")) c.getConfig("coordinateSource") else com.typesafe.config.ConfigFactory.parseString("coordinateSource{}"), parentPath + "coordinateSource.", $tsCfgValidator), - couchbaseParams = if(c.hasPathOrNull("couchbaseParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.CouchbaseParams(c.getConfig("couchbaseParams"), parentPath + "couchbaseParams.", $tsCfgValidator)) else None, - csvParams = if(c.hasPathOrNull("csvParams")) scala.Some(SimonaConfig.BaseCsvParams(c.getConfig("csvParams"), parentPath + "csvParams.", $tsCfgValidator)) else None, - influxDb1xParams = if(c.hasPathOrNull("influxDb1xParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.InfluxDb1xParams(c.getConfig("influxDb1xParams"), parentPath + "influxDb1xParams.", $tsCfgValidator)) else None, - resolution = if(c.hasPathOrNull("resolution")) Some(c.getLong("resolution").longValue()) else None, - sampleParams = if(c.hasPathOrNull("sampleParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.SampleParams(c.getConfig("sampleParams"), parentPath + "sampleParams.", $tsCfgValidator)) else None, - scheme = if(c.hasPathOrNull("scheme")) c.getString("scheme") else "icon", - sqlParams = if(c.hasPathOrNull("sqlParams")) scala.Some(SimonaConfig.Simona.Input.Weather.Datasource.SqlParams(c.getConfig("sqlParams"), parentPath + "sqlParams.", $tsCfgValidator)) else None, - timestampPattern = if(c.hasPathOrNull("timestampPattern")) Some(c.getString("timestampPattern")) else None + coordinateSource = + SimonaConfig.Simona.Input.Weather.Datasource.CoordinateSource( + if (c.hasPathOrNull("coordinateSource")) + c.getConfig("coordinateSource") + else + com.typesafe.config.ConfigFactory + .parseString("coordinateSource{}"), + parentPath + "coordinateSource.", + $tsCfgValidator + ), + couchbaseParams = + if (c.hasPathOrNull("couchbaseParams")) + scala.Some( + SimonaConfig.Simona.Input.Weather.Datasource + .CouchbaseParams( + c.getConfig("couchbaseParams"), + parentPath + "couchbaseParams.", + $tsCfgValidator + ) + ) + else None, + csvParams = + if (c.hasPathOrNull("csvParams")) + scala.Some( + SimonaConfig.BaseCsvParams( + c.getConfig("csvParams"), + parentPath + "csvParams.", + $tsCfgValidator + ) + ) + else None, + influxDb1xParams = + if (c.hasPathOrNull("influxDb1xParams")) + scala.Some( + SimonaConfig.Simona.Input.Weather.Datasource + .InfluxDb1xParams( + c.getConfig("influxDb1xParams"), + parentPath + "influxDb1xParams.", + $tsCfgValidator + ) + ) + else None, + resolution = + if (c.hasPathOrNull("resolution")) + Some(c.getLong("resolution").longValue()) + else None, + sampleParams = + if (c.hasPathOrNull("sampleParams")) + scala.Some( + SimonaConfig.Simona.Input.Weather.Datasource.SampleParams( + c.getConfig("sampleParams"), + parentPath + "sampleParams.", + $tsCfgValidator + ) + ) + else None, + scheme = + if (c.hasPathOrNull("scheme")) c.getString("scheme") + else "icon", + sqlParams = + if (c.hasPathOrNull("sqlParams")) + scala.Some( + SimonaConfig.Simona.Input.Weather.Datasource.SqlParams( + c.getConfig("sqlParams"), + parentPath + "sqlParams.", + $tsCfgValidator + ) + ) + else None, + timestampPattern = + if (c.hasPathOrNull("timestampPattern")) + Some(c.getString("timestampPattern")) + else None ) } } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input.Weather = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input.Weather = { SimonaConfig.Simona.Input.Weather( - datasource = SimonaConfig.Simona.Input.Weather.Datasource(if(c.hasPathOrNull("datasource")) c.getConfig("datasource") else com.typesafe.config.ConfigFactory.parseString("datasource{}"), parentPath + "datasource.", $tsCfgValidator) + datasource = SimonaConfig.Simona.Input.Weather.Datasource( + if (c.hasPathOrNull("datasource")) c.getConfig("datasource") + else + com.typesafe.config.ConfigFactory.parseString("datasource{}"), + parentPath + "datasource.", + $tsCfgValidator + ) ) } } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Input = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Input = { SimonaConfig.Simona.Input( - grid = SimonaConfig.Simona.Input.Grid(if(c.hasPathOrNull("grid")) c.getConfig("grid") else com.typesafe.config.ConfigFactory.parseString("grid{}"), parentPath + "grid.", $tsCfgValidator), - primary = SimonaConfig.Simona.Input.Primary(if(c.hasPathOrNull("primary")) c.getConfig("primary") else com.typesafe.config.ConfigFactory.parseString("primary{}"), parentPath + "primary.", $tsCfgValidator), - weather = SimonaConfig.Simona.Input.Weather(if(c.hasPathOrNull("weather")) c.getConfig("weather") else com.typesafe.config.ConfigFactory.parseString("weather{}"), parentPath + "weather.", $tsCfgValidator) + grid = SimonaConfig.Simona.Input.Grid( + if (c.hasPathOrNull("grid")) c.getConfig("grid") + else com.typesafe.config.ConfigFactory.parseString("grid{}"), + parentPath + "grid.", + $tsCfgValidator + ), + primary = SimonaConfig.Simona.Input.Primary( + if (c.hasPathOrNull("primary")) c.getConfig("primary") + else com.typesafe.config.ConfigFactory.parseString("primary{}"), + parentPath + "primary.", + $tsCfgValidator + ), + weather = SimonaConfig.Simona.Input.Weather( + if (c.hasPathOrNull("weather")) c.getConfig("weather") + else com.typesafe.config.ConfigFactory.parseString("weather{}"), + parentPath + "weather.", + $tsCfgValidator + ) ) } } - + final case class Output( - base : SimonaConfig.Simona.Output.Base, - grid : SimonaConfig.GridOutputConfig, - participant : SimonaConfig.Simona.Output.Participant, - sink : SimonaConfig.Simona.Output.Sink + base: SimonaConfig.Simona.Output.Base, + grid: SimonaConfig.GridOutputConfig, + participant: SimonaConfig.Simona.Output.Participant, + sink: SimonaConfig.Simona.Output.Sink ) object Output { final case class Base( - addTimestampToOutputDir : scala.Boolean, - dir : java.lang.String + addTimestampToOutputDir: scala.Boolean, + dir: java.lang.String ) object Base { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Base = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Output.Base = { SimonaConfig.Simona.Output.Base( - addTimestampToOutputDir = !c.hasPathOrNull("addTimestampToOutputDir") || c.getBoolean("addTimestampToOutputDir"), - dir = $_reqStr(parentPath, c, "dir", $tsCfgValidator) + addTimestampToOutputDir = !c.hasPathOrNull( + "addTimestampToOutputDir" + ) || c.getBoolean("addTimestampToOutputDir"), + dir = $_reqStr(parentPath, c, "dir", $tsCfgValidator) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + final case class Participant( - defaultConfig : SimonaConfig.BaseOutputConfig, - individualConfigs : scala.List[SimonaConfig.BaseOutputConfig] + defaultConfig: SimonaConfig.BaseOutputConfig, + individualConfigs: scala.List[SimonaConfig.BaseOutputConfig] ) object Participant { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Participant = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Output.Participant = { SimonaConfig.Simona.Output.Participant( - defaultConfig = SimonaConfig.BaseOutputConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), - individualConfigs = $_LSimonaConfig_BaseOutputConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) + defaultConfig = SimonaConfig.BaseOutputConfig( + if (c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") + else + com.typesafe.config.ConfigFactory + .parseString("defaultConfig{}"), + parentPath + "defaultConfig.", + $tsCfgValidator + ), + individualConfigs = $_LSimonaConfig_BaseOutputConfig( + c.getList("individualConfigs"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_BaseOutputConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.BaseOutputConfig] = { + private def $_LSimonaConfig_BaseOutputConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.BaseOutputConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.BaseOutputConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.BaseOutputConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class Sink( - csv : scala.Option[SimonaConfig.Simona.Output.Sink.Csv], - influxDb1x : scala.Option[SimonaConfig.Simona.Output.Sink.InfluxDb1x] + csv: scala.Option[SimonaConfig.Simona.Output.Sink.Csv], + influxDb1x: scala.Option[SimonaConfig.Simona.Output.Sink.InfluxDb1x] ) object Sink { final case class Csv( - fileFormat : java.lang.String, - filePrefix : java.lang.String, - fileSuffix : java.lang.String, - isHierarchic : scala.Boolean + fileFormat: java.lang.String, + filePrefix: java.lang.String, + fileSuffix: java.lang.String, + isHierarchic: scala.Boolean ) object Csv { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Sink.Csv = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Output.Sink.Csv = { SimonaConfig.Simona.Output.Sink.Csv( - fileFormat = if(c.hasPathOrNull("fileFormat")) c.getString("fileFormat") else ".csv", - filePrefix = if(c.hasPathOrNull("filePrefix")) c.getString("filePrefix") else "", - fileSuffix = if(c.hasPathOrNull("fileSuffix")) c.getString("fileSuffix") else "", - isHierarchic = c.hasPathOrNull("isHierarchic") && c.getBoolean("isHierarchic") + fileFormat = + if (c.hasPathOrNull("fileFormat")) c.getString("fileFormat") + else ".csv", + filePrefix = + if (c.hasPathOrNull("filePrefix")) c.getString("filePrefix") + else "", + fileSuffix = + if (c.hasPathOrNull("fileSuffix")) c.getString("fileSuffix") + else "", + isHierarchic = + c.hasPathOrNull("isHierarchic") && c.getBoolean("isHierarchic") ) } } - + final case class InfluxDb1x( - database : java.lang.String, - port : scala.Int, - url : java.lang.String + database: java.lang.String, + port: scala.Int, + url: java.lang.String ) object InfluxDb1x { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Sink.InfluxDb1x = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Output.Sink.InfluxDb1x = { SimonaConfig.Simona.Output.Sink.InfluxDb1x( database = $_reqStr(parentPath, c, "database", $tsCfgValidator), - port = $_reqInt(parentPath, c, "port", $tsCfgValidator), - url = $_reqStr(parentPath, c, "url", $tsCfgValidator) + port = $_reqInt(parentPath, c, "port", $tsCfgValidator), + url = $_reqStr(parentPath, c, "url", $tsCfgValidator) ) } - private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { + private def $_reqInt( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Int = { if (c == null) 0 - else try c.getInt(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getInt(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output.Sink = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Output.Sink = { SimonaConfig.Simona.Output.Sink( - csv = if(c.hasPathOrNull("csv")) scala.Some(SimonaConfig.Simona.Output.Sink.Csv(c.getConfig("csv"), parentPath + "csv.", $tsCfgValidator)) else None, - influxDb1x = if(c.hasPathOrNull("influxDb1x")) scala.Some(SimonaConfig.Simona.Output.Sink.InfluxDb1x(c.getConfig("influxDb1x"), parentPath + "influxDb1x.", $tsCfgValidator)) else None + csv = + if (c.hasPathOrNull("csv")) + scala.Some( + SimonaConfig.Simona.Output.Sink.Csv( + c.getConfig("csv"), + parentPath + "csv.", + $tsCfgValidator + ) + ) + else None, + influxDb1x = + if (c.hasPathOrNull("influxDb1x")) + scala.Some( + SimonaConfig.Simona.Output.Sink.InfluxDb1x( + c.getConfig("influxDb1x"), + parentPath + "influxDb1x.", + $tsCfgValidator + ) + ) + else None ) } } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Output = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Output = { SimonaConfig.Simona.Output( - base = SimonaConfig.Simona.Output.Base(if(c.hasPathOrNull("base")) c.getConfig("base") else com.typesafe.config.ConfigFactory.parseString("base{}"), parentPath + "base.", $tsCfgValidator), - grid = SimonaConfig.GridOutputConfig(if(c.hasPathOrNull("grid")) c.getConfig("grid") else com.typesafe.config.ConfigFactory.parseString("grid{}"), parentPath + "grid.", $tsCfgValidator), - participant = SimonaConfig.Simona.Output.Participant(if(c.hasPathOrNull("participant")) c.getConfig("participant") else com.typesafe.config.ConfigFactory.parseString("participant{}"), parentPath + "participant.", $tsCfgValidator), - sink = SimonaConfig.Simona.Output.Sink(if(c.hasPathOrNull("sink")) c.getConfig("sink") else com.typesafe.config.ConfigFactory.parseString("sink{}"), parentPath + "sink.", $tsCfgValidator) + base = SimonaConfig.Simona.Output.Base( + if (c.hasPathOrNull("base")) c.getConfig("base") + else com.typesafe.config.ConfigFactory.parseString("base{}"), + parentPath + "base.", + $tsCfgValidator + ), + grid = SimonaConfig.GridOutputConfig( + if (c.hasPathOrNull("grid")) c.getConfig("grid") + else com.typesafe.config.ConfigFactory.parseString("grid{}"), + parentPath + "grid.", + $tsCfgValidator + ), + participant = SimonaConfig.Simona.Output.Participant( + if (c.hasPathOrNull("participant")) c.getConfig("participant") + else com.typesafe.config.ConfigFactory.parseString("participant{}"), + parentPath + "participant.", + $tsCfgValidator + ), + sink = SimonaConfig.Simona.Output.Sink( + if (c.hasPathOrNull("sink")) c.getConfig("sink") + else com.typesafe.config.ConfigFactory.parseString("sink{}"), + parentPath + "sink.", + $tsCfgValidator + ) ) } } - + final case class Powerflow( - maxSweepPowerDeviation : scala.Double, - newtonraphson : SimonaConfig.Simona.Powerflow.Newtonraphson, - resolution : java.time.Duration, - sweepTimeout : java.time.Duration + maxSweepPowerDeviation: scala.Double, + newtonraphson: SimonaConfig.Simona.Powerflow.Newtonraphson, + resolution: java.time.Duration, + sweepTimeout: java.time.Duration ) object Powerflow { final case class Newtonraphson( - epsilon : scala.List[scala.Double], - iterations : scala.Int + epsilon: scala.List[scala.Double], + iterations: scala.Int ) object Newtonraphson { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Powerflow.Newtonraphson = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Powerflow.Newtonraphson = { SimonaConfig.Simona.Powerflow.Newtonraphson( - epsilon = $_L$_dbl(c.getList("epsilon"), parentPath, $tsCfgValidator), + epsilon = + $_L$_dbl(c.getList("epsilon"), parentPath, $tsCfgValidator), iterations = $_reqInt(parentPath, c, "iterations", $tsCfgValidator) ) } - private def $_reqInt(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Int = { + private def $_reqInt( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Int = { if (c == null) 0 - else try c.getInt(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getInt(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Powerflow = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Powerflow = { SimonaConfig.Simona.Powerflow( - maxSweepPowerDeviation = $_reqDbl(parentPath, c, "maxSweepPowerDeviation", $tsCfgValidator), - newtonraphson = SimonaConfig.Simona.Powerflow.Newtonraphson(if(c.hasPathOrNull("newtonraphson")) c.getConfig("newtonraphson") else com.typesafe.config.ConfigFactory.parseString("newtonraphson{}"), parentPath + "newtonraphson.", $tsCfgValidator), - resolution = if(c.hasPathOrNull("resolution")) c.getDuration("resolution") else java.time.Duration.parse("PT1H"), - sweepTimeout = if(c.hasPathOrNull("sweepTimeout")) c.getDuration("sweepTimeout") else java.time.Duration.parse("PT30S") + maxSweepPowerDeviation = + $_reqDbl(parentPath, c, "maxSweepPowerDeviation", $tsCfgValidator), + newtonraphson = SimonaConfig.Simona.Powerflow.Newtonraphson( + if (c.hasPathOrNull("newtonraphson")) c.getConfig("newtonraphson") + else + com.typesafe.config.ConfigFactory.parseString("newtonraphson{}"), + parentPath + "newtonraphson.", + $tsCfgValidator + ), + resolution = + if (c.hasPathOrNull("resolution")) c.getDuration("resolution") + else java.time.Duration.parse("PT1H"), + sweepTimeout = + if (c.hasPathOrNull("sweepTimeout")) c.getDuration("sweepTimeout") + else java.time.Duration.parse("PT30S") ) } - private def $_reqDbl(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.Double = { + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { if (c == null) 0 - else try c.getDouble(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } } - + } - + final case class Runtime( - participant : SimonaConfig.Simona.Runtime.Participant, - selected_subgrids : scala.Option[scala.List[scala.Int]], - selected_volt_lvls : scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] + participant: SimonaConfig.Simona.Runtime.Participant, + selected_subgrids: scala.Option[scala.List[scala.Int]], + selected_volt_lvls: scala.Option[scala.List[SimonaConfig.VoltLvlConfig]] ) object Runtime { final case class Participant( - evcs : SimonaConfig.Simona.Runtime.Participant.Evcs, - fixedFeedIn : SimonaConfig.Simona.Runtime.Participant.FixedFeedIn, - load : SimonaConfig.Simona.Runtime.Participant.Load, - pv : SimonaConfig.Simona.Runtime.Participant.Pv, - requestVoltageDeviationThreshold : scala.Double, - wec : SimonaConfig.Simona.Runtime.Participant.Wec + evcs: SimonaConfig.Simona.Runtime.Participant.Evcs, + fixedFeedIn: SimonaConfig.Simona.Runtime.Participant.FixedFeedIn, + load: SimonaConfig.Simona.Runtime.Participant.Load, + pv: SimonaConfig.Simona.Runtime.Participant.Pv, + requestVoltageDeviationThreshold: scala.Double, + wec: SimonaConfig.Simona.Runtime.Participant.Wec ) object Participant { final case class Evcs( - defaultConfig : SimonaConfig.EvcsRuntimeConfig, - individualConfigs : scala.List[SimonaConfig.EvcsRuntimeConfig] + defaultConfig: SimonaConfig.EvcsRuntimeConfig, + individualConfigs: scala.List[SimonaConfig.EvcsRuntimeConfig] ) object Evcs { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Evcs = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Runtime.Participant.Evcs = { SimonaConfig.Simona.Runtime.Participant.Evcs( - defaultConfig = SimonaConfig.EvcsRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), - individualConfigs = $_LSimonaConfig_EvcsRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) + defaultConfig = SimonaConfig.EvcsRuntimeConfig( + if (c.hasPathOrNull("defaultConfig")) + c.getConfig("defaultConfig") + else + com.typesafe.config.ConfigFactory + .parseString("defaultConfig{}"), + parentPath + "defaultConfig.", + $tsCfgValidator + ), + individualConfigs = $_LSimonaConfig_EvcsRuntimeConfig( + c.getList("individualConfigs"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_EvcsRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.EvcsRuntimeConfig] = { + private def $_LSimonaConfig_EvcsRuntimeConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.EvcsRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.EvcsRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.EvcsRuntimeConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class FixedFeedIn( - defaultConfig : SimonaConfig.FixedFeedInRuntimeConfig, - individualConfigs : scala.List[SimonaConfig.FixedFeedInRuntimeConfig] + defaultConfig: SimonaConfig.FixedFeedInRuntimeConfig, + individualConfigs: scala.List[SimonaConfig.FixedFeedInRuntimeConfig] ) object FixedFeedIn { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.FixedFeedIn = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Runtime.Participant.FixedFeedIn = { SimonaConfig.Simona.Runtime.Participant.FixedFeedIn( - defaultConfig = SimonaConfig.FixedFeedInRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), - individualConfigs = $_LSimonaConfig_FixedFeedInRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) + defaultConfig = SimonaConfig.FixedFeedInRuntimeConfig( + if (c.hasPathOrNull("defaultConfig")) + c.getConfig("defaultConfig") + else + com.typesafe.config.ConfigFactory + .parseString("defaultConfig{}"), + parentPath + "defaultConfig.", + $tsCfgValidator + ), + individualConfigs = $_LSimonaConfig_FixedFeedInRuntimeConfig( + c.getList("individualConfigs"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_FixedFeedInRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.FixedFeedInRuntimeConfig] = { + private def $_LSimonaConfig_FixedFeedInRuntimeConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.FixedFeedInRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.FixedFeedInRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.FixedFeedInRuntimeConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class Load( - defaultConfig : SimonaConfig.LoadRuntimeConfig, - individualConfigs : scala.List[SimonaConfig.LoadRuntimeConfig] + defaultConfig: SimonaConfig.LoadRuntimeConfig, + individualConfigs: scala.List[SimonaConfig.LoadRuntimeConfig] ) object Load { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Load = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Runtime.Participant.Load = { SimonaConfig.Simona.Runtime.Participant.Load( - defaultConfig = SimonaConfig.LoadRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), - individualConfigs = $_LSimonaConfig_LoadRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) + defaultConfig = SimonaConfig.LoadRuntimeConfig( + if (c.hasPathOrNull("defaultConfig")) + c.getConfig("defaultConfig") + else + com.typesafe.config.ConfigFactory + .parseString("defaultConfig{}"), + parentPath + "defaultConfig.", + $tsCfgValidator + ), + individualConfigs = $_LSimonaConfig_LoadRuntimeConfig( + c.getList("individualConfigs"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_LoadRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.LoadRuntimeConfig] = { + private def $_LSimonaConfig_LoadRuntimeConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.LoadRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.LoadRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.LoadRuntimeConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class Pv( - defaultConfig : SimonaConfig.PvRuntimeConfig, - individualConfigs : scala.List[SimonaConfig.PvRuntimeConfig] + defaultConfig: SimonaConfig.PvRuntimeConfig, + individualConfigs: scala.List[SimonaConfig.PvRuntimeConfig] ) object Pv { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Pv = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Runtime.Participant.Pv = { SimonaConfig.Simona.Runtime.Participant.Pv( - defaultConfig = SimonaConfig.PvRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), - individualConfigs = $_LSimonaConfig_PvRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) + defaultConfig = SimonaConfig.PvRuntimeConfig( + if (c.hasPathOrNull("defaultConfig")) + c.getConfig("defaultConfig") + else + com.typesafe.config.ConfigFactory + .parseString("defaultConfig{}"), + parentPath + "defaultConfig.", + $tsCfgValidator + ), + individualConfigs = $_LSimonaConfig_PvRuntimeConfig( + c.getList("individualConfigs"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_PvRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.PvRuntimeConfig] = { + private def $_LSimonaConfig_PvRuntimeConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.PvRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.PvRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.PvRuntimeConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class Wec( - defaultConfig : SimonaConfig.WecRuntimeConfig, - individualConfigs : scala.List[SimonaConfig.WecRuntimeConfig] + defaultConfig: SimonaConfig.WecRuntimeConfig, + individualConfigs: scala.List[SimonaConfig.WecRuntimeConfig] ) object Wec { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant.Wec = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Runtime.Participant.Wec = { SimonaConfig.Simona.Runtime.Participant.Wec( - defaultConfig = SimonaConfig.WecRuntimeConfig(if(c.hasPathOrNull("defaultConfig")) c.getConfig("defaultConfig") else com.typesafe.config.ConfigFactory.parseString("defaultConfig{}"), parentPath + "defaultConfig.", $tsCfgValidator), - individualConfigs = $_LSimonaConfig_WecRuntimeConfig(c.getList("individualConfigs"), parentPath, $tsCfgValidator) + defaultConfig = SimonaConfig.WecRuntimeConfig( + if (c.hasPathOrNull("defaultConfig")) + c.getConfig("defaultConfig") + else + com.typesafe.config.ConfigFactory + .parseString("defaultConfig{}"), + parentPath + "defaultConfig.", + $tsCfgValidator + ), + individualConfigs = $_LSimonaConfig_WecRuntimeConfig( + c.getList("individualConfigs"), + parentPath, + $tsCfgValidator + ) ) } - private def $_LSimonaConfig_WecRuntimeConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.WecRuntimeConfig] = { + private def $_LSimonaConfig_WecRuntimeConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.WecRuntimeConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.WecRuntimeConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.WecRuntimeConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime.Participant = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Runtime.Participant = { SimonaConfig.Simona.Runtime.Participant( - evcs = SimonaConfig.Simona.Runtime.Participant.Evcs(if(c.hasPathOrNull("evcs")) c.getConfig("evcs") else com.typesafe.config.ConfigFactory.parseString("evcs{}"), parentPath + "evcs.", $tsCfgValidator), - fixedFeedIn = SimonaConfig.Simona.Runtime.Participant.FixedFeedIn(if(c.hasPathOrNull("fixedFeedIn")) c.getConfig("fixedFeedIn") else com.typesafe.config.ConfigFactory.parseString("fixedFeedIn{}"), parentPath + "fixedFeedIn.", $tsCfgValidator), - load = SimonaConfig.Simona.Runtime.Participant.Load(if(c.hasPathOrNull("load")) c.getConfig("load") else com.typesafe.config.ConfigFactory.parseString("load{}"), parentPath + "load.", $tsCfgValidator), - pv = SimonaConfig.Simona.Runtime.Participant.Pv(if(c.hasPathOrNull("pv")) c.getConfig("pv") else com.typesafe.config.ConfigFactory.parseString("pv{}"), parentPath + "pv.", $tsCfgValidator), - requestVoltageDeviationThreshold = if(c.hasPathOrNull("requestVoltageDeviationThreshold")) c.getDouble("requestVoltageDeviationThreshold") else 1E-14, - wec = SimonaConfig.Simona.Runtime.Participant.Wec(if(c.hasPathOrNull("wec")) c.getConfig("wec") else com.typesafe.config.ConfigFactory.parseString("wec{}"), parentPath + "wec.", $tsCfgValidator) + evcs = SimonaConfig.Simona.Runtime.Participant.Evcs( + if (c.hasPathOrNull("evcs")) c.getConfig("evcs") + else com.typesafe.config.ConfigFactory.parseString("evcs{}"), + parentPath + "evcs.", + $tsCfgValidator + ), + fixedFeedIn = SimonaConfig.Simona.Runtime.Participant.FixedFeedIn( + if (c.hasPathOrNull("fixedFeedIn")) c.getConfig("fixedFeedIn") + else + com.typesafe.config.ConfigFactory.parseString("fixedFeedIn{}"), + parentPath + "fixedFeedIn.", + $tsCfgValidator + ), + load = SimonaConfig.Simona.Runtime.Participant.Load( + if (c.hasPathOrNull("load")) c.getConfig("load") + else com.typesafe.config.ConfigFactory.parseString("load{}"), + parentPath + "load.", + $tsCfgValidator + ), + pv = SimonaConfig.Simona.Runtime.Participant.Pv( + if (c.hasPathOrNull("pv")) c.getConfig("pv") + else com.typesafe.config.ConfigFactory.parseString("pv{}"), + parentPath + "pv.", + $tsCfgValidator + ), + requestVoltageDeviationThreshold = + if (c.hasPathOrNull("requestVoltageDeviationThreshold")) + c.getDouble("requestVoltageDeviationThreshold") + else 1e-14, + wec = SimonaConfig.Simona.Runtime.Participant.Wec( + if (c.hasPathOrNull("wec")) c.getConfig("wec") + else com.typesafe.config.ConfigFactory.parseString("wec{}"), + parentPath + "wec.", + $tsCfgValidator + ) ) } } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Runtime = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Runtime = { SimonaConfig.Simona.Runtime( - participant = SimonaConfig.Simona.Runtime.Participant(if(c.hasPathOrNull("participant")) c.getConfig("participant") else com.typesafe.config.ConfigFactory.parseString("participant{}"), parentPath + "participant.", $tsCfgValidator), - selected_subgrids = if(c.hasPathOrNull("selected_subgrids")) scala.Some($_L$_int(c.getList("selected_subgrids"), parentPath, $tsCfgValidator)) else None, - selected_volt_lvls = if(c.hasPathOrNull("selected_volt_lvls")) scala.Some($_LSimonaConfig_VoltLvlConfig(c.getList("selected_volt_lvls"), parentPath, $tsCfgValidator)) else None + participant = SimonaConfig.Simona.Runtime.Participant( + if (c.hasPathOrNull("participant")) c.getConfig("participant") + else com.typesafe.config.ConfigFactory.parseString("participant{}"), + parentPath + "participant.", + $tsCfgValidator + ), + selected_subgrids = + if (c.hasPathOrNull("selected_subgrids")) + scala.Some( + $_L$_int( + c.getList("selected_subgrids"), + parentPath, + $tsCfgValidator + ) + ) + else None, + selected_volt_lvls = + if (c.hasPathOrNull("selected_volt_lvls")) + scala.Some( + $_LSimonaConfig_VoltLvlConfig( + c.getList("selected_volt_lvls"), + parentPath, + $tsCfgValidator + ) + ) + else None ) } - private def $_LSimonaConfig_VoltLvlConfig(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[SimonaConfig.VoltLvlConfig] = { + private def $_LSimonaConfig_VoltLvlConfig( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.VoltLvlConfig] = { import scala.jdk.CollectionConverters._ - cl.asScala.map(cv => SimonaConfig.VoltLvlConfig(cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, $tsCfgValidator)).toList + cl.asScala + .map(cv => + SimonaConfig.VoltLvlConfig( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList } } - + final case class Time( - endDateTime : java.lang.String, - schedulerReadyCheckWindow : scala.Option[scala.Int], - startDateTime : java.lang.String, - stopOnFailedPowerFlow : scala.Boolean + endDateTime: java.lang.String, + schedulerReadyCheckWindow: scala.Option[scala.Int], + startDateTime: java.lang.String, + stopOnFailedPowerFlow: scala.Boolean ) object Time { - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona.Time = { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Time = { SimonaConfig.Simona.Time( - endDateTime = if(c.hasPathOrNull("endDateTime")) c.getString("endDateTime") else "2011-05-01 01:00:00", - schedulerReadyCheckWindow = if(c.hasPathOrNull("schedulerReadyCheckWindow")) Some(c.getInt("schedulerReadyCheckWindow")) else None, - startDateTime = if(c.hasPathOrNull("startDateTime")) c.getString("startDateTime") else "2011-05-01 00:00:00", - stopOnFailedPowerFlow = c.hasPathOrNull("stopOnFailedPowerFlow") && c.getBoolean("stopOnFailedPowerFlow") + endDateTime = + if (c.hasPathOrNull("endDateTime")) c.getString("endDateTime") + else "2011-05-01 01:00:00", + schedulerReadyCheckWindow = + if (c.hasPathOrNull("schedulerReadyCheckWindow")) + Some(c.getInt("schedulerReadyCheckWindow")) + else None, + startDateTime = + if (c.hasPathOrNull("startDateTime")) c.getString("startDateTime") + else "2011-05-01 00:00:00", + stopOnFailedPowerFlow = + c.hasPathOrNull("stopOnFailedPowerFlow") && c.getBoolean( + "stopOnFailedPowerFlow" + ) ) } } - - def apply(c: com.typesafe.config.Config, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): SimonaConfig.Simona = { + + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona = { SimonaConfig.Simona( - control = if(c.hasPathOrNull("control")) scala.Some(SimonaConfig.Simona.Control(c.getConfig("control"), parentPath + "control.", $tsCfgValidator)) else None, - event = SimonaConfig.Simona.Event(if(c.hasPathOrNull("event")) c.getConfig("event") else com.typesafe.config.ConfigFactory.parseString("event{}"), parentPath + "event.", $tsCfgValidator), - gridConfig = SimonaConfig.Simona.GridConfig(if(c.hasPathOrNull("gridConfig")) c.getConfig("gridConfig") else com.typesafe.config.ConfigFactory.parseString("gridConfig{}"), parentPath + "gridConfig.", $tsCfgValidator), - input = SimonaConfig.Simona.Input(if(c.hasPathOrNull("input")) c.getConfig("input") else com.typesafe.config.ConfigFactory.parseString("input{}"), parentPath + "input.", $tsCfgValidator), - output = SimonaConfig.Simona.Output(if(c.hasPathOrNull("output")) c.getConfig("output") else com.typesafe.config.ConfigFactory.parseString("output{}"), parentPath + "output.", $tsCfgValidator), - powerflow = SimonaConfig.Simona.Powerflow(if(c.hasPathOrNull("powerflow")) c.getConfig("powerflow") else com.typesafe.config.ConfigFactory.parseString("powerflow{}"), parentPath + "powerflow.", $tsCfgValidator), - runtime = SimonaConfig.Simona.Runtime(if(c.hasPathOrNull("runtime")) c.getConfig("runtime") else com.typesafe.config.ConfigFactory.parseString("runtime{}"), parentPath + "runtime.", $tsCfgValidator), - simulationName = $_reqStr(parentPath, c, "simulationName", $tsCfgValidator), - time = SimonaConfig.Simona.Time(if(c.hasPathOrNull("time")) c.getConfig("time") else com.typesafe.config.ConfigFactory.parseString("time{}"), parentPath + "time.", $tsCfgValidator) + control = + if (c.hasPathOrNull("control")) + scala.Some( + SimonaConfig.Simona.Control( + c.getConfig("control"), + parentPath + "control.", + $tsCfgValidator + ) + ) + else None, + event = SimonaConfig.Simona.Event( + if (c.hasPathOrNull("event")) c.getConfig("event") + else com.typesafe.config.ConfigFactory.parseString("event{}"), + parentPath + "event.", + $tsCfgValidator + ), + gridConfig = SimonaConfig.Simona.GridConfig( + if (c.hasPathOrNull("gridConfig")) c.getConfig("gridConfig") + else com.typesafe.config.ConfigFactory.parseString("gridConfig{}"), + parentPath + "gridConfig.", + $tsCfgValidator + ), + input = SimonaConfig.Simona.Input( + if (c.hasPathOrNull("input")) c.getConfig("input") + else com.typesafe.config.ConfigFactory.parseString("input{}"), + parentPath + "input.", + $tsCfgValidator + ), + output = SimonaConfig.Simona.Output( + if (c.hasPathOrNull("output")) c.getConfig("output") + else com.typesafe.config.ConfigFactory.parseString("output{}"), + parentPath + "output.", + $tsCfgValidator + ), + powerflow = SimonaConfig.Simona.Powerflow( + if (c.hasPathOrNull("powerflow")) c.getConfig("powerflow") + else com.typesafe.config.ConfigFactory.parseString("powerflow{}"), + parentPath + "powerflow.", + $tsCfgValidator + ), + runtime = SimonaConfig.Simona.Runtime( + if (c.hasPathOrNull("runtime")) c.getConfig("runtime") + else com.typesafe.config.ConfigFactory.parseString("runtime{}"), + parentPath + "runtime.", + $tsCfgValidator + ), + simulationName = + $_reqStr(parentPath, c, "simulationName", $tsCfgValidator), + time = SimonaConfig.Simona.Time( + if (c.hasPathOrNull("time")) c.getConfig("time") + else com.typesafe.config.ConfigFactory.parseString("time{}"), + parentPath + "time.", + $tsCfgValidator + ) ) } - private def $_reqStr(parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, $tsCfgValidator: $TsCfgValidator): java.lang.String = { + private def $_reqStr( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): java.lang.String = { if (c == null) null - else try c.getString(path) - catch { - case e:com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - null - } + else + try c.getString(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + null + } } - + } - + def apply(c: com.typesafe.config.Config): SimonaConfig = { val $tsCfgValidator: $TsCfgValidator = new $TsCfgValidator() val parentPath: java.lang.String = "" val $result = SimonaConfig( - simona = SimonaConfig.Simona(if(c.hasPathOrNull("simona")) c.getConfig("simona") else com.typesafe.config.ConfigFactory.parseString("simona{}"), parentPath + "simona.", $tsCfgValidator) + simona = SimonaConfig.Simona( + if (c.hasPathOrNull("simona")) c.getConfig("simona") + else com.typesafe.config.ConfigFactory.parseString("simona{}"), + parentPath + "simona.", + $tsCfgValidator + ) ) $tsCfgValidator.validate() $result } - private def $_L$_dbl(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[scala.Double] = { + private def $_L$_dbl( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[scala.Double] = { import scala.jdk.CollectionConverters._ cl.asScala.map(cv => $_dbl(cv)).toList } - private def $_L$_int(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[scala.Int] = { + private def $_L$_int( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[scala.Int] = { import scala.jdk.CollectionConverters._ cl.asScala.map(cv => $_int(cv)).toList } - private def $_L$_str(cl:com.typesafe.config.ConfigList, parentPath: java.lang.String, $tsCfgValidator: $TsCfgValidator): scala.List[java.lang.String] = { + private def $_L$_str( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[java.lang.String] = { import scala.jdk.CollectionConverters._ cl.asScala.map(cv => $_str(cv)).toList } - private def $_dbl(cv:com.typesafe.config.ConfigValue): scala.Double = { + private def $_dbl(cv: com.typesafe.config.ConfigValue): scala.Double = { val u: Any = cv.unwrapped - if ((cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || - !u.isInstanceOf[java.lang.Number]) throw $_expE(cv, "double") + if ( + (cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || + !u.isInstanceOf[java.lang.Number] + ) throw $_expE(cv, "double") u.asInstanceOf[java.lang.Number].doubleValue() } - private def $_expE(cv:com.typesafe.config.ConfigValue, exp:java.lang.String) = { + private def $_expE( + cv: com.typesafe.config.ConfigValue, + exp: java.lang.String + ) = { val u: Any = cv.unwrapped - new java.lang.RuntimeException(s"${cv.origin.lineNumber}: " + - "expecting: " + exp + " got: " + - (if (u.isInstanceOf[java.lang.String]) "\"" + u + "\"" else u)) + new java.lang.RuntimeException( + s"${cv.origin.lineNumber}: " + + "expecting: " + exp + " got: " + + (if (u.isInstanceOf[java.lang.String]) "\"" + u + "\"" else u) + ) } - private def $_int(cv:com.typesafe.config.ConfigValue): scala.Int = { + private def $_int(cv: com.typesafe.config.ConfigValue): scala.Int = { val u: Any = cv.unwrapped - if ((cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || - !u.isInstanceOf[Integer]) throw $_expE(cv, "integer") + if ( + (cv.valueType != com.typesafe.config.ConfigValueType.NUMBER) || + !u.isInstanceOf[Integer] + ) throw $_expE(cv, "integer") u.asInstanceOf[Integer] } - private def $_str(cv:com.typesafe.config.ConfigValue): java.lang.String = { + private def $_str(cv: com.typesafe.config.ConfigValue): java.lang.String = { java.lang.String.valueOf(cv.unwrapped()) } final class $TsCfgValidator { - private val badPaths = scala.collection.mutable.ArrayBuffer[java.lang.String]() + private val badPaths = + scala.collection.mutable.ArrayBuffer[java.lang.String]() - def addBadPath(path: java.lang.String, e: com.typesafe.config.ConfigException): Unit = { + def addBadPath( + path: java.lang.String, + e: com.typesafe.config.ConfigException + ): Unit = { badPaths += s"'$path': ${e.getClass.getName}(${e.getMessage})" } - def addInvalidEnumValue(path: java.lang.String, value: java.lang.String, enumName: java.lang.String): Unit = { + def addInvalidEnumValue( + path: java.lang.String, + value: java.lang.String, + enumName: java.lang.String + ): Unit = { badPaths += s"'$path': invalid value $value for enumeration $enumName" } @@ -1243,7 +2358,7 @@ object SimonaConfig { if (badPaths.nonEmpty) { throw new com.typesafe.config.ConfigException( badPaths.mkString("Invalid configuration:\n ", "\n ", "") - ){} + ) {} } } } From f004d6aabf86d037858c5fe9eb10293cb293be9f Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Mon, 20 Jun 2022 18:38:28 +0200 Subject: [PATCH 016/123] Adding link to changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ab37feb55..18c65fd408 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Config possibility for transformer control groups - Implement SQL source for primary data [#34](https://github.com/ie3-institute/simona/issues/34), [#101](https://github.com/ie3-institute/simona/issues/101) - Relevant scientific papers have been added to the documentation [#139](https://github.com/ie3-institute/simona/issues/139) - Add troubleshooting section to Users guide [#160](https://github.com/ie3-institute/simona/issues/160) - Added Kafka sink for results [#24](https://github.com/ie3-institute/simona/issues/24) +- Config possibility for transformer control groups [#90](https://github.com/ie3-institute/simona/issues/90) ### Changed - Re-organizing test resources into their respective packages [#105](https://github.com/ie3-institute/simona/issues/105) From b0ee37d36cfc06d9a5a3c6fce973a71818af362e Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 21 Jun 2022 17:00:26 +0200 Subject: [PATCH 017/123] include transformerControlGroup to Exception message --- .../scala/edu/ie3/simona/config/ConfigFailFast.scala | 10 +++++----- .../edu/ie3/simona/config/ConfigFailFastSpec.scala | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala index 661337bd2b..b068411a6d 100644 --- a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala +++ b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala @@ -581,24 +581,24 @@ case object ConfigFailFast extends LazyLogging { case TransformerControlGroup(measurements, transformers, vMax, vMin) => if (measurements.isEmpty) throw new InvalidConfigParameterException( - "A transformer control group cannot have no measurements assigned." + s"A transformer control group (${transformerControlGroup.toString}) cannot have no measurements assigned." ) if (transformers.isEmpty) throw new InvalidConfigParameterException( - "A transformer control group cannot have no transformers assigned." + s"A transformer control group (${transformerControlGroup.toString}) cannot have no transformers assigned." ) if (vMax < vMin) throw new InvalidConfigParameterException( - "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." + s"The minimum permissible voltage magnitude of a transformer control group (${transformerControlGroup.toString}) must be smaller than the maximum permissible voltage magnitude." ) if (vMin < lowerBoundary) throw new InvalidConfigParameterException( - s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"A control group (${transformerControlGroup.toString}) which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + s"by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" ) if (vMax > upperBoundary) throw new InvalidConfigParameterException( - s"A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"A control group (${transformerControlGroup.toString}) which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + s"by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" ) } diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 1917d316b1..64cd61890f 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -947,7 +947,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { intercept[InvalidConfigParameterException] { ConfigFailFast invokePrivate checkTransformerControl(dut) - }.getMessage shouldBe "A transformer control group cannot have no measurements assigned." + }.getMessage shouldBe s"A transformer control group (${dut.toString}) cannot have no measurements assigned." } "throw an exception, if the transformers are empty" in { @@ -960,7 +960,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { intercept[InvalidConfigParameterException] { ConfigFailFast invokePrivate checkTransformerControl(dut) - }.getMessage shouldBe "A transformer control group cannot have no transformers assigned." + }.getMessage shouldBe s"A transformer control group (${dut.toString}) cannot have no transformers assigned." } "throw an exception, if vMax is smaller than vMin" in { @@ -973,7 +973,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { intercept[InvalidConfigParameterException] { ConfigFailFast invokePrivate checkTransformerControl(dut) - }.getMessage shouldBe "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." + }.getMessage shouldBe s"The minimum permissible voltage magnitude of a transformer control group (${dut.toString}) must be smaller than the maximum permissible voltage magnitude." } "throw Exception when vMin is lower then -21% of nominal Voltage" in { @@ -986,7 +986,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { intercept[InvalidConfigParameterException] { ConfigFailFast invokePrivate checkTransformerControl(dut) - }.getMessage shouldBe "A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + }.getMessage shouldBe s"A control group (${dut.toString}) which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + "by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" } @@ -1000,7 +1000,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { intercept[InvalidConfigParameterException] { ConfigFailFast invokePrivate checkTransformerControl(dut) - }.getMessage shouldBe "A control group which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + }.getMessage shouldBe s"A control group (${dut.toString}) which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + "by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" } } From 1b0169145535603ec9835c3e9fd97bd6e6660d9c Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Sat, 25 Jun 2022 10:16:58 +0200 Subject: [PATCH 018/123] check voltage measurement at gridagent failfast --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 387b96f373..558f90e564 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -7,11 +7,7 @@ package edu.ie3.simona.agent.grid import akka.actor.{ActorRef, Props, Stash} -import edu.ie3.simona.agent.grid.GridAgentData.{ - GridAgentBaseData, - GridAgentInitData, - GridAgentUninitializedData -} +import edu.ie3.simona.agent.grid.GridAgentData.{GridAgentBaseData, GridAgentInitData, GridAgentUninitializedData} import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} @@ -19,22 +15,15 @@ import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage -import edu.ie3.simona.ontology.messages.SchedulerMessage.{ - CompletionMessage, - ScheduleTriggerMessage, - TriggerWithIdMessage -} +import edu.ie3.simona.ontology.messages.SchedulerMessage.{CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage} import edu.ie3.simona.ontology.messages.StopMessage -import edu.ie3.simona.ontology.trigger.Trigger.{ - ActivityStartTrigger, - InitializeGridAgentTrigger, - StartGridSimulationTrigger -} +import edu.ie3.simona.ontology.trigger.Trigger.{ActivityStartTrigger, InitializeGridAgentTrigger, StartGridSimulationTrigger} import edu.ie3.util.TimeUtil import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.UUID +import scala.jdk.CollectionConverters.CollectionHasAsScala import scala.language.postfixOps object GridAgent { @@ -52,7 +41,8 @@ object GridAgent { ) private def failFast( - gridAgentInitData: GridAgentInitData + gridAgentInitData: GridAgentInitData, + simonaConfig: SimonaConfig, ): Unit = { /** Check if there is InitData for superior or inferior GridGates @@ -64,6 +54,15 @@ object GridAgent { s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" ) + + /** Check if there exits voltage measurements for transformerControlGroups + */ + val measurementUnitInput = gridAgentInitData.subGridContainer.getRawGrid.getMeasurementUnits + val maybeControlConfig: Option[SimonaConfig.Simona.Control] = simonaConfig.simona.control + if (maybeControlConfig.isDefined && !measurementUnitInput.asScala.exists(input => input.getVMag)) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a control group with measurement that don't deliver voltage magnitude." + ) } } @@ -122,7 +121,7 @@ class GridAgent( _ ) => // fail fast sanity checks - GridAgent.failFast(gridAgentInitData) + GridAgent.failFast(gridAgentInitData, simonaConfig) log.debug( s"Inferior Subnets: {}; Inferior Subnet Nodes: {}", From 58a2f34ff3650b4b37986520c13eff1aac0d7c0c Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Sat, 25 Jun 2022 10:27:13 +0200 Subject: [PATCH 019/123] move GridAgentFailFast to own class --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 48 +++++++------------ .../simona/agent/grid/GridAgentFailFast.scala | 46 ++++++++++++++++++ 2 files changed, 62 insertions(+), 32 deletions(-) create mode 100644 src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 558f90e564..94a607f6fa 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -7,23 +7,33 @@ package edu.ie3.simona.agent.grid import akka.actor.{ActorRef, Props, Stash} -import edu.ie3.simona.agent.grid.GridAgentData.{GridAgentBaseData, GridAgentInitData, GridAgentUninitializedData} +import edu.ie3.simona.agent.grid.GridAgentData.{ + GridAgentBaseData, + GridAgentInitData, + GridAgentUninitializedData +} import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} import edu.ie3.simona.config.SimonaConfig -import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage -import edu.ie3.simona.ontology.messages.SchedulerMessage.{CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage} +import edu.ie3.simona.ontology.messages.SchedulerMessage.{ + CompletionMessage, + ScheduleTriggerMessage, + TriggerWithIdMessage +} import edu.ie3.simona.ontology.messages.StopMessage -import edu.ie3.simona.ontology.trigger.Trigger.{ActivityStartTrigger, InitializeGridAgentTrigger, StartGridSimulationTrigger} +import edu.ie3.simona.ontology.trigger.Trigger.{ + ActivityStartTrigger, + InitializeGridAgentTrigger, + StartGridSimulationTrigger +} import edu.ie3.util.TimeUtil import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.UUID -import scala.jdk.CollectionConverters.CollectionHasAsScala import scala.language.postfixOps object GridAgent { @@ -39,33 +49,7 @@ object GridAgent { listener ) ) - - private def failFast( - gridAgentInitData: GridAgentInitData, - simonaConfig: SimonaConfig, - ): Unit = { - - /** Check if there is InitData for superior or inferior GridGates - */ - if ( - gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty - ) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + - s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" - ) - - /** Check if there exits voltage measurements for transformerControlGroups - */ - val measurementUnitInput = gridAgentInitData.subGridContainer.getRawGrid.getMeasurementUnits - val maybeControlConfig: Option[SimonaConfig.Simona.Control] = simonaConfig.simona.control - if (maybeControlConfig.isDefined && !measurementUnitInput.asScala.exists(input => input.getVMag)) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a control group with measurement that don't deliver voltage magnitude." - ) - } } - class GridAgent( val environmentRefs: EnvironmentRefs, simonaConfig: SimonaConfig, @@ -121,7 +105,7 @@ class GridAgent( _ ) => // fail fast sanity checks - GridAgent.failFast(gridAgentInitData, simonaConfig) + GridAgentFailFast.failFast(gridAgentInitData, simonaConfig) log.debug( s"Inferior Subnets: {}; Inferior Subnet Nodes: {}", diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala new file mode 100644 index 0000000000..9d1d411abc --- /dev/null +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -0,0 +1,46 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.agent.grid + +import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData +import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.exceptions.agent.GridAgentInitializationException +import scala.jdk.CollectionConverters.CollectionHasAsScala + +case object GridAgentFailFast { + + def failFast( + gridAgentInitData: GridAgentInitData, + simonaConfig: SimonaConfig + ): Unit = { + + /** Check if there is InitData for superior or inferior GridGates + */ + if ( + gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty + ) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + + s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" + ) + + /** Check if there exits voltage measurements for transformerControlGroups + */ + val measurementUnitInput = + gridAgentInitData.subGridContainer.getRawGrid.getMeasurementUnits + val maybeControlConfig: Option[SimonaConfig.Simona.Control] = + simonaConfig.simona.control + if ( + maybeControlConfig.isDefined && !measurementUnitInput.asScala.exists( + input => input.getVMag + ) + ) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a control group with measurement that don't deliver voltage magnitude." + ) + } +} From 4d0e826d57cfe21a36e2b38ef8737598736d3f33 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 5 Jul 2022 14:58:42 +0200 Subject: [PATCH 020/123] fastfail check voltage measurement of transformerControlGroups --- .../simona/agent/grid/GridAgentFailFast.scala | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 9d1d411abc..fafe56a1e3 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -9,7 +9,9 @@ package edu.ie3.simona.agent.grid import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException -import scala.jdk.CollectionConverters.CollectionHasAsScala + +import java.util.UUID +import scala.jdk.CollectionConverters._ case object GridAgentFailFast { @@ -30,17 +32,29 @@ case object GridAgentFailFast { /** Check if there exits voltage measurements for transformerControlGroups */ - val measurementUnitInput = - gridAgentInitData.subGridContainer.getRawGrid.getMeasurementUnits + val maybeControlConfig: Option[SimonaConfig.Simona.Control] = simonaConfig.simona.control - if ( - maybeControlConfig.isDefined && !measurementUnitInput.asScala.exists( - input => input.getVMag + + val measurementUnits = + gridAgentInitData.subGridContainer.getRawGrid.getMeasurementUnits.asScala + + maybeControlConfig.foreach(control => + control.transformer.foreach(transformer => + transformer.measurements.map(UUID.fromString).foreach { measurements => + val measurementUnit = measurementUnits + .find(element => element.getUuid == measurements) + .getOrElse( + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." + ) + ) + if (!measurementUnit.getVMag) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." + ) + } ) ) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a control group with measurement that don't deliver voltage magnitude." - ) } } From 9be075db378dcce949b19db7be6895df5a282256 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 5 Jul 2022 18:06:36 +0200 Subject: [PATCH 021/123] update fastfail check voltage measurement of transformerControlGroups --- .../simona/agent/grid/GridAgentFailFast.scala | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index fafe56a1e3..4905bb141f 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -39,22 +39,50 @@ case object GridAgentFailFast { val measurementUnits = gridAgentInitData.subGridContainer.getRawGrid.getMeasurementUnits.asScala - maybeControlConfig.foreach(control => - control.transformer.foreach(transformer => - transformer.measurements.map(UUID.fromString).foreach { measurements => - val measurementUnit = measurementUnits - .find(element => element.getUuid == measurements) - .getOrElse( - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." - ) - ) - if (!measurementUnit.getVMag) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." - ) - } + val transformerUnits2W = + gridAgentInitData.subGridContainer.getRawGrid.getTransformer2Ws.asScala + + if (maybeControlConfig.isDefined) { + /* + maybeControlConfig.foreach(control => + control.transformer.foreach(transformer => + transformer.transformers.map(UUID.fromString).foreach { + transformers => + val transformerUnit = transformerUnits2W + .find(element => element.getUuid == transformers) + + + if(transformerUnit.isDefined) + + */ + maybeControlConfig.foreach(control => + control.transformer.foreach(transformer => + transformer.transformers.map(UUID.fromString).foreach { + transformers => + // Check if transformer is part of subgrid of this GridAgent + val transformerUnit = transformerUnits2W + .find(element => element.getUuid == transformers) + if (transformerUnit.isDefined) { + + transformer.measurements + .map(UUID.fromString) + .foreach { measurements => + val measurementUnit = measurementUnits + .find(element => element.getUuid == measurements) + .getOrElse( + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." + ) + ) + if (!measurementUnit.getVMag) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." + ) + } + } + } + ) ) - ) + } } } From 92a00be2ece4391633e0c9be9810f784ac20fd74 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Tue, 5 Jul 2022 18:11:13 +0200 Subject: [PATCH 022/123] update also for 3Wtransformers --- .../simona/agent/grid/GridAgentFailFast.scala | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 4905bb141f..09217d5c6e 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -42,27 +42,20 @@ case object GridAgentFailFast { val transformerUnits2W = gridAgentInitData.subGridContainer.getRawGrid.getTransformer2Ws.asScala - if (maybeControlConfig.isDefined) { - /* - maybeControlConfig.foreach(control => - control.transformer.foreach(transformer => - transformer.transformers.map(UUID.fromString).foreach { - transformers => - val transformerUnit = transformerUnits2W - .find(element => element.getUuid == transformers) + val transformerUnits3W = + gridAgentInitData.subGridContainer.getRawGrid.getTransformer3Ws.asScala - - if(transformerUnit.isDefined) - - */ + if (maybeControlConfig.isDefined) { maybeControlConfig.foreach(control => control.transformer.foreach(transformer => transformer.transformers.map(UUID.fromString).foreach { transformers => // Check if transformer is part of subgrid of this GridAgent - val transformerUnit = transformerUnits2W + val transformerUnit2W = transformerUnits2W + .find(element => element.getUuid == transformers) + val transformerUnit3W = transformerUnits3W .find(element => element.getUuid == transformers) - if (transformerUnit.isDefined) { + if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { transformer.measurements .map(UUID.fromString) From b58d2295f2e2963fe7efd23925756e6d058727f3 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 8 Jul 2022 12:59:07 +0200 Subject: [PATCH 023/123] rollback remove of scalingfactor --- .../edu/ie3/simona/model/participant/SystemParticipant.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala index 8eb4e6b966..77c2e11eff 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala @@ -105,7 +105,7 @@ abstract class SystemParticipant[CD <: CalcRelevantData]( def activeToReactivePowerFunc( nodalVoltage: ComparableQuantity[Dimensionless] ): ComparableQuantity[Power] => ComparableQuantity[Power] = - qControl.activeToReactivePowerFunc(sRated, cosPhiRated, nodalVoltage) + qControl.activeToReactivePowerFunc(sRated.multiply(scalingFactor), cosPhiRated, nodalVoltage) /** Calculate the reactive power of the model * From cd7d7b6faeaf226c9821677c4ac784bf14013ba7 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 8 Jul 2022 13:19:53 +0200 Subject: [PATCH 024/123] spotless --- .../ie3/simona/model/participant/SystemParticipant.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala index 77c2e11eff..3331b2280d 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala @@ -105,7 +105,11 @@ abstract class SystemParticipant[CD <: CalcRelevantData]( def activeToReactivePowerFunc( nodalVoltage: ComparableQuantity[Dimensionless] ): ComparableQuantity[Power] => ComparableQuantity[Power] = - qControl.activeToReactivePowerFunc(sRated.multiply(scalingFactor), cosPhiRated, nodalVoltage) + qControl.activeToReactivePowerFunc( + sRated.multiply(scalingFactor), + cosPhiRated, + nodalVoltage + ) /** Calculate the reactive power of the model * From 0fe62ce825bf75cc2a9340bb2ae7136551411c06 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:14:52 +0200 Subject: [PATCH 025/123] change case object to object class --- .../scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 09217d5c6e..43dbfc48df 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -13,7 +13,7 @@ import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import java.util.UUID import scala.jdk.CollectionConverters._ -case object GridAgentFailFast { +object GridAgentFailFast { def failFast( gridAgentInitData: GridAgentInitData, From e941d9bdbc20ffbd0d989583bb1ef204ad1be1da Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:16:58 +0200 Subject: [PATCH 026/123] remove unnecessarfy if statement --- .../scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 43dbfc48df..14336608b6 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -45,8 +45,7 @@ object GridAgentFailFast { val transformerUnits3W = gridAgentInitData.subGridContainer.getRawGrid.getTransformer3Ws.asScala - if (maybeControlConfig.isDefined) { - maybeControlConfig.foreach(control => + maybeControlConfig.foreach(control => control.transformer.foreach(transformer => transformer.transformers.map(UUID.fromString).foreach { transformers => @@ -76,6 +75,6 @@ object GridAgentFailFast { } ) ) - } + } } From 9305f5c5df5fd7bdb1001316a298e8960b6e190f Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:19:01 +0200 Subject: [PATCH 027/123] renaming subjects in foreach loops --- .../ie3/simona/agent/grid/GridAgentFailFast.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 14336608b6..3cfee1e1f8 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -46,17 +46,17 @@ object GridAgentFailFast { gridAgentInitData.subGridContainer.getRawGrid.getTransformer3Ws.asScala maybeControlConfig.foreach(control => - control.transformer.foreach(transformer => - transformer.transformers.map(UUID.fromString).foreach { - transformers => + control.transformer.foreach(controlGroup => + controlGroup.transformers.map(UUID.fromString).foreach { + transformer => // Check if transformer is part of subgrid of this GridAgent val transformerUnit2W = transformerUnits2W - .find(element => element.getUuid == transformers) + .find(element => element.getUuid == transformer) val transformerUnit3W = transformerUnits3W - .find(element => element.getUuid == transformers) + .find(element => element.getUuid == transformer) if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { - transformer.measurements + controlGroup.measurements .map(UUID.fromString) .foreach { measurements => val measurementUnit = measurementUnits @@ -75,6 +75,6 @@ object GridAgentFailFast { } ) ) - + } } From 581d5802b32b8cf9e91b21945fe0ca765ed19023 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:20:14 +0200 Subject: [PATCH 028/123] Update src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala commit from review, direct apply of variable Co-authored-by: Sebastian Peter --- .../scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 09217d5c6e..6e0036b254 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -52,7 +52,7 @@ case object GridAgentFailFast { transformers => // Check if transformer is part of subgrid of this GridAgent val transformerUnit2W = transformerUnits2W - .find(element => element.getUuid == transformers) + .find(_.getUuid == transformer) val transformerUnit3W = transformerUnits3W .find(element => element.getUuid == transformers) if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { From 8b7b93da1bdcdb482a71888d51928033d849bf0e Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:22:52 +0200 Subject: [PATCH 029/123] change to direct apply of variable --- .../scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index fe34f56e05..0136772cda 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -53,14 +53,14 @@ object GridAgentFailFast { val transformerUnit2W = transformerUnits2W .find(_.getUuid == transformer) val transformerUnit3W = transformerUnits3W - .find(element => element.getUuid == transformer) + .find(_.getUuid == transformer) if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { controlGroup.measurements .map(UUID.fromString) .foreach { measurements => val measurementUnit = measurementUnits - .find(element => element.getUuid == measurements) + .find(_.getUuid == measurements) .getOrElse( throw new GridAgentInitializationException( s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." From 24793fd4db07050b30a677fad69323524c629a6f Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:23:51 +0200 Subject: [PATCH 030/123] singular measurment --- .../scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 0136772cda..a24e509e0e 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -58,9 +58,9 @@ object GridAgentFailFast { controlGroup.measurements .map(UUID.fromString) - .foreach { measurements => + .foreach { measurement => val measurementUnit = measurementUnits - .find(_.getUuid == measurements) + .find(_.getUuid == measurement) .getOrElse( throw new GridAgentInitializationException( s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." From dae0ea4e83f42fd7b025a3a0aadc09232824fca7 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:25:29 +0200 Subject: [PATCH 031/123] Update src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala more explicid test description 1 Co-authored-by: Sebastian Peter --- src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 64cd61890f..761f69f613 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -976,7 +976,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { }.getMessage shouldBe s"The minimum permissible voltage magnitude of a transformer control group (${dut.toString}) must be smaller than the maximum permissible voltage magnitude." } - "throw Exception when vMin is lower then -21% of nominal Voltage" in { + "throw Exception if vMin is lower than -20% of nominal Voltage" in { val dut = TransformerControlGroup( List("6888c53a-7629-4563-ac8e-840f80b03106"), List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), From 027d6d3c443b04e8660739dd400c2f20107ebdb1 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:25:43 +0200 Subject: [PATCH 032/123] Update src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala more explicid test description 2 Co-authored-by: Sebastian Peter --- src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 761f69f613..67b6bb055f 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -990,7 +990,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { "by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" } - "throw Exception when vMax is higher then +21% of nominal Voltage" in { + "throw Exception if vMax is higher than +20% of nominal Voltage" in { val dut = TransformerControlGroup( List("6888c53a-7629-4563-ac8e-840f80b03106"), List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), From 05c5e36073bd098c52e165931c4a0f32ea084f7e Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:27:17 +0200 Subject: [PATCH 033/123] remove unnecessary imports --- src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 26e198f0d7..42199475d7 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -11,8 +11,6 @@ import breeze.linalg.DenseMatrix import breeze.math.Complex import breeze.numerics.abs import edu.ie3.datamodel.exceptions.InvalidGridException -import edu.ie3.datamodel.models.input.MeasurementUnitInput -import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.TransformerControlGroup import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} @@ -23,9 +21,6 @@ import edu.ie3.simona.test.common.model.grid.{ FiveLinesWithNodes } import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} -import testutils.TestObjectFactory - -import scala.jdk.CollectionConverters.SetHasAsJava class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { From 14b046957ae6996d44022e51d2fca217cbaca667 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:29:18 +0200 Subject: [PATCH 034/123] spotless --- .../simona/agent/grid/GridAgentFailFast.scala | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index a24e509e0e..1e82c39e81 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -46,35 +46,34 @@ object GridAgentFailFast { gridAgentInitData.subGridContainer.getRawGrid.getTransformer3Ws.asScala maybeControlConfig.foreach(control => - control.transformer.foreach(controlGroup => - controlGroup.transformers.map(UUID.fromString).foreach { - transformer => - // Check if transformer is part of subgrid of this GridAgent - val transformerUnit2W = transformerUnits2W - .find(_.getUuid == transformer) - val transformerUnit3W = transformerUnits3W - .find(_.getUuid == transformer) - if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { + control.transformer.foreach(controlGroup => + controlGroup.transformers.map(UUID.fromString).foreach { transformer => + // Check if transformer is part of subgrid of this GridAgent + val transformerUnit2W = transformerUnits2W + .find(_.getUuid == transformer) + val transformerUnit3W = transformerUnits3W + .find(_.getUuid == transformer) + if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { - controlGroup.measurements - .map(UUID.fromString) - .foreach { measurement => - val measurementUnit = measurementUnits - .find(_.getUuid == measurement) - .getOrElse( - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." - ) - ) - if (!measurementUnit.getVMag) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." - ) - } + controlGroup.measurements + .map(UUID.fromString) + .foreach { measurement => + val measurementUnit = measurementUnits + .find(_.getUuid == measurement) + .getOrElse( + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." + ) + ) + if (!measurementUnit.getVMag) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." + ) } } - ) + } ) + ) } } From bf36273e687fb6323ed3dc66e0ea71a1f90a0059 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 15 Jul 2022 08:04:53 +0200 Subject: [PATCH 035/123] Scala Doc --- .../simona/agent/grid/GridAgentFailFast.scala | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 1e82c39e81..ffd588ad6d 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -6,6 +6,7 @@ package edu.ie3.simona.agent.grid +import edu.ie3.datamodel.models.input.container.SubGridContainer import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException @@ -15,6 +16,13 @@ import scala.jdk.CollectionConverters._ object GridAgentFailFast { + /** FailFast Check of GridAgent at Initialisation + * @param gridAgentInitData + * Data that is send to the [[GridAgent]] directly after startup. It + * contains the main information for initialization. + * @param simonaConfig + * the config that should be checked + */ def failFast( gridAgentInitData: GridAgentInitData, simonaConfig: SimonaConfig @@ -33,17 +41,34 @@ object GridAgentFailFast { /** Check if there exits voltage measurements for transformerControlGroups */ - val maybeControlConfig: Option[SimonaConfig.Simona.Control] = + checkControlGroupsForMeasurement( + gridAgentInitData.subGridContainer, simonaConfig.simona.control + ) + } + + /** Checks all ControlGroups if a) Transformer of ControlGroup and Measurement + * belongs to the same sub grid. b) Measurements are measure voltage + * magnitude. + * + * @param subGridContainer + * Container of all models for this sub grid + * @param maybeControlConfig + * Config of ControlGroup + */ + def checkControlGroupsForMeasurement( + subGridContainer: SubGridContainer, + maybeControlConfig: Option[SimonaConfig.Simona.Control] + ): Unit = { val measurementUnits = - gridAgentInitData.subGridContainer.getRawGrid.getMeasurementUnits.asScala + subGridContainer.getRawGrid.getMeasurementUnits.asScala val transformerUnits2W = - gridAgentInitData.subGridContainer.getRawGrid.getTransformer2Ws.asScala + subGridContainer.getRawGrid.getTransformer2Ws.asScala val transformerUnits3W = - gridAgentInitData.subGridContainer.getRawGrid.getTransformer3Ws.asScala + subGridContainer.getRawGrid.getTransformer3Ws.asScala maybeControlConfig.foreach(control => control.transformer.foreach(controlGroup => @@ -62,18 +87,17 @@ object GridAgentFailFast { .find(_.getUuid == measurement) .getOrElse( throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." + s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." ) ) if (!measurementUnit.getVMag) throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." + s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." ) } } } ) ) - } } From 2cc9e4083df1b08b62cf03b806c4331555fd3327 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 15 Jul 2022 08:16:31 +0200 Subject: [PATCH 036/123] More Scala Doc --- .../scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index ffd588ad6d..665430856b 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -73,13 +73,15 @@ object GridAgentFailFast { maybeControlConfig.foreach(control => control.transformer.foreach(controlGroup => controlGroup.transformers.map(UUID.fromString).foreach { transformer => - // Check if transformer is part of subgrid of this GridAgent val transformerUnit2W = transformerUnits2W .find(_.getUuid == transformer) val transformerUnit3W = transformerUnits3W .find(_.getUuid == transformer) + /** In order to check that the measurements are located in the subgrid + * of this GridAgent, it is first checked if the transformer belongs + * to this GridAgent and is therefore part of this subgrid. + */ if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { - controlGroup.measurements .map(UUID.fromString) .foreach { measurement => From 4abfe3898ff49ceaecefe3818b23b7f13dd44b15 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 15 Jul 2022 08:22:52 +0200 Subject: [PATCH 037/123] even more Scala Doc --- .../scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala | 1 + src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 665430856b..27d8d216c8 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -77,6 +77,7 @@ object GridAgentFailFast { .find(_.getUuid == transformer) val transformerUnit3W = transformerUnits3W .find(_.getUuid == transformer) + /** In order to check that the measurements are located in the subgrid * of this GridAgent, it is first checked if the transformer belongs * to this GridAgent and is therefore part of this subgrid. diff --git a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala index b068411a6d..dd3cf4cf84 100644 --- a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala +++ b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala @@ -567,7 +567,8 @@ case object ConfigFailFast extends LazyLogging { * * One important check cannot be performed at this place, as input data is * not available, yet: Do the measurements belong to a region, that can be - * influenced by the transformer? + * influenced by the transformer? This is partly addressed in + * [[edu.ie3.simona.agent.grid.GridAgentFailFast]] * * @param transformerControlGroup * Transformer control group definition From 10e066e544da5c1fa34016176fe729bd346336c7 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 3 Aug 2022 13:48:46 +0200 Subject: [PATCH 038/123] generate SimonaConfig and spotless --- .../edu/ie3/simona/config/SimonaConfig.scala | 39 +++++++++++++++++++ .../simona/config/ConfigFailFastSpec.scala | 6 ++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala index 3133b193c7..ca4f958fb3 100644 --- a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala +++ b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala @@ -675,6 +675,45 @@ object SimonaConfig { } + final case class TransformerControlGroup( + measurements: scala.List[java.lang.String], + transformers: scala.List[java.lang.String], + vMax: scala.Double, + vMin: scala.Double + ) + object TransformerControlGroup { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.TransformerControlGroup = { + SimonaConfig.TransformerControlGroup( + measurements = + $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), + transformers = + $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), + vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), + vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) + ) + } + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { + if (c == null) 0 + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } + } + + } + final case class VoltLvlConfig( id: java.lang.String, vNom: java.lang.String diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 13f7a7103b..b1db4feeb4 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -12,7 +12,11 @@ import edu.ie3.simona.config.SimonaConfig.Simona.Output.Sink import edu.ie3.simona.config.SimonaConfig.Simona.Output.Sink.{Csv, InfluxDb1x} import edu.ie3.simona.config.SimonaConfig.Simona.Powerflow.Newtonraphson import edu.ie3.simona.config.SimonaConfig.Simona.{Powerflow, Time} -import edu.ie3.simona.config.SimonaConfig.{BaseCsvParams, ResultKafkaParams, TransformerControlGroup} +import edu.ie3.simona.config.SimonaConfig.{ + BaseCsvParams, + ResultKafkaParams, + TransformerControlGroup +} import edu.ie3.simona.exceptions.InvalidConfigParameterException import edu.ie3.simona.test.common.{ConfigTestData, UnitSpec} import edu.ie3.simona.util.ConfigUtil.{CsvConfigUtil, NotifierIdentifier} From c446b9b9b19e1e93d37a32fca4c308620c80443d Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 3 Aug 2022 14:00:10 +0200 Subject: [PATCH 039/123] change gradletasks to name change of simona-config-template --- gradle/scripts/tscfg.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/scripts/tscfg.gradle b/gradle/scripts/tscfg.gradle index e81ad99320..d9ee8bca7b 100644 --- a/gradle/scripts/tscfg.gradle +++ b/gradle/scripts/tscfg.gradle @@ -15,7 +15,7 @@ task genConfigClass { args = [ "build/tscfg-${tscfgVersion}.jar", "--spec", - "src/main/resources/config/config-template.conf", + "src/main/resources/config/simona-config-template.conf", "--scala", "--durations", "--pn", @@ -47,7 +47,7 @@ task genConfigSample { args = [ "build/tscfg-${tscfgVersion}.jar", "--spec", - "src/main/resources/config/config-template.conf", + "src/main/resources/config/simona-config-template.conf", "--tpl", "input/samples/configSample.conf" ] From 26a4b8317d01545788b804d34c9de2fe46d9f3ca Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 3 Aug 2022 14:03:06 +0200 Subject: [PATCH 040/123] generate SimonaConfig and spotless --- .../edu/ie3/simona/config/SimonaConfig.scala | 75 +++++++++++++++++++ .../simona/config/ConfigFailFastSpec.scala | 6 +- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala index 1ace3e57f9..ca4f958fb3 100644 --- a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala +++ b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala @@ -675,6 +675,45 @@ object SimonaConfig { } + final case class TransformerControlGroup( + measurements: scala.List[java.lang.String], + transformers: scala.List[java.lang.String], + vMax: scala.Double, + vMin: scala.Double + ) + object TransformerControlGroup { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.TransformerControlGroup = { + SimonaConfig.TransformerControlGroup( + measurements = + $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), + transformers = + $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), + vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), + vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) + ) + } + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.Double = { + if (c == null) 0 + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } + } + + } + final case class VoltLvlConfig( id: java.lang.String, vNom: java.lang.String @@ -769,6 +808,7 @@ object SimonaConfig { } final case class Simona( + control: scala.Option[SimonaConfig.Simona.Control], event: SimonaConfig.Simona.Event, gridConfig: SimonaConfig.Simona.GridConfig, input: SimonaConfig.Simona.Input, @@ -779,6 +819,41 @@ object SimonaConfig { time: SimonaConfig.Simona.Time ) object Simona { + final case class Control( + transformer: scala.List[SimonaConfig.TransformerControlGroup] + ) + object Control { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): SimonaConfig.Simona.Control = { + SimonaConfig.Simona.Control( + transformer = $_LSimonaConfig_TransformerControlGroup( + c.getList("transformer"), + parentPath, + $tsCfgValidator + ) + ) + } + private def $_LSimonaConfig_TransformerControlGroup( + cl: com.typesafe.config.ConfigList, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator + ): scala.List[SimonaConfig.TransformerControlGroup] = { + import scala.jdk.CollectionConverters._ + cl.asScala + .map(cv => + SimonaConfig.TransformerControlGroup( + cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, + parentPath, + $tsCfgValidator + ) + ) + .toList + } + } + final case class Event( listener: scala.Option[ scala.List[SimonaConfig.Simona.Event.Listener$Elm] diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 42de85365e..d83aa551e0 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -12,7 +12,11 @@ import edu.ie3.simona.config.SimonaConfig.Simona.Output.Sink import edu.ie3.simona.config.SimonaConfig.Simona.Output.Sink.{Csv, InfluxDb1x} import edu.ie3.simona.config.SimonaConfig.Simona.Powerflow.Newtonraphson import edu.ie3.simona.config.SimonaConfig.Simona.{Powerflow, Time} -import edu.ie3.simona.config.SimonaConfig.{BaseCsvParams, ResultKafkaParams, TransformerControlGroup} +import edu.ie3.simona.config.SimonaConfig.{ + BaseCsvParams, + ResultKafkaParams, + TransformerControlGroup +} import edu.ie3.simona.exceptions.InvalidConfigParameterException import edu.ie3.simona.test.common.{ConfigTestData, UnitSpec} import edu.ie3.simona.util.ConfigUtil.{CsvConfigUtil, NotifierIdentifier} From f36c5b290497717fa66149d110eddcbaaf061468 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 6 Sep 2022 12:40:39 +0200 Subject: [PATCH 041/123] merge --- .../edu/ie3/simona/model/grid/GridModel.scala | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 9f5e0ac83e..5e49eba51e 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -9,11 +9,15 @@ package edu.ie3.simona.model.grid import breeze.linalg.DenseMatrix import breeze.math.Complex import edu.ie3.datamodel.exceptions.InvalidGridException -import edu.ie3.datamodel.models.input.{MeasurementUnitInput, NodeInput} -import edu.ie3.datamodel.models.input.connector._ +import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup +import edu.ie3.datamodel.models.input.MeasurementUnitInput +import edu.ie3.datamodel.models.input.connector.{ + ConnectorInput, + ConnectorPort, + Transformer3WInput +} import edu.ie3.datamodel.models.input.container.SubGridContainer import edu.ie3.simona.config.SimonaConfig -import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.SystemComponent import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} @@ -22,9 +26,6 @@ import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseB, PowerFlowCaseC } -import edu.ie3.simona.model.control.{ - TransformerControlGroup => ControlGroupModel -} import edu.ie3.simona.util.CollectionUtils import edu.ie3.util.quantities.PowerSystemUnits import org.jgrapht.Graph @@ -32,6 +33,9 @@ import org.jgrapht.alg.connectivity.ConnectivityInspector import org.jgrapht.graph.{DefaultEdge, SimpleGraph} import tech.units.indriya.ComparableQuantity import tech.units.indriya.quantity.Quantities +import edu.ie3.simona.model.control.{ + TransformerControlGroup => ControlGroupModel +} import java.time.ZonedDateTime import java.util.UUID From 4a61fa451b44527d3e7aff529e71f2220578d511 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 8 Feb 2023 14:37:51 +0100 Subject: [PATCH 042/123] rtd for transformer control groups --- docs/readthedocs/measurement_control.md | 9 +++++++++ docs/readthedocs/models.md | 6 ++++++ 2 files changed, 15 insertions(+) create mode 100644 docs/readthedocs/measurement_control.md diff --git a/docs/readthedocs/measurement_control.md b/docs/readthedocs/measurement_control.md new file mode 100644 index 0000000000..11b2a4ba07 --- /dev/null +++ b/docs/readthedocs/measurement_control.md @@ -0,0 +1,9 @@ +(measurement_control)= + +# Measurement and Control + +This page gives an overview of available Measurement and Control functions in *SIMONA*. + +## Transformer Control groups + +Transformer control group can be used to implement control functionalities like long-range control for active voltage stability. For this purpose, network areas and transformers can be logically linked to a control group via measuring points. If a deviation from the target voltage magnitude is detected at one of the measuring points, the transformer is switched to the appropriate tap position to solve the deviation, provided that no limit values are violated at other measuring points. This requires that only measuring points are included in control groups that can also be influenced by the associated transformer diff --git a/docs/readthedocs/models.md b/docs/readthedocs/models.md index 482d2abd15..ec65d0cbc4 100644 --- a/docs/readthedocs/models.md +++ b/docs/readthedocs/models.md @@ -31,3 +31,9 @@ models/load_model models/pv_model models/wec_model ``` + +## Measurement and Control +```{toctree} +--- +maxdepth: 1 +--- \ No newline at end of file From 6eaf9fdb09788b061147b8ccdaf3b3fb25a2f53b Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 8 Feb 2023 14:44:18 +0100 Subject: [PATCH 043/123] rtd for transformer control groups --- docs/readthedocs/models.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/readthedocs/models.md b/docs/readthedocs/models.md index ec65d0cbc4..fd1fb07e84 100644 --- a/docs/readthedocs/models.md +++ b/docs/readthedocs/models.md @@ -36,4 +36,5 @@ models/wec_model ```{toctree} --- maxdepth: 1 ---- \ No newline at end of file +--- +measurement_control From 5107c506af952855dd5d7db4d96706709d2c729e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 8 Feb 2023 14:50:11 +0100 Subject: [PATCH 044/123] rtd for transformer control groups --- docs/readthedocs/measurement_control.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/readthedocs/measurement_control.md b/docs/readthedocs/measurement_control.md index 11b2a4ba07..8913f2a753 100644 --- a/docs/readthedocs/measurement_control.md +++ b/docs/readthedocs/measurement_control.md @@ -1,9 +1,5 @@ -(measurement_control)= +(transformer_control_groups)= -# Measurement and Control - -This page gives an overview of available Measurement and Control functions in *SIMONA*. - -## Transformer Control groups +# Transformer Control groups Transformer control group can be used to implement control functionalities like long-range control for active voltage stability. For this purpose, network areas and transformers can be logically linked to a control group via measuring points. If a deviation from the target voltage magnitude is detected at one of the measuring points, the transformer is switched to the appropriate tap position to solve the deviation, provided that no limit values are violated at other measuring points. This requires that only measuring points are included in control groups that can also be influenced by the associated transformer From 0bf2e69ea046f6ff4232428e68014ab1bb4f6f42 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 8 Feb 2023 14:52:29 +0100 Subject: [PATCH 045/123] typo --- docs/readthedocs/measurement_control.md | 2 +- docs/readthedocs/models.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/readthedocs/measurement_control.md b/docs/readthedocs/measurement_control.md index 8913f2a753..243ed82975 100644 --- a/docs/readthedocs/measurement_control.md +++ b/docs/readthedocs/measurement_control.md @@ -1,5 +1,5 @@ (transformer_control_groups)= -# Transformer Control groups +# Transformer Control Groups Transformer control group can be used to implement control functionalities like long-range control for active voltage stability. For this purpose, network areas and transformers can be logically linked to a control group via measuring points. If a deviation from the target voltage magnitude is detected at one of the measuring points, the transformer is switched to the appropriate tap position to solve the deviation, provided that no limit values are violated at other measuring points. This requires that only measuring points are included in control groups that can also be influenced by the associated transformer diff --git a/docs/readthedocs/models.md b/docs/readthedocs/models.md index fd1fb07e84..6981a8e308 100644 --- a/docs/readthedocs/models.md +++ b/docs/readthedocs/models.md @@ -37,4 +37,4 @@ models/wec_model --- maxdepth: 1 --- -measurement_control +transformer_control_groups From be6f3a9cfe161d686db9d93036eb2bf0a6650b0c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 15 Mar 2023 11:10:37 +0100 Subject: [PATCH 046/123] typo --- docs/readthedocs/models.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/readthedocs/models.md b/docs/readthedocs/models.md index 6981a8e308..402b66908b 100644 --- a/docs/readthedocs/models.md +++ b/docs/readthedocs/models.md @@ -38,3 +38,4 @@ models/wec_model maxdepth: 1 --- transformer_control_groups +``` \ No newline at end of file From 106ef522e4686230dc2451aa751363e0d0e92aab Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 15 Mar 2023 11:25:35 +0100 Subject: [PATCH 047/123] rtd --- docs/readthedocs/measurement_control.md | 4 ++-- docs/readthedocs/models.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/readthedocs/measurement_control.md b/docs/readthedocs/measurement_control.md index 243ed82975..e57238d6a6 100644 --- a/docs/readthedocs/measurement_control.md +++ b/docs/readthedocs/measurement_control.md @@ -1,5 +1,5 @@ -(transformer_control_groups)= +(measurement_control)= # Transformer Control Groups -Transformer control group can be used to implement control functionalities like long-range control for active voltage stability. For this purpose, network areas and transformers can be logically linked to a control group via measuring points. If a deviation from the target voltage magnitude is detected at one of the measuring points, the transformer is switched to the appropriate tap position to solve the deviation, provided that no limit values are violated at other measuring points. This requires that only measuring points are included in control groups that can also be influenced by the associated transformer +Transformer control group can be used to implement control functionalities like long-range control for active voltage stability. For this purpose, network areas and transformers can be logically linked to a control group via measuring points. If a deviation from the target voltage magnitude is detected at one of the measuring points, the transformer is switched to the appropriate tap position to solve the deviation, provided that no limit values are violated at other measuring points. This requires that only measuring points are included in control groups that can also be influenced by the associated transformer. diff --git a/docs/readthedocs/models.md b/docs/readthedocs/models.md index 402b66908b..0dcd569d64 100644 --- a/docs/readthedocs/models.md +++ b/docs/readthedocs/models.md @@ -37,5 +37,5 @@ models/wec_model --- maxdepth: 1 --- -transformer_control_groups -``` \ No newline at end of file +measurement_control +``` From 236c18cf66bccfcd12a833795c4211b5878ab466 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 25 Apr 2023 16:58:03 +0200 Subject: [PATCH 048/123] fix BasicGridWithSwitches --- .../edu/ie3/simona/model/grid/GridModel.scala | 19 ++++++++++--------- .../edu/ie3/simona/model/grid/GridSpec.scala | 2 +- .../model/grid/BasicGridWithSwitches.scala | 13 ++++--------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 5dfbb048f5..5cd11970d2 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -9,22 +9,16 @@ package edu.ie3.simona.model.grid import breeze.linalg.DenseMatrix import breeze.math.Complex import edu.ie3.datamodel.exceptions.InvalidGridException -import edu.ie3.datamodel.models.input.{MeasurementUnitInput, NodeInput} +import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.input.connector._ import edu.ie3.datamodel.models.input.container.SubGridContainer import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.SystemComponent +import edu.ie3.simona.model.control.{TransformerControlGroup => ControlGroupModel} import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} -import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ - PowerFlowCaseA, - PowerFlowCaseB, - PowerFlowCaseC -} -import edu.ie3.simona.model.control.{ - TransformerControlGroup => ControlGroupModel -} +import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{PowerFlowCaseA, PowerFlowCaseB, PowerFlowCaseC} import edu.ie3.simona.util.CollectionUtils import edu.ie3.util.quantities.PowerSystemUnits import org.jgrapht.Graph @@ -105,6 +99,13 @@ case object GridModel { transformerControlGroups: Set[ControlGroupModel] ) + /** Represents an empty Transformer control groups + * + */ + val EMPTY_GRID_CONTROLS: GridControls = GridControls( + Set.empty[ControlGroupModel] + ) + /** Checks the availability of node calculation models, that are connected by * the given [[ConnectorInput]]. If not both models can be found, * [[InvalidGridException]] s are thrown diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 439af5a255..560bacf17f 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -287,7 +287,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], switches ), - GridControls(Set.empty[TransformerControlGroup]) + Set.empty[ControlGroupModel] ) // get the private method for validation diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index c9270e0888..fec4c39d46 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -6,14 +6,8 @@ package edu.ie3.simona.test.common.model.grid -import edu.ie3.simona.model.grid.GridModel.GridComponents -import edu.ie3.simona.model.grid.{ - GridModel, - LineModel, - NodeModel, - SwitchModel, - Transformer3wModel -} +import edu.ie3.simona.model.grid.GridModel.{EMPTY_GRID_CONTROLS, GridComponents, GridControls} +import edu.ie3.simona.model.grid.{GridModel, LineModel, NodeModel, SwitchModel, Transformer3wModel} import edu.ie3.util.quantities.PowerSystemUnits._ import tech.units.indriya.quantity.Quantities @@ -229,7 +223,8 @@ trait BasicGridWithSwitches extends BasicGrid { Set(transformer2wModel), Set.empty[Transformer3wModel], gridSwitches - ) + ), + EMPTY_GRID_CONTROLS, ) } From 758ae20442188ace0caa0f899151c8130e224c3d Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 25 Apr 2023 17:02:45 +0200 Subject: [PATCH 049/123] fix GridSpec --- src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 560bacf17f..19f1f48fee 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -15,7 +15,11 @@ import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.TransformerControlGroup -import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} +import edu.ie3.simona.model.grid.GridModel.{ + EMPTY_GRID_CONTROLS, + GridComponents, + GridControls +} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} import edu.ie3.simona.test.common.model.grid.{ BasicGrid, @@ -26,7 +30,6 @@ import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} import testutils.TestObjectFactory import scala.jdk.CollectionConverters.SetHasAsJava - import java.util.UUID class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { @@ -287,7 +290,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], switches ), - Set.empty[ControlGroupModel] + EMPTY_GRID_CONTROLS ) // get the private method for validation From 4810475d9d02fe400a1559402ca196111a1ddb7d Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 25 Apr 2023 17:03:08 +0200 Subject: [PATCH 050/123] fmt --- .../edu/ie3/simona/model/grid/GridModel.scala | 11 ++++++++--- .../model/grid/BasicGridWithSwitches.scala | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 5cd11970d2..55bb02069d 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -16,9 +16,15 @@ import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.SystemComponent -import edu.ie3.simona.model.control.{TransformerControlGroup => ControlGroupModel} +import edu.ie3.simona.model.control.{ + TransformerControlGroup => ControlGroupModel +} import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} -import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{PowerFlowCaseA, PowerFlowCaseB, PowerFlowCaseC} +import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ + PowerFlowCaseA, + PowerFlowCaseB, + PowerFlowCaseC +} import edu.ie3.simona.util.CollectionUtils import edu.ie3.util.quantities.PowerSystemUnits import org.jgrapht.Graph @@ -100,7 +106,6 @@ case object GridModel { ) /** Represents an empty Transformer control groups - * */ val EMPTY_GRID_CONTROLS: GridControls = GridControls( Set.empty[ControlGroupModel] diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index fec4c39d46..226e46a82f 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -6,8 +6,18 @@ package edu.ie3.simona.test.common.model.grid -import edu.ie3.simona.model.grid.GridModel.{EMPTY_GRID_CONTROLS, GridComponents, GridControls} -import edu.ie3.simona.model.grid.{GridModel, LineModel, NodeModel, SwitchModel, Transformer3wModel} +import edu.ie3.simona.model.grid.GridModel.{ + EMPTY_GRID_CONTROLS, + GridComponents, + GridControls +} +import edu.ie3.simona.model.grid.{ + GridModel, + LineModel, + NodeModel, + SwitchModel, + Transformer3wModel +} import edu.ie3.util.quantities.PowerSystemUnits._ import tech.units.indriya.quantity.Quantities @@ -224,7 +234,7 @@ trait BasicGridWithSwitches extends BasicGrid { Set.empty[Transformer3wModel], gridSwitches ), - EMPTY_GRID_CONTROLS, + EMPTY_GRID_CONTROLS ) } From d11a1982758b7e9118665665d97114f659487e20 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 25 Apr 2023 17:09:04 +0200 Subject: [PATCH 051/123] fix BasicGridWithSwitches and GridSpec --- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 6 ++++++ src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala | 2 +- .../test/common/model/grid/BasicGridWithSwitches.scala | 9 +++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index ace9679725..d49f27bd1f 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -109,6 +109,12 @@ case object GridModel { transformerControlGroups: Set[ControlGroupModel] ) + /** Represents an empty Transformer control groups + */ + val EMPTY_GRID_CONTROLS: GridControls = GridControls( + Set.empty[ControlGroupModel] + ) + /** Checks the availability of node calculation models, that are connected by * the given [[ConnectorInput]]. If not both models can be found, * [[InvalidGridException]] s are thrown diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index cc84552b53..4f2c3f3403 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -282,7 +282,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], switches ), - GridControls(Set.empty[TransformerControlGroup]) + EMPTY_GRID_CONTROLS ) // get the private method for validation diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index c9270e0888..226e46a82f 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -6,7 +6,11 @@ package edu.ie3.simona.test.common.model.grid -import edu.ie3.simona.model.grid.GridModel.GridComponents +import edu.ie3.simona.model.grid.GridModel.{ + EMPTY_GRID_CONTROLS, + GridComponents, + GridControls +} import edu.ie3.simona.model.grid.{ GridModel, LineModel, @@ -229,7 +233,8 @@ trait BasicGridWithSwitches extends BasicGrid { Set(transformer2wModel), Set.empty[Transformer3wModel], gridSwitches - ) + ), + EMPTY_GRID_CONTROLS ) } From 5c7c88569a7903541b629e3650d2625d01d49d66 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 25 Apr 2023 17:13:42 +0200 Subject: [PATCH 052/123] fix BasicGridWithSwitches and GridSpec --- src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 4f2c3f3403..1ec9814682 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -13,13 +13,9 @@ import breeze.numerics.abs import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.TransformerControlGroup -import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} +import edu.ie3.simona.model.grid.GridModel.{EMPTY_GRID_CONTROLS, GridComponents, GridControls} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} -import edu.ie3.simona.test.common.model.grid.{ - BasicGrid, - BasicGridWithSwitches, - FiveLinesWithNodes -} +import edu.ie3.simona.test.common.model.grid.{BasicGrid, BasicGridWithSwitches, FiveLinesWithNodes} import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} import java.util.UUID From 2ea2e4634ceb5246c197d02f9389e5bca9186e9e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 25 Apr 2023 17:17:56 +0200 Subject: [PATCH 053/123] fmt --- .../scala/edu/ie3/simona/model/grid/GridSpec.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 1ec9814682..8a7f210c2d 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -13,9 +13,17 @@ import breeze.numerics.abs import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.TransformerControlGroup -import edu.ie3.simona.model.grid.GridModel.{EMPTY_GRID_CONTROLS, GridComponents, GridControls} +import edu.ie3.simona.model.grid.GridModel.{ + EMPTY_GRID_CONTROLS, + GridComponents, + GridControls +} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} -import edu.ie3.simona.test.common.model.grid.{BasicGrid, BasicGridWithSwitches, FiveLinesWithNodes} +import edu.ie3.simona.test.common.model.grid.{ + BasicGrid, + BasicGridWithSwitches, + FiveLinesWithNodes +} import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} import java.util.UUID From 60a9cb768945acad600818215dbe8967c217493a Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Sep 2023 20:50:39 +0200 Subject: [PATCH 054/123] codacy --- .../edu/ie3/simona/model/grid/GridModel.scala | 45 +++++++++++-------- .../edu/ie3/simona/model/grid/GridSpec.scala | 5 +-- .../model/grid/BasicGridWithSwitches.scala | 4 +- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index dfa6d64fb9..e6a1ab2f02 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -107,7 +107,7 @@ case object GridModel { /** Represents an empty Transformer control groups */ - val EMPTY_GRID_CONTROLS: GridControls = GridControls( + val emptyGridControls: GridControls = GridControls( Set.empty[ControlGroupModel] ) @@ -687,14 +687,19 @@ case object GridModel { val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => uuid -> { (complexVoltage: Complex) => { - val vMag = complexVoltage.abs - if (vMag > vMax) - Some(vMax - vMag) - else if (vMag < vMin) - Some(vMin - vMag) - else - None - }.map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + complexVoltage.abs match { + case vMag if { + vMag > vMax + } => + Some(vMax - vMag) + case vMag if { + vMag < vMax + } => + Some(vMin - vMag) + case _ => None + } + } + .map(Quantities.getQuantity(_, PowerSystemUnits.PU)) } }.toMap @@ -707,16 +712,20 @@ case object GridModel { _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) ) - if (negativeRequests.nonEmpty && positiveRequests.nonEmpty) { - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - } else if (negativeRequests.nonEmpty) { - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - } else { - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None } + } ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 19f1f48fee..6d50e2da8a 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -16,7 +16,7 @@ import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.TransformerControlGroup import edu.ie3.simona.model.grid.GridModel.{ - EMPTY_GRID_CONTROLS, + emptyGridControls, GridComponents, GridControls } @@ -30,7 +30,6 @@ import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} import testutils.TestObjectFactory import scala.jdk.CollectionConverters.SetHasAsJava -import java.util.UUID class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { @@ -290,7 +289,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], switches ), - EMPTY_GRID_CONTROLS + emptyGridControls ) // get the private method for validation diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index 226e46a82f..781a9e7620 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -7,7 +7,7 @@ package edu.ie3.simona.test.common.model.grid import edu.ie3.simona.model.grid.GridModel.{ - EMPTY_GRID_CONTROLS, + emptyGridControls, GridComponents, GridControls } @@ -234,7 +234,7 @@ trait BasicGridWithSwitches extends BasicGrid { Set.empty[Transformer3wModel], gridSwitches ), - EMPTY_GRID_CONTROLS + emptyGridControls ) } From 4ce037f8b05103e8b699cebc18a368adf48e2f2f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Sep 2023 20:54:37 +0200 Subject: [PATCH 055/123] codacy --- .../edu/ie3/simona/model/grid/GridModel.scala | 45 +++++++++++-------- .../edu/ie3/simona/model/grid/GridSpec.scala | 6 +-- .../model/grid/BasicGridWithSwitches.scala | 4 +- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index cea9720bb0..1c9c01d93c 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -111,7 +111,7 @@ case object GridModel { /** Represents an empty Transformer control groups */ - val EMPTY_GRID_CONTROLS: GridControls = GridControls( + val emptyGridControls: GridControls = GridControls( Set.empty[ControlGroupModel] ) @@ -691,14 +691,19 @@ case object GridModel { val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => uuid -> { (complexVoltage: Complex) => { - val vMag = complexVoltage.abs - if (vMag > vMax) - Some(vMax - vMag) - else if (vMag < vMin) - Some(vMin - vMag) - else - None - }.map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + complexVoltage.abs match { + case vMag if { + vMag > vMax + } => + Some(vMax - vMag) + case vMag if { + vMag < vMax + } => + Some(vMin - vMag) + case _ => None + } + } + .map(Quantities.getQuantity(_, PowerSystemUnits.PU)) } }.toMap @@ -711,16 +716,20 @@ case object GridModel { _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) ) - if (negativeRequests.nonEmpty && positiveRequests.nonEmpty) { - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - } else if (negativeRequests.nonEmpty) { - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - } else { - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None } + } ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 8a7f210c2d..d1f05ff66a 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -14,7 +14,7 @@ import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.TransformerControlGroup import edu.ie3.simona.model.grid.GridModel.{ - EMPTY_GRID_CONTROLS, + emptyGridControls, GridComponents, GridControls } @@ -26,8 +26,6 @@ import edu.ie3.simona.test.common.model.grid.{ } import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} -import java.util.UUID - class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { private val _printAdmittanceMatrixOnMismatch @@ -286,7 +284,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], switches ), - EMPTY_GRID_CONTROLS + emptyGridControls ) // get the private method for validation diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index 226e46a82f..781a9e7620 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -7,7 +7,7 @@ package edu.ie3.simona.test.common.model.grid import edu.ie3.simona.model.grid.GridModel.{ - EMPTY_GRID_CONTROLS, + emptyGridControls, GridComponents, GridControls } @@ -234,7 +234,7 @@ trait BasicGridWithSwitches extends BasicGrid { Set.empty[Transformer3wModel], gridSwitches ), - EMPTY_GRID_CONTROLS + emptyGridControls ) } From dbe8de721682544487f0dc11dc5097202ff820a1 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Sep 2023 21:19:29 +0200 Subject: [PATCH 056/123] fix test --- .../edu/ie3/simona/model/grid/GridModel.scala | 159 +++++++++--------- 1 file changed, 76 insertions(+), 83 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index e6a1ab2f02..780314d4cb 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -685,97 +685,90 @@ case object GridModel { ): ControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> { (complexVoltage: Complex) => - { - complexVoltage.abs match { - case vMag if { - vMag > vMax - } => - Some(vMax - vMag) - case vMag if { - vMag < vMax - } => - Some(vMin - vMag) + uuid -> { + (complexVoltage: Complex) => + val vMag = complexVoltage.abs + vMag match { + case mag if mag > vMax => Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + case mag if mag < vMin => Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) case _ => None } - } - .map(Quantities.getQuantity(_, PowerSystemUnits.PU)) } }.toMap - val harmonizationFunction = - (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { - val negativeRequests = regulationRequests.filter( - _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) - val positiveRequests = regulationRequests.filter( - _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) - - (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { - case (true, true) => - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - case (true, false) => - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - case (false, true) => - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption - case _ => - None - } - - } - - ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) - } + val harmonizationFunction = + (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { + val negativeRequests = regulationRequests.filter( + _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) + val positiveRequests = regulationRequests.filter( + _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) - /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to - * account for changes on switches (open / close) It is highly recommended (= - * mandatory) to call this method every time a node admittance matrix is - * needed after a switch status has changed. - * - * @param gridModel - * the grid model we operate on - */ - def updateUuidToIndexMap(gridModel: GridModel): Unit = { + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None + } - val switches = gridModel.gridComponents.switches - val nodes = gridModel.gridComponents.nodes + } - val nodesAndSwitches: ListSet[SystemComponent] = ListSet - .empty[SystemComponent] ++ switches ++ nodes + ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) + } - val updatedNodeToUuidMap = nodesAndSwitches - .filter(_.isInOperation) - .filter { - case switch: SwitchModel => switch.isClosed - case _: NodeModel => true - } - .zipWithIndex - .foldLeft(Map.empty[UUID, Int]) { - case (map, (gridComponent, componentId)) => - gridComponent match { - case switchModel: SwitchModel => - map ++ Map( - switchModel.nodeAUuid -> componentId, - switchModel.nodeBUuid -> componentId - ) - - case nodeModel: NodeModel => - if (!map.contains(nodeModel.uuid)) { - val idx = map.values.toList.sorted.lastOption - .getOrElse( - -1 - ) + 1 // if we didn't found anything in the list, we don't have switches and want to start @ 0 - map + (nodeModel.uuid -> idx) - } else { - map - } - } - } + /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to + * account for changes on switches (open / close) It is highly recommended (= + * mandatory) to call this method every time a node admittance matrix is + * needed after a switch status has changed. + * + * @param gridModel + * the grid model we operate on + */ + def updateUuidToIndexMap(gridModel: GridModel): Unit = { + + val switches = gridModel.gridComponents.switches + val nodes = gridModel.gridComponents.nodes + + val nodesAndSwitches: ListSet[SystemComponent] = ListSet + .empty[SystemComponent] ++ switches ++ nodes + + val updatedNodeToUuidMap = nodesAndSwitches + .filter(_.isInOperation) + .filter { + case switch: SwitchModel => switch.isClosed + case _: NodeModel => true + } + .zipWithIndex + .foldLeft(Map.empty[UUID, Int]) { + case (map, (gridComponent, componentId)) => + gridComponent match { + case switchModel: SwitchModel => + map ++ Map( + switchModel.nodeAUuid -> componentId, + switchModel.nodeBUuid -> componentId + ) + + case nodeModel: NodeModel => + if (!map.contains(nodeModel.uuid)) { + val idx = map.values.toList.sorted.lastOption + .getOrElse( + -1 + ) + 1 // if we didn't found anything in the list, we don't have switches and want to start @ 0 + map + (nodeModel.uuid -> idx) + } else { + map + } + } + } - gridModel._nodeUuidToIndexMap = updatedNodeToUuidMap + gridModel._nodeUuidToIndexMap = updatedNodeToUuidMap + } } -} From 0854e085304fd1353eab4a3e9b66f5c7171895aa Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Sep 2023 21:21:01 +0200 Subject: [PATCH 057/123] fix test --- .../edu/ie3/simona/model/grid/GridModel.scala | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 1c9c01d93c..4bbd017701 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -689,21 +689,14 @@ case object GridModel { ): ControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> { (complexVoltage: Complex) => - { - complexVoltage.abs match { - case vMag if { - vMag > vMax - } => - Some(vMax - vMag) - case vMag if { - vMag < vMax - } => - Some(vMin - vMag) + uuid -> { + (complexVoltage: Complex) => + val vMag = complexVoltage.abs + vMag match { + case mag if mag > vMax => Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + case mag if mag < vMin => Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) case _ => None } - } - .map(Quantities.getQuantity(_, PowerSystemUnits.PU)) } }.toMap From 051fbedf80494085dddff8d78c04397a2c4d79d5 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Sep 2023 21:24:30 +0200 Subject: [PATCH 058/123] spotless --- .../edu/ie3/simona/model/grid/GridModel.scala | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 4bbd017701..8dbb1a4424 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -689,14 +689,15 @@ case object GridModel { ): ControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> { - (complexVoltage: Complex) => - val vMag = complexVoltage.abs - vMag match { - case mag if mag > vMax => Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) - case mag if mag < vMin => Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) - case _ => None - } + uuid -> { (complexVoltage: Complex) => + val vMag = complexVoltage.abs + vMag match { + case mag if mag > vMax => + Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + case mag if mag < vMin => + Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + case _ => None + } } }.toMap From b180043fbbe0d4504c3a0ad7e2a79c641ee59fc8 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Sep 2023 21:25:36 +0200 Subject: [PATCH 059/123] spotless --- .../edu/ie3/simona/model/grid/GridModel.scala | 157 +++++++++--------- 1 file changed, 79 insertions(+), 78 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 780314d4cb..c01455d731 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -685,90 +685,91 @@ case object GridModel { ): ControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> { - (complexVoltage: Complex) => - val vMag = complexVoltage.abs - vMag match { - case mag if mag > vMax => Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) - case mag if mag < vMin => Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) - case _ => None - } + uuid -> { (complexVoltage: Complex) => + val vMag = complexVoltage.abs + vMag match { + case mag if mag > vMax => + Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + case mag if mag < vMin => + Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + case _ => None + } } }.toMap - val harmonizationFunction = - (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { - val negativeRequests = regulationRequests.filter( - _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) - val positiveRequests = regulationRequests.filter( - _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) - - (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { - case (true, true) => - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - case (true, false) => - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - case (false, true) => - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption - case _ => - None - } + val harmonizationFunction = + (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { + val negativeRequests = regulationRequests.filter( + _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) + val positiveRequests = regulationRequests.filter( + _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) + ) + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None } - ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) - } + } - /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to - * account for changes on switches (open / close) It is highly recommended (= - * mandatory) to call this method every time a node admittance matrix is - * needed after a switch status has changed. - * - * @param gridModel - * the grid model we operate on - */ - def updateUuidToIndexMap(gridModel: GridModel): Unit = { - - val switches = gridModel.gridComponents.switches - val nodes = gridModel.gridComponents.nodes - - val nodesAndSwitches: ListSet[SystemComponent] = ListSet - .empty[SystemComponent] ++ switches ++ nodes - - val updatedNodeToUuidMap = nodesAndSwitches - .filter(_.isInOperation) - .filter { - case switch: SwitchModel => switch.isClosed - case _: NodeModel => true - } - .zipWithIndex - .foldLeft(Map.empty[UUID, Int]) { - case (map, (gridComponent, componentId)) => - gridComponent match { - case switchModel: SwitchModel => - map ++ Map( - switchModel.nodeAUuid -> componentId, - switchModel.nodeBUuid -> componentId - ) - - case nodeModel: NodeModel => - if (!map.contains(nodeModel.uuid)) { - val idx = map.values.toList.sorted.lastOption - .getOrElse( - -1 - ) + 1 // if we didn't found anything in the list, we don't have switches and want to start @ 0 - map + (nodeModel.uuid -> idx) - } else { - map - } - } - } + ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) + } - gridModel._nodeUuidToIndexMap = updatedNodeToUuidMap - } + /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to + * account for changes on switches (open / close) It is highly recommended (= + * mandatory) to call this method every time a node admittance matrix is + * needed after a switch status has changed. + * + * @param gridModel + * the grid model we operate on + */ + def updateUuidToIndexMap(gridModel: GridModel): Unit = { + + val switches = gridModel.gridComponents.switches + val nodes = gridModel.gridComponents.nodes + + val nodesAndSwitches: ListSet[SystemComponent] = ListSet + .empty[SystemComponent] ++ switches ++ nodes + + val updatedNodeToUuidMap = nodesAndSwitches + .filter(_.isInOperation) + .filter { + case switch: SwitchModel => switch.isClosed + case _: NodeModel => true + } + .zipWithIndex + .foldLeft(Map.empty[UUID, Int]) { + case (map, (gridComponent, componentId)) => + gridComponent match { + case switchModel: SwitchModel => + map ++ Map( + switchModel.nodeAUuid -> componentId, + switchModel.nodeBUuid -> componentId + ) + + case nodeModel: NodeModel => + if (!map.contains(nodeModel.uuid)) { + val idx = map.values.toList.sorted.lastOption + .getOrElse( + -1 + ) + 1 // if we didn't found anything in the list, we don't have switches and want to start @ 0 + map + (nodeModel.uuid -> idx) + } else { + map + } + } + } + + gridModel._nodeUuidToIndexMap = updatedNodeToUuidMap } +} From 586b75afe86dd7612583aabd26ca0dba63cbacca Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 28 Sep 2023 12:15:35 +0200 Subject: [PATCH 060/123] squants --- .../model/participant/control/QControl.scala | 49 +++++++++---------- .../util/scala/quantities/QuantityUtil.scala | 7 ++- .../agent/grid/GridResultsSupportSpec.scala | 16 +++--- .../ie3/simona/util/CollectionUtilsSpec.scala | 12 ++--- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/control/QControl.scala b/src/main/scala/edu/ie3/simona/model/participant/control/QControl.scala index cb28f8392b..02c42be94f 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/control/QControl.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/control/QControl.scala @@ -13,7 +13,7 @@ import edu.ie3.simona.model.system.Characteristic import edu.ie3.simona.model.system.Characteristic.XYPair import edu.ie3.util.quantities.PowerSystemUnits.PU import edu.ie3.util.scala.quantities.{Megavars, ReactivePower} -import squants.Each +import squants.{Dimensionless, Each, Power} import tech.units.indriya.AbstractUnit import scala.collection.SortedSet @@ -22,9 +22,8 @@ import scala.jdk.CollectionConverters._ import scala.math._ sealed trait QControl { - protected val _cosPhiMultiplication - : (Double, squants.Power) => ReactivePower = - (cosPhi: Double, p: squants.Power) => + protected val _cosPhiMultiplication: (Double, Power) => ReactivePower = + (cosPhi: Double, p: Power) => if ((cosPhi - 1).abs < 0.0000001) { Megavars(0d) } else { @@ -44,10 +43,10 @@ sealed trait QControl { * The function */ def activeToReactivePowerFunc( - sRated: squants.Power, + sRated: Power, cosPhiRated: Double, - nodalVoltage: squants.Dimensionless - ): squants.Power => ReactivePower + nodalVoltage: Dimensionless + ): Power => ReactivePower } /** Object to create a [[QControl]]. Currently the following QControls @@ -72,7 +71,7 @@ object QControl { CosPhiP( TreeSet.from( cosPhiP.getPoints.asScala.map(point => - XYPair[squants.Dimensionless, squants.Dimensionless]( + XYPair[Dimensionless, Dimensionless]( Each(point.getX.getValue.doubleValue()), Each(point.getY.getValue.doubleValue()) ) @@ -84,7 +83,7 @@ object QControl { TreeSet.from( qv.getPoints.asScala .map(point => - XYPair[squants.Dimensionless, squants.Dimensionless]( + XYPair[Dimensionless, Dimensionless]( Each(point.getX.getValue.doubleValue()), Each(point.getY.getValue.doubleValue()) ) @@ -117,10 +116,10 @@ object QControl { * The function */ override def activeToReactivePowerFunc( - sRated: squants.Power, + sRated: Power, cosPhiRated: Double, - nodalVoltage: squants.Dimensionless - ): squants.Power => ReactivePower = { activePower: squants.Power => + nodalVoltage: Dimensionless + ): Power => ReactivePower = { activePower: Power => _cosPhiMultiplication(cosPhi, activePower) } } @@ -132,10 +131,10 @@ object QControl { */ final case class QV private ( xyCoordinates: SortedSet[ - XYPair[squants.Dimensionless, squants.Dimensionless] + XYPair[Dimensionless, Dimensionless] ] ) extends QControl - with Characteristic[squants.Dimensionless, squants.Dimensionless] { + with Characteristic[Dimensionless, Dimensionless] { /** Returns the resulting reactive power for the requested voltage level * value. The conversion to abstract unit [[AbstractUnit.ONE]] is necessary @@ -151,7 +150,7 @@ object QControl { * the resulting reactive power q */ def q( - vInPu: squants.Dimensionless, + vInPu: Dimensionless, qMax: ReactivePower ): ReactivePower = { qMax * interpolateXy(vInPu)._2.toEach @@ -169,10 +168,10 @@ object QControl { * The function */ override def activeToReactivePowerFunc( - sRated: squants.Power, + sRated: Power, cosPhiRated: Double, - nodalVoltage: squants.Dimensionless - ): squants.Power => ReactivePower = { activePower: squants.Power => + nodalVoltage: Dimensionless + ): Power => ReactivePower = { activePower: Power => val qMaxFromP = Megavars( sqrt( pow(sRated.toMegawatts, 2) - @@ -213,10 +212,10 @@ object QControl { */ final case class CosPhiP private ( xyCoordinates: SortedSet[ - XYPair[squants.Dimensionless, squants.Dimensionless] + XYPair[Dimensionless, Dimensionless] ] ) extends QControl - with Characteristic[squants.Dimensionless, squants.Dimensionless] { + with Characteristic[Dimensionless, Dimensionless] { /** Returns the requested cosine phi value for a provided power value * (p/sRated) in p.u. If the cosine phi cannot be found for the requested @@ -228,8 +227,8 @@ object QControl { * the cosine phi for the requested p.u. value */ def cosPhi( - pInPu: squants.Dimensionless - ): squants.Dimensionless = + pInPu: Dimensionless + ): Dimensionless = interpolateXy(pInPu)._2 /** Obtain the function, that transfers active into reactive power @@ -244,10 +243,10 @@ object QControl { * The function */ override def activeToReactivePowerFunc( - sRated: squants.Power, + sRated: Power, cosPhiRated: Double, - nodalVoltage: squants.Dimensionless - ): squants.Power => ReactivePower = { activePower: squants.Power => + nodalVoltage: Dimensionless + ): Power => ReactivePower = { activePower: Power => /* cosphi( P / P_N ) = cosphi( P / (S_N * cosphi_rated) ) */ val pInPu = activePower / (sRated * cosPhiRated) diff --git a/src/main/scala/edu/ie3/util/scala/quantities/QuantityUtil.scala b/src/main/scala/edu/ie3/util/scala/quantities/QuantityUtil.scala index bc949dae2b..8507633d4c 100644 --- a/src/main/scala/edu/ie3/util/scala/quantities/QuantityUtil.scala +++ b/src/main/scala/edu/ie3/util/scala/quantities/QuantityUtil.scala @@ -8,6 +8,7 @@ package edu.ie3.util.scala.quantities import edu.ie3.simona.exceptions.QuantityException import edu.ie3.util.quantities.{QuantityUtil => PSQuantityUtil} +import squants.UnitOfMeasure import tech.units.indriya.ComparableQuantity import tech.units.indriya.function.Calculus import tech.units.indriya.quantity.Quantities @@ -33,10 +34,14 @@ object QuantityUtil { ) ) - def zero[Q <: Quantity[Q]]( + def zeroCompQuantity[Q <: Quantity[Q]]( unit: javax.measure.Unit[Q] ): ComparableQuantity[Q] = Quantities.getQuantity(0, unit) + def zero[Q <: squants.Quantity[Q]]( + unit: UnitOfMeasure[Q] + ): Q = unit(0d) + @deprecated( "Use reduceOption { (power1, power2) => power1.add(power2) } instead" ) diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala index 77668a425e..c2f67e8701 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala @@ -199,10 +199,10 @@ class GridResultsSupportSpec disabledLineResult shouldBe new LineResult( defaultSimulationStart, line0To1.uuid, - ScalaQuantityUtil.zero(Units.AMPERE), - ScalaQuantityUtil.zero(DEGREE_GEOM), - ScalaQuantityUtil.zero(Units.AMPERE), - ScalaQuantityUtil.zero(DEGREE_GEOM) + ScalaQuantityUtil.zeroCompQuantity(Units.AMPERE), + ScalaQuantityUtil.zeroCompQuantity(DEGREE_GEOM), + ScalaQuantityUtil.zeroCompQuantity(Units.AMPERE), + ScalaQuantityUtil.zeroCompQuantity(DEGREE_GEOM) ) } @@ -403,10 +403,10 @@ class GridResultsSupportSpec val expectedResult: Transformer2WResult = new Transformer2WResult( TimeUtil.withDefaults.toZonedDateTime("2020-06-08 09:03:00"), transformerModel.uuid, - ScalaQuantityUtil.zero(AMPERE), - ScalaQuantityUtil.zero(DEGREE_GEOM), - ScalaQuantityUtil.zero(AMPERE), - ScalaQuantityUtil.zero(DEGREE_GEOM), + ScalaQuantityUtil.zeroCompQuantity(AMPERE), + ScalaQuantityUtil.zeroCompQuantity(DEGREE_GEOM), + ScalaQuantityUtil.zeroCompQuantity(AMPERE), + ScalaQuantityUtil.zeroCompQuantity(DEGREE_GEOM), transformerModel.currentTapPos ) diff --git a/src/test/scala/edu/ie3/simona/util/CollectionUtilsSpec.scala b/src/test/scala/edu/ie3/simona/util/CollectionUtilsSpec.scala index 6b6fdb3243..2553818567 100644 --- a/src/test/scala/edu/ie3/simona/util/CollectionUtilsSpec.scala +++ b/src/test/scala/edu/ie3/simona/util/CollectionUtilsSpec.scala @@ -8,12 +8,8 @@ package edu.ie3.simona.util import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.util.CollectionUtils._ -import edu.ie3.util.quantities.PowerSystemUnits._ import squants.Each -import tech.units.indriya.ComparableQuantity -import tech.units.indriya.quantity.Quantities.getQuantity - -import javax.measure.quantity.Dimensionless +import squants.Dimensionless class CollectionUtilsSpec extends UnitSpec { @@ -38,13 +34,13 @@ class CollectionUtilsSpec extends UnitSpec { ) def returnedSequence1: Seq[ - (squants.Dimensionless, squants.Dimensionless) + (Dimensionless, Dimensionless) ] = closestKeyValuePairs(map, Each(1.5)) def returnedSequence2: Seq[ - (squants.Dimensionless, squants.Dimensionless) + (Dimensionless, Dimensionless) ] = closestKeyValuePairs(map, Each(2.5)) def returnedSequence3: Seq[ - (squants.Dimensionless, squants.Dimensionless) + (Dimensionless, Dimensionless) ] = closestKeyValuePairs(map, Each(3d)) returnedSequence1 shouldBe Seq( From 7fed7c00211ceb80ed64a8cfb37ce86d8e59d29e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 28 Sep 2023 12:15:55 +0200 Subject: [PATCH 061/123] transfer tests to squants --- .../agent/grid/GridResultsSupport.scala | 16 +++++++-------- .../control/TransformerControlGroup.scala | 11 ++++------ .../edu/ie3/simona/model/grid/GridModel.scala | 20 +++++++------------ .../control/TransformerControlGroupSpec.scala | 12 ++++------- 4 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala index 55d0a5d995..4cf61786db 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala @@ -346,10 +346,10 @@ private[grid] trait GridResultsSupport { new LineResult( timestamp, line.uuid, - QuantityUtil.zero(Units.AMPERE), - QuantityUtil.zero(PowerSystemUnits.DEGREE_GEOM), - QuantityUtil.zero(Units.AMPERE), - QuantityUtil.zero(PowerSystemUnits.DEGREE_GEOM) + QuantityUtil.zeroCompQuantity(Units.AMPERE), + QuantityUtil.zeroCompQuantity(PowerSystemUnits.DEGREE_GEOM), + QuantityUtil.zeroCompQuantity(Units.AMPERE), + QuantityUtil.zeroCompQuantity(PowerSystemUnits.DEGREE_GEOM) ) } } @@ -415,10 +415,10 @@ private[grid] trait GridResultsSupport { new Transformer2WResult( timestamp, trafo2w.uuid, - QuantityUtil.zero(Units.AMPERE), - QuantityUtil.zero(PowerSystemUnits.DEGREE_GEOM), - QuantityUtil.zero(Units.AMPERE), - QuantityUtil.zero(PowerSystemUnits.DEGREE_GEOM), + QuantityUtil.zeroCompQuantity(Units.AMPERE), + QuantityUtil.zeroCompQuantity(PowerSystemUnits.DEGREE_GEOM), + QuantityUtil.zeroCompQuantity(Units.AMPERE), + QuantityUtil.zeroCompQuantity(PowerSystemUnits.DEGREE_GEOM), trafo2w.currentTapPos ) } diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala index 652b40b4e1..0a8bf08f1e 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala @@ -10,10 +10,9 @@ import breeze.math.Complex import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult import edu.ie3.simona.model.control.TransformerControlGroup.RegulationCriterion -import tech.units.indriya.ComparableQuantity import java.util.UUID -import javax.measure.quantity.Dimensionless +import squants.Dimensionless /** Business logic for a transformer control group. It's main purpose is to * determine, if there is any regulation need and if yes, in what circumference @@ -28,9 +27,7 @@ import javax.measure.quantity.Dimensionless */ final case class TransformerControlGroup( nodalRegulationCriterion: Map[UUID, RegulationCriterion], - harmonizeRegulationNeeds: Array[ - ComparableQuantity[Dimensionless] - ] => Option[ComparableQuantity[Dimensionless]] + harmonizeRegulationNeeds: Array[Dimensionless] => Option[Dimensionless] ) { /** Based on the given successful power flow result, determine the difference @@ -48,7 +45,7 @@ final case class TransformerControlGroup( def determineRegulationNeed( result: SuccessFullPowerFlowResult, uuidToIndex: Map[UUID, Int] - ): Option[ComparableQuantity[Dimensionless]] = { + ): Option[Dimensionless] = { val regulationNeeds = result.nodeData.flatMap { case StateData(resultNodeIndex, _, voltage, _) => /* Find possible matching criterion and evaluate it */ @@ -71,5 +68,5 @@ final case class TransformerControlGroup( object TransformerControlGroup { type RegulationCriterion = - Complex => Option[ComparableQuantity[Dimensionless]] + Complex => Option[Dimensionless] } diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index c01455d731..3342809985 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -26,16 +26,14 @@ import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseC } import edu.ie3.simona.util.CollectionUtils -import edu.ie3.util.quantities.PowerSystemUnits + import org.jgrapht.Graph import org.jgrapht.alg.connectivity.ConnectivityInspector import org.jgrapht.graph.{DefaultEdge, SimpleGraph} -import tech.units.indriya.ComparableQuantity -import tech.units.indriya.quantity.Quantities +import squants.{Dimensionless, Each} import java.time.ZonedDateTime import java.util.UUID -import javax.measure.quantity.Dimensionless import scala.collection.immutable.ListSet import scala.jdk.CollectionConverters._ @@ -689,22 +687,18 @@ case object GridModel { val vMag = complexVoltage.abs vMag match { case mag if mag > vMax => - Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + Some(vMax - mag).map(Each(_)) case mag if mag < vMin => - Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + Some(vMin - mag).map(Each(_)) case _ => None } } }.toMap val harmonizationFunction = - (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { - val negativeRequests = regulationRequests.filter( - _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) - val positiveRequests = regulationRequests.filter( - _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) + (regulationRequests: Array[Dimensionless]) => { + val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) + val positiveRequests = regulationRequests.filter(_ > Each(0d)) (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { case (true, true) => diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala index 8def596ce6..100f1bb9e5 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala @@ -14,12 +14,12 @@ import edu.ie3.powerflow.model.enums.NodeType import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.matchers.QuantityMatchers -import edu.ie3.util.quantities.PowerSystemUnits -import tech.units.indriya.quantity.Quantities +import squants.{Dimensionless, Each} import java.util.UUID class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { + implicit val tolerance: Dimensionless = Each(1e-10) "Checking the function of transformer control groups" should { val buildTransformerControlModels = PrivateMethod[TransformerControlGroup]( Symbol("buildTransformerControlModels") @@ -100,9 +100,7 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { actual match { case Some(regulationNeed) => - regulationNeed should equalWithTolerance( - Quantities.getQuantity(0.05, PowerSystemUnits.PU) - ) + regulationNeed =~ Each(0.05d) case None => fail("Did expect to receive a regulation need.") } } @@ -122,9 +120,7 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { actual match { case Some(regulationNeed) => - regulationNeed should equalWithTolerance( - Quantities.getQuantity(-0.05, PowerSystemUnits.PU) - ) + regulationNeed =~ Each(-990.05d) case None => fail("Did expect to receive a regulation need.") } } From 7655154c519505a19ee7ce5ddf113c1fb8ba5c9c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 22 Nov 2023 17:40:59 +0100 Subject: [PATCH 062/123] fmt --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f41129154..d79171d0d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add safety factor sRated calculation [#629](https://github.com/ie3-institute/simona/issues/629) - Re-implemented ResultEventListener in akka typed [#343](https://github.com/ie3-institute/simona/issues/343) - Add additional test cases from references for PvModelTest [#590](https://github.com/ie3-institute/simona/issues/590) - - Models for measurements within the grid structure [#89](https://github.com/ie3-institute/simona/issues/89) - Config possibility for transformer control groups [#90](https://github.com/ie3-institute/simona/issues/90) From b3f04f1d6c359e4bb6768f5a755cf3fb4ec5ffc4 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 1 Feb 2024 13:12:51 +0100 Subject: [PATCH 063/123] Convert `GridAgent` & `DBFSAlgorithm` to pekko typed --- CHANGELOG.md | 1 + .../ie3/simona/actor/SimonaActorNaming.scala | 24 +- .../ie3/simona/agent/grid/DBFSAlgorithm.scala | 1709 +++++++++-------- .../edu/ie3/simona/agent/grid/GridAgent.scala | 286 ++- .../agent/grid/GridAgentController.scala | 294 +-- .../ie3/simona/agent/grid/GridAgentData.scala | 25 +- .../simona/agent/grid/GridAgentMessage.scala | 110 ++ .../simona/agent/grid/GridEnvironment.scala | 11 +- .../agent/grid/GridResultsSupport.scala | 21 +- .../simona/agent/grid/PowerFlowSupport.scala | 6 +- .../simona/agent/grid/ReceivedValues.scala | 28 +- .../agent/grid/ReceivedValuesStore.scala | 29 +- .../agent/participant/ParticipantAgent.scala | 8 +- .../simona/agent/state/GridAgentState.scala | 21 - .../ie3/simona/event/notifier/Notifier.scala | 4 +- .../ontology/messages/PowerMessage.scala | 5 +- .../ontology/messages/VoltageMessage.scala | 5 +- .../scala/edu/ie3/simona/sim/SimonaSim.scala | 35 +- .../ie3/simona/sim/setup/SetupHelper.scala | 13 +- .../ie3/simona/sim/setup/SimonaSetup.scala | 53 +- .../sim/setup/SimonaStandaloneSetup.scala | 78 +- .../agent/grid/DBFSAlgorithmCenGridSpec.scala | 143 +- .../DBFSAlgorithmFailedPowerFlowSpec.scala | 120 +- .../grid/DBFSAlgorithmParticipantSpec.scala | 175 +- .../agent/grid/DBFSAlgorithmSupGridSpec.scala | 163 +- .../agent/grid/DBFSMockGridAgents.scala | 99 +- .../agent/grid/GridAgentSetup2WSpec.scala | 126 +- .../agent/grid/GridAgentSetup3WSpec.scala | 134 +- .../agent/grid/GridResultsSupportSpec.scala | 2 - .../agent/grid/PowerFlowSupportSpec.scala | 27 +- .../agent/grid/ReceivedValuesStoreSpec.scala | 65 +- .../ParticipantAgent2ListenerSpec.scala | 2 +- .../edu/ie3/simona/event/NotifierSpec.scala | 9 +- .../ie3/simona/sim/SimonaSimFailSpec.scala | 30 +- .../simona/sim/setup/SetupHelperSpec.scala | 18 +- .../simona/sim/setup/SimonaSetupSpec.scala | 38 +- 36 files changed, 2103 insertions(+), 1814 deletions(-) create mode 100644 src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala delete mode 100644 src/main/scala/edu/ie3/simona/agent/state/GridAgentState.scala diff --git a/CHANGELOG.md b/CHANGELOG.md index 475c746d92..c4dccff0e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Replaced akka with pekko [#641](https://github.com/ie3-institute/simona/issues/641) - Use `ThermalGrid` to calculate thermal environment of a heat pump [#315](https://github.com/ie3-institute/simona/issues/315) - Enable windows path as config parameters [#549](https://github.com/ie3-institute/simona/issues/549) +- Converting the `GridAgent` and the `DBFSAlgorithm` to `pekko typed` [#666](https://github.com/ie3-institute/simona/issues/666) ### Fixed - Removed a repeated line in the documentation of vn_simona config [#658](https://github.com/ie3-institute/simona/issues/658) diff --git a/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala b/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala index bc5b548f2f..04a2dbff60 100644 --- a/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala +++ b/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala @@ -6,7 +6,8 @@ package edu.ie3.simona.actor -import org.apache.pekko.actor.{ActorRef, ActorRefFactory, Props} +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.{ActorRefFactory, Props, ActorRef => classicRef} import java.util.UUID @@ -15,10 +16,10 @@ object SimonaActorNaming { implicit class RichActorRefFactory(private val refFactory: ActorRefFactory) extends AnyVal { - def simonaActorOf(props: Props, actorId: String): ActorRef = + def simonaActorOf(props: Props, actorId: String): classicRef = refFactory.actorOf(props, actorName(props, actorId)) - def simonaActorOf(props: Props): ActorRef = + def simonaActorOf(props: Props): classicRef = refFactory.actorOf(props, actorName(props, simonaActorUuid)) } @@ -62,13 +63,28 @@ object SimonaActorNaming { def actorName(typeName: String, actorId: String): String = s"${typeName}_${cleanActorIdForPekko(actorId)}" + /** Extracts the actor name from given [[classicRef]]. Cluster singletons are + * taken care of separately. + * + * @return + * the actor name extract from the ActorRef + */ + def actorName(actorRef: classicRef): String = + actorRef.path.name match { + case "singleton" => + // singletons end in /${actorName}/singleton + actorRef.path.parent.name + case other => + other + } + /** Extracts the actor name from given [[ActorRef]]. Cluster singletons are * taken care of separately. * * @return * the actor name extract from the ActorRef */ - def actorName(actorRef: ActorRef): String = + def actorName(actorRef: ActorRef[_]): String = actorRef.path.name match { case "singleton" => // singletons end in /${actorName}/singleton diff --git a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala index 309fb1b7ef..a6e3177ab7 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -6,10 +6,6 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps -import org.apache.pekko.actor.{ActorRef, FSM, PoisonPill} -import org.apache.pekko.pattern.{ask, pipe} -import org.apache.pekko.util.{Timeout => PekkoTimeout} import breeze.linalg.{DenseMatrix, DenseVector} import breeze.math.Complex import edu.ie3.datamodel.graph.SubGridGate @@ -19,19 +15,13 @@ import edu.ie3.powerflow.model.PowerFlowResult import edu.ie3.powerflow.model.PowerFlowResult.FailedPowerFlowResult.FailedNewtonRaphsonPFResult import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult import edu.ie3.powerflow.model.enums.NodeType -import edu.ie3.simona.agent.grid.GridAgent._ import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentBaseData, PowerFlowDoneData } +import edu.ie3.simona.agent.grid.GridAgentMessage._ import edu.ie3.simona.agent.grid.ReceivedValues._ -import edu.ie3.simona.agent.state.AgentState -import edu.ie3.simona.agent.state.AgentState.Idle -import edu.ie3.simona.agent.state.GridAgentState.{ - CheckPowerDifferences, - HandlePowerFlowCalculations, - SimulateGrid -} +import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.event.RuntimeEvent.PowerFlowFailed import edu.ie3.simona.exceptions.agent.DBFSAlgorithmException import edu.ie3.simona.model.grid.{NodeModel, RefSystem} @@ -46,12 +36,21 @@ import edu.ie3.simona.ontology.messages.VoltageMessage.{ import edu.ie3.simona.util.TickUtil.TickLong import edu.ie3.util.scala.quantities.Megavars import edu.ie3.util.scala.quantities.SquantsUtils.RichElectricPotential +import org.apache.pekko.actor.typed.scaladsl.AskPattern._ +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps +import org.apache.pekko.actor.typed.scaladsl.{ActorContext, Behaviors} +import org.apache.pekko.actor.typed.{ActorRef, Behavior, Scheduler} +import org.apache.pekko.actor.{ActorRef => classicRef} +import org.apache.pekko.pattern.ask +import org.apache.pekko.util.{Timeout => PekkoTimeout} +import org.slf4j.Logger import squants.Each import squants.energy.Megawatts import java.time.{Duration, ZonedDateTime} import java.util.UUID import scala.concurrent.{ExecutionContext, Future} +import scala.util.{Failure, Success} /** Trait that is normally mixed into every [[GridAgent]] to enable distributed * forward backward sweep (DBFS) algorithm execution. It is considered to be @@ -59,693 +58,785 @@ import scala.concurrent.{ExecutionContext, Future} */ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { this: GridAgent => - // implicit ExecutionContext should be in scope - // see https://pekko.apache.org/docs/pekko/current/futures.html - implicit val ec: ExecutionContext = context.dispatcher - - when(SimulateGrid) { - - // first part of the grid simulation, same for all gridAgents on all levels - // we start with a forward-sweep by requesting the data from our child assets and grids (if any) - case Event( - Activation(currentTick), - gridAgentBaseData: GridAgentBaseData - ) => - log.debug("Start sweep number: {}", gridAgentBaseData.currentSweepNo) - // hold tick and trigger for the whole time the dbfs is executed or - // at least until the the first full sweep is done (for superior grid agent only) - holdTick(currentTick) - - // we start the grid simulation by requesting the p/q values of all the nodes we are responsible for - // as well as the slack voltage power from our superior grid - // 1. assets p/q values - askForAssetPowers( - currentTick, - gridAgentBaseData.sweepValueStores - .get(gridAgentBaseData.currentSweepNo), - gridAgentBaseData.gridEnv.nodeToAssetAgents, - gridAgentBaseData.gridEnv.gridModel.mainRefSystem, - gridAgentBaseData.powerFlowParams.sweepTimeout - ) - // 2. inferior grids p/q values - askInferiorGridsForPowers( - gridAgentBaseData.currentSweepNo, - gridAgentBaseData.gridEnv.subgridGateToActorRef, - gridAgentBaseData.inferiorGridGates, - gridAgentBaseData.powerFlowParams.sweepTimeout - ) + /** Method that defines the [[Behavior]] for simulating the grid. + * @param gridAgentData + * state data of the actor + * @param currentTick + * current simulation tick + * @return + * a [[Behavior]] + */ + protected def simulateGrid( + gridAgentData: GridAgentData, + currentTick: Long + ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + (ctx, message) => + (message, gridAgentData) match { + // first part of the grid simulation, same for all gridAgents on all levels + // we start with a forward-sweep by requesting the data from our child assets and grids (if any) + case ( + ActivationAdapter(activation: Activation), + gridAgentBaseData: GridAgentBaseData + ) => + ctx.log.debug( + "Start sweep number: {}", + gridAgentBaseData.currentSweepNo + ) - // 3. superior grids slack voltage - askSuperiorGridsForSlackVoltages( - gridAgentBaseData.currentSweepNo, - gridAgentBaseData.gridEnv.subgridGateToActorRef, - gridAgentBaseData.superiorGridGates, - gridAgentBaseData.powerFlowParams.sweepTimeout - ) + // we start the grid simulation by requesting the p/q values of all the nodes we are responsible for + // as well as the slack voltage power from our superior grid + // 1. assets p/q values + askForAssetPowers( + currentTick, + gridAgentBaseData.sweepValueStores + .get(gridAgentBaseData.currentSweepNo), + gridAgentBaseData.gridEnv.nodeToAssetAgents, + gridAgentBaseData.gridEnv.gridModel.mainRefSystem, + gridAgentBaseData.powerFlowParams.sweepTimeout + )(ctx) - stay() - - // if we receive power values as response on our request, we process them here - case Event( - receivedValues: ReceivedValues, - gridAgentBaseData: GridAgentBaseData - ) => - // we just received either all provided slack voltage values or all provided power values - val updatedGridAgentBaseData: GridAgentBaseData = receivedValues match { - case receivedPowers: ReceivedPowerValues => - /* Can be a message from an asset or a message from an inferior grid */ - gridAgentBaseData.updateWithReceivedPowerValues(receivedPowers) - case receivedSlacks: ReceivedSlackVoltageValues => - gridAgentBaseData.updateWithReceivedSlackVoltages(receivedSlacks) - case unknownReceivedValues => - throw new DBFSAlgorithmException( - s"Received unknown values: $unknownReceivedValues" + // 2. inferior grids p/q values + askInferiorGridsForPowers( + gridAgentBaseData.currentSweepNo, + gridAgentBaseData.gridEnv.subgridGateToActorRef, + gridAgentBaseData.inferiorGridGates, + gridAgentBaseData.powerFlowParams.sweepTimeout + )(ctx) + + // 3. superior grids slack voltage + askSuperiorGridsForSlackVoltages( + gridAgentBaseData.currentSweepNo, + gridAgentBaseData.gridEnv.subgridGateToActorRef, + gridAgentBaseData.superiorGridGates, + gridAgentBaseData.powerFlowParams.sweepTimeout + )(ctx) + + simulateGrid(gridAgentBaseData, activation.tick) + + // if we receive power values as response on our request, we process them here + case ( + ValuesAdapter(receivedValues: ReceivedValues), + gridAgentBaseData: GridAgentBaseData + ) => + // we just received either all provided slack voltage values or all provided power values + val updatedGridAgentBaseData: GridAgentBaseData = + receivedValues match { + case receivedPowers: ReceivedPowerValues => + /* Can be a message from an asset or a message from an inferior grid */ + gridAgentBaseData.updateWithReceivedPowerValues(receivedPowers) + case receivedSlacks: ReceivedSlackVoltageValues => + gridAgentBaseData.updateWithReceivedSlackVoltages( + receivedSlacks + ) + case unknownReceivedValues => + throw new DBFSAlgorithmException( + s"Received unknown values: $unknownReceivedValues" + ) + } + + // check if we have enough data for a power flow calculation or a + // power differences check (if the grid agent is a superior agent) + // if yes, check if we have failing power flow in at least one of the inferior grids + // if there are failing ones, escalate the failure to the superior grid (if any), + // if not go to power flow or power differences check + // if we haven't received everything yet, stay and wait + val allValuesReceived = + updatedGridAgentBaseData.allRequestedDataReceived + + ctx.log.debug( + "{}", + if (allValuesReceived) + "Got answers for all my requests for Slack Voltages and Power Values." + else + "Still waiting for answers my requests for Slack Voltages and Power Values." ) - } - // check if we have enough data for a power flow calculation or a - // power differences check (if the grid agent is a superior agent) - // if yes, check if we have failing power flow in at least one of the inferior grids - // if there are failing ones, escalate the failure to the superior grid (if any), - // if not go to power flow or power differences check - // if we haven't received everything yet, stay and wait - val allValuesReceived = updatedGridAgentBaseData.allRequestedDataReceived - - log.debug( - "{}", - if (allValuesReceived) - "Got answers for all my requests for Slack Voltages and Power Values." - else - "Still waiting for answers my requests for Slack Voltages and Power Values." - ) + if (gridAgentBaseData.isSuperior) { + goToCheckPowerDifferencesOrStay( + allValuesReceived, + updatedGridAgentBaseData, + currentTick, + simulateGrid + )(ctx) + } else { + goToPowerFlowCalculationOrStay( + allValuesReceived, + updatedGridAgentBaseData, + currentTick, + simulateGrid + )(ctx) + } - if (gridAgentBaseData.isSuperior) { - goToCheckPowerDifferencesOrStay( - allValuesReceived, - updatedGridAgentBaseData - ) - } else { - goToPowerFlowCalculationOrStay( - allValuesReceived, - updatedGridAgentBaseData - ) - } + // if we receive a request for slack voltages from our inferior grids we want to answer it + case ( + VMAdapter( + RequestSlackVoltageMessage( + currentSweepNo, + nodeUuids, + sender: ActorRef[GridAgentMessage] + ) + ), + gridAgentBaseData: GridAgentBaseData + ) => + ctx.log.debug( + s"Received Slack Voltages request from {} for nodes {} and sweepNo: {}", + sender, + nodeUuids, + gridAgentBaseData.currentSweepNo + ) - // if we receive a request for slack voltages from our inferior grids we want to answer it - case Event( - RequestSlackVoltageMessage(currentSweepNo, nodeUuids), - gridAgentBaseData: GridAgentBaseData - ) => - log.debug( - s"Received Slack Voltages request from {} for nodes {} and sweepNo: {}", - sender(), - nodeUuids, - gridAgentBaseData.currentSweepNo - ) + nodeUuids.map { nodeUuid => + // we either have voltages ready calculated (not the first sweep) or we don't have them here + // -> return calculated value or target voltage as physical value + (gridAgentBaseData.sweepValueStores.get(currentSweepNo) match { + case Some(result) => + Some(result, currentSweepNo) + case None => + // this happens if this agent is either a) the superior grid agent, because it will always get a request for + // the next sweep, as it triggers calculations for the next sweep or b) at all other + // (non last downstream grid agents) in sweep 0 + ctx.log.debug( + "Unable to find slack voltage for nodes '{}' in sweep '{}'. Try to get voltage of previous sweep.", + nodeUuids, + currentSweepNo + ) + gridAgentBaseData.sweepValueStores + .get(currentSweepNo - 1) + .map((_, currentSweepNo - 1)) + }).map { case (result, sweepNo) => + // get nodeUUID + result.sweepData.find(_.nodeUuid == nodeUuid) match { + case Some(sweepValueStoreData) => + val slackVoltageInPu = sweepValueStoreData.stateData.voltage + val mainRefSystem = + gridAgentBaseData.gridEnv.gridModel.mainRefSystem + ( + mainRefSystem.vInSi(slackVoltageInPu.real), + mainRefSystem.vInSi(slackVoltageInPu.imag) + ) + case None => + throw new DBFSAlgorithmException( + s"Requested nodeUuid $nodeUuid " + + s"not found in sweep value store data for sweepNo: $sweepNo. This indicates" + + s"either a wrong processing of a previous sweep result or inconsistencies in grid model data!" + ) + } + }.getOrElse { + ctx.log.debug( + "Unable to get slack voltage for node '{}' in sweeps '{}' and '{}'. Returning target voltage.", + nodeUuid, + currentSweepNo, + currentSweepNo - 1 + ) - nodeUuids.map { nodeUuid => - // we either have voltages ready calculated (not the first sweep) or we don't have them here - // -> return calculated value or target voltage as physical value - (gridAgentBaseData.sweepValueStores.get(currentSweepNo) match { - case Some(result) => - Some(result, currentSweepNo) - case None => - // this happens if this agent is either a) the superior grid agent, because it will always get a request for - // the next sweep, as it triggers calculations for the next sweep or b) at all other - // (non last downstream grid agents) in sweep 0 - log.debug( - "Unable to find slack voltage for nodes '{}' in sweep '{}'. Try to get voltage of previous sweep.", - nodeUuids, - currentSweepNo - ) - gridAgentBaseData.sweepValueStores - .get(currentSweepNo - 1) - .map((_, currentSweepNo - 1)) - }).map { case (result, sweepNo) => - // get nodeUUID - result.sweepData.find(_.nodeUuid == nodeUuid) match { - case Some(sweepValueStoreData) => - val slackVoltageInPu = sweepValueStoreData.stateData.voltage - val mainRefSystem = + val refSystem = gridAgentBaseData.gridEnv.gridModel.mainRefSystem + + /* Determine the slack node voltage under consideration of the target voltage set point */ + val vTarget = + gridAgentBaseData.gridEnv.gridModel.gridComponents.nodes + .find { case NodeModel(uuid, _, _, isSlack, _, _) => + uuid == nodeUuid && isSlack + } + .map(_.vTarget) + .getOrElse(Each(1d)) + val vSlack = + refSystem.nominalVoltage.multiplyWithDimensionles(vTarget) + ( - mainRefSystem.vInSi(slackVoltageInPu.real), - mainRefSystem.vInSi(slackVoltageInPu.imag) + vSlack, + refSystem.vInSi(0d) ) - case None => - throw new DBFSAlgorithmException( - s"Requested nodeUuid $nodeUuid " + - s"not found in sweep value store data for sweepNo: $sweepNo. This indicates" + - s"either a wrong processing of a previous sweep result or inconsistencies in grid model data!" + } match { + case (slackE, slackF) => + ctx.log.debug( + s"Provide {} to {} for node {} and sweepNo: {}", + s"$slackE, $slackF", + sender, + nodeUuid, + gridAgentBaseData.currentSweepNo + ) + + ExchangeVoltage(nodeUuid, slackE, slackF) + } + } match { + case exchangeVoltages => + sender ! VMAdapter( + ProvideSlackVoltageMessage(currentSweepNo, exchangeVoltages) ) + Behaviors.same } - }.getOrElse { - log.debug( - "Unable to get slack voltage for node '{}' in sweeps '{}' and '{}'. Returning target voltage.", - nodeUuid, - currentSweepNo, - currentSweepNo - 1 - ) - val refSystem = - gridAgentBaseData.gridEnv.gridModel.mainRefSystem + // receive grid power values message request from superior grids + // before power flow calc for this sweep we either have to stash() the message to answer it later (in current sweep) + // or trigger a new run for the next sweepNo + case ( + PMAdapter( + RequestGridPowerMessage( + requestSweepNo, + nodeUuids, + sender: ActorRef[GridAgentMessage] + ) + ), + gridAgentBaseData: GridAgentBaseData + ) => + if (gridAgentBaseData.currentSweepNo == requestSweepNo) { + ctx.log.debug( + s"Received request for grid power values for sweepNo {} before my first power flow calc. Stashing away.", + requestSweepNo + ) - /* Determine the slack node voltage under consideration of the target voltage set point */ - val vTarget = - gridAgentBaseData.gridEnv.gridModel.gridComponents.nodes - .find { case NodeModel(uuid, _, _, isSlack, _, _) => - uuid == nodeUuid && isSlack - } - .map(_.vTarget) - .getOrElse(Each(1d)) - val vSlack = - refSystem.nominalVoltage.multiplyWithDimensionles(vTarget) - - ( - vSlack, - refSystem.vInSi(0d) - ) - } match { - case (slackE, slackF) => - log.debug( - s"Provide {} to {} for node {} and sweepNo: {}", - s"$slackE, $slackF", - sender(), - nodeUuid, - gridAgentBaseData.currentSweepNo + buffer.stash( + PMAdapter( + RequestGridPowerMessage(requestSweepNo, nodeUuids, sender) + ) ) - ExchangeVoltage(nodeUuid, slackE, slackF) - } - } match { - case exchangeVoltages => - stay() replying ProvideSlackVoltageMessage( - currentSweepNo, - exchangeVoltages - ) - } + Behaviors.same + } else { + ctx.log.debug( + s"Received request for grid power values for a NEW sweep (request: {}, my: {})", + requestSweepNo, + gridAgentBaseData.currentSweepNo + ) + ctx.self ! PrepareNextSweepTrigger(currentTick) - // receive grid power values message request from superior grids - // / before power flow calc for this sweep we either have to stash() the message to answer it later (in current sweep) - // / or trigger a new run for the next sweepNo - case Event( - RequestGridPowerMessage(requestSweepNo, _), - gridAgentBaseData: GridAgentBaseData - ) => - if (gridAgentBaseData.currentSweepNo == requestSweepNo) { - log.debug( - s"Received request for grid power values for sweepNo {} before my first power flow calc. Stashing away.", - requestSweepNo - ) - stash() - stay() - } else { - log.debug( - s"Received request for grid power values for a NEW sweep (request: {}, my: {})", - requestSweepNo, - gridAgentBaseData.currentSweepNo - ) - self ! PrepareNextSweepTrigger(currentTick) + buffer.stash( + PMAdapter( + RequestGridPowerMessage(requestSweepNo, nodeUuids, sender) + ) + ) - stash() - stay() using gridAgentBaseData.copy(currentSweepNo = requestSweepNo) - } + simulateGrid( + gridAgentBaseData.copy(currentSweepNo = requestSweepNo), + currentTick + ) + } - // / after power flow calc for this sweepNo - case Event( - RequestGridPowerMessage(_, requestedNodeUuids), - powerFlowDoneData @ PowerFlowDoneData( - gridAgentBaseData, - powerFlowResult, - pendingRequestAnswers + // after power flow calc for this sweepNo + case ( + PMAdapter(RequestGridPowerMessage(_, requestedNodeUuids, sender)), + powerFlowDoneData @ PowerFlowDoneData( + gridAgentBaseData, + powerFlowResult, + pendingRequestAnswers + ) + ) => + /* Determine the subgrid number of the grid agent, that has sent the request */ + val firstRequestedNodeUuid = requestedNodeUuids.headOption.getOrElse( + throw new DBFSAlgorithmException( + "Did receive a grid power request but without specified nodes" + ) ) - ) => - /* Determine the subgrid number of the grid agent, that has sent the request */ - val firstRequestedNodeUuid = requestedNodeUuids.headOption.getOrElse( - throw new DBFSAlgorithmException( - "Did receive a grid power request but without specified nodes" - ) - ) - gridAgentBaseData.gridEnv.subgridGateToActorRef - .map { case (subGridGate, _) => subGridGate.superiorNode } - .find(_.getUuid == firstRequestedNodeUuid) - .map(_.getSubnet) match { - case Some(requestingSubgridNumber) => - powerFlowResult match { - case validNewtonRaphsonPFResult: ValidNewtonRaphsonPFResult => - val exchangePowers = requestedNodeUuids - .map { nodeUuid => - /* Figure out the node index for each requested node */ - nodeUuid -> gridAgentBaseData.gridEnv.gridModel.nodeUuidToIndexMap - .get(nodeUuid) - .flatMap { nodeIndex => - /* Find matching node result */ - validNewtonRaphsonPFResult.nodeData.find(stateData => - stateData.index == nodeIndex - ) + + gridAgentBaseData.gridEnv.subgridGateToActorRef + .map { case (subGridGate, _) => subGridGate.superiorNode } + .find(_.getUuid == firstRequestedNodeUuid) + .map(_.getSubnet) match { + case Some(requestingSubgridNumber) => + powerFlowResult match { + case validNewtonRaphsonPFResult: ValidNewtonRaphsonPFResult => + val exchangePowers = requestedNodeUuids + .map { nodeUuid => + /* Figure out the node index for each requested node */ + nodeUuid -> gridAgentBaseData.gridEnv.gridModel.nodeUuidToIndexMap + .get(nodeUuid) + .flatMap { nodeIndex => + /* Find matching node result */ + validNewtonRaphsonPFResult.nodeData.find(stateData => + stateData.index == nodeIndex + ) + } + .map { + case StateData(_, nodeType, _, power) + if nodeType == NodeType.SL => + val refSystem = + gridAgentBaseData.gridEnv.gridModel.mainRefSystem + val (pInPu, qInPu) = + (power.real, power.imag) + // The power flow result data provides the nodal residual power at the slack node. + // A feed-in case from the inferior grid TO the superior grid leads to positive residual power at the + // inferior grid's *slack node* (superior grid seems to be a load to the inferior grid). + // To model the exchanged power from the superior grid's point of view, -1 has to be multiplied. + // (Inferior grid is a feed in facility to superior grid, which is negative then). Analogously for load case. + ( + refSystem.pInSi(pInPu) * (-1), + refSystem.qInSi(qInPu) * (-1) + ) + case _ => + /* TODO: As long as there are no multiple slack nodes, provide "real" power only for the slack node */ + ( + Megawatts(0d), + Megavars(0d) + ) + } + .getOrElse { + throw new DBFSAlgorithmException( + s"Got a request for power @ node with uuid $requestedNodeUuids but cannot find it in my result data!" + ) + } } - .map { - case StateData(_, nodeType, _, power) - if nodeType == NodeType.SL => - val refSystem = - gridAgentBaseData.gridEnv.gridModel.mainRefSystem - val (pInPu, qInPu) = - (power.real, power.imag) - // The power flow result data provides the nodal residual power at the slack node. - // A feed-in case from the inferior grid TO the superior grid leads to positive residual power at the - // inferior grid's *slack node* (superior grid seems to be a load to the inferior grid). - // To model the exchanged power from the superior grid's point of view, -1 has to be multiplied. - // (Inferior grid is a feed in facility to superior grid, which is negative then). Analogously for load case. - ( - refSystem.pInSi(pInPu) * (-1), - refSystem.qInSi(qInPu) * (-1) - ) - case _ => - /* TODO: As long as there are no multiple slack nodes, provide "real" power only for the slack node */ - ( - Megawatts(0d), - Megavars(0d) - ) + .map { case (nodeUuid, (p, q)) => + ProvideGridPowerMessage.ExchangePower( + nodeUuid, + p, + q + ) } - .getOrElse { - throw new DBFSAlgorithmException( - s"Got a request for power @ node with uuid $requestedNodeUuids but cannot find it in my result data!" + + /* Determine the remaining replies */ + val stillPendingRequestAnswers = + pendingRequestAnswers.filterNot( + _ == requestingSubgridNumber + ) + + // update the sweep value store and clear all received maps + // note: normally it is expected that this has to be done after power flow calculations but for the sake + // of having it only once in the code we put this here. Otherwise it would have to been put before EVERY + // return with a valid power flow result (currently happens already in two situations) + val updatedGridAgentBaseData = + if (stillPendingRequestAnswers.isEmpty) { + gridAgentBaseData.storeSweepDataAndClearReceiveMaps( + validNewtonRaphsonPFResult, + gridAgentBaseData.superiorGridNodeUuids, + gridAgentBaseData.inferiorGridGates + ) + } else { + powerFlowDoneData.copy(pendingRequestAnswers = + stillPendingRequestAnswers ) } - } - .map { case (nodeUuid, (p, q)) => - ProvideGridPowerMessage.ExchangePower( - nodeUuid, - p, - q - ) - } - /* Determine the remaining replies */ - val stillPendingRequestAnswers = - pendingRequestAnswers.filterNot(_ == requestingSubgridNumber) - - // update the sweep value store and clear all received maps - // note: normally it is expected that this has to be done after power flow calculations but for the sake - // of having it only once in the code we put this here. Otherwise it would have to been put before EVERY - // return with a valid power flow result (currently happens already in two situations) - val updatedGridAgentBaseData = - if (stillPendingRequestAnswers.isEmpty) { - gridAgentBaseData.storeSweepDataAndClearReceiveMaps( - validNewtonRaphsonPFResult, - gridAgentBaseData.superiorGridNodeUuids, - gridAgentBaseData.inferiorGridGates - ) - } else { - powerFlowDoneData.copy(pendingRequestAnswers = - stillPendingRequestAnswers - ) - } + sender ! PMAdapter(ProvideGridPowerMessage(exchangePowers)) + simulateGrid(updatedGridAgentBaseData, currentTick) - stay() replying - ProvideGridPowerMessage( - exchangePowers - ) using updatedGridAgentBaseData + case _: FailedNewtonRaphsonPFResult => + sender ! PMAdapter(FailedPowerFlow) + simulateGrid(gridAgentBaseData, currentTick) + } + case None => + /* It is not possible to determine, who has asked */ + ctx.log.error( + "I got a grid power request from a subgrid I don't know. Can't answer it properly." + ) - case _: FailedNewtonRaphsonPFResult => - stay() replying FailedPowerFlow using gridAgentBaseData + sender ! PMAdapter(FailedPowerFlow) + Behaviors.same } - case None => - /* It is not possible to determine, who has asked */ - log.error( - "I got a grid power request from a subgrid I don't know. Can't answer it properly." - ) - stay() replying FailedPowerFlow using gridAgentBaseData - } - // called when a grid power values request from a superior grid is received - // which is similar to a new sweep and causes a) a power flow with updated slack voltage values and - // b) afterwards a request for updated power values from inferior grids and assets with updated voltage values - // based on the just carried out power flow - case Event( - PrepareNextSweepTrigger(_), - gridAgentBaseData: GridAgentBaseData - ) => - // request the updated slack voltages from the superior grid - askSuperiorGridsForSlackVoltages( - gridAgentBaseData.currentSweepNo, - gridAgentBaseData.gridEnv.subgridGateToActorRef, - gridAgentBaseData.superiorGridGates, - gridAgentBaseData.powerFlowParams.sweepTimeout - ) + // called when a grid power values request from a superior grid is received + // which is similar to a new sweep and causes a) a power flow with updated slack voltage values and + // b) afterwards a request for updated power values from inferior grids and assets with updated voltage values + // based on the just carried out power flow + case ( + PrepareNextSweepTrigger(_), + gridAgentBaseData: GridAgentBaseData + ) => + // request the updated slack voltages from the superior grid + askSuperiorGridsForSlackVoltages( + gridAgentBaseData.currentSweepNo, + gridAgentBaseData.gridEnv.subgridGateToActorRef, + gridAgentBaseData.superiorGridGates, + gridAgentBaseData.powerFlowParams.sweepTimeout + )(ctx) + + ctx.log.debug(s"Going to HandlePowerFlowCalculation") + + handlePowerFlowCalculations(gridAgentBaseData, currentTick) + + // last step which should includes a) information on inferior grids about finish and + // b) cleanup of receiveMaps and sweepStore + case ( + FinishGridSimulationTrigger(currentTick), + gridAgentBaseData: GridAgentBaseData + ) => + // inform my child grids about the end of this grid simulation + gridAgentBaseData.inferiorGridGates + .map { + gridAgentBaseData.gridEnv.subgridGateToActorRef(_) + } + .distinct + .foreach( + _ ! FinishGridSimulationTrigger(currentTick) + ) - log.debug(s"Going to {}", HandlePowerFlowCalculations) - - goto(HandlePowerFlowCalculations) using gridAgentBaseData - - // last step which should includes a) information on inferior grids about finish and - // b) cleanup of receiveMaps and sweepStore - case Event( - FinishGridSimulationTrigger(currentTick), - gridAgentBaseData: GridAgentBaseData - ) => - // inform my child grids about the end of this grid simulation - gridAgentBaseData.inferiorGridGates - .map { - gridAgentBaseData.gridEnv.subgridGateToActorRef(_) - } - .distinct - .foreach(_ ! FinishGridSimulationTrigger(currentTick)) - - // inform every system participant about the end of this grid simulation - gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => - actors.foreach(actor => { - actor ! FinishGridSimulationTrigger( - currentTick - ) - }) - } + // inform every system participant about the end of this grid simulation + gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { + case (_, actors) => + actors.foreach { actor => + actor.toClassic ! FinishGridSimulationTrigger(currentTick) + } + } - // notify listener about the results - log.debug("Calculate results and sending the results to the listener ...") - createAndSendPowerFlowResults( - gridAgentBaseData, - currentTick.toDateTime(simStartTime) - ) + // notify listener about the results + ctx.log.debug( + "Calculate results and sending the results to the listener ..." + ) + createAndSendPowerFlowResults( + gridAgentBaseData, + currentTick.toDateTime(simStartTime) + )(ctx.log) - // do my cleanup stuff - log.debug("Doing my cleanup stuff") + // do my cleanup stuff + ctx.log.debug("Doing my cleanup stuff") - // / clean copy of the gridAgentBaseData - val cleanedGridAgentBaseData = GridAgentBaseData.clean( - gridAgentBaseData, - gridAgentBaseData.superiorGridNodeUuids, - gridAgentBaseData.inferiorGridGates - ) + // / clean copy of the gridAgentBaseData + val cleanedGridAgentBaseData = GridAgentBaseData.clean( + gridAgentBaseData, + gridAgentBaseData.superiorGridNodeUuids, + gridAgentBaseData.inferiorGridGates + ) - // / release tick for the whole simulation (StartGridSimulationTrigger) - releaseTick() + // / inform scheduler that we are done with the whole simulation and request new trigger for next time step + environmentRefs.scheduler ! Completion( + activationAdapter, + Some(currentTick + resolution) + ) - // / inform scheduler that we are done with the whole simulation and request new trigger for next time step - environmentRefs.scheduler ! Completion( - self.toTyped, - Some(currentTick + resolution) - ) + // return to Idle + idle(cleanedGridAgentBaseData) - // return to Idle - goto(Idle) using cleanedGridAgentBaseData + case (StopGridAgent, _) => + Behaviors.stopped + case (_, _) => + Behaviors.unhandled + } } - /** Every power flow calculation should take place here. Generally used for - * power flow calculations only and only if all data required are already - * received as requested. + /** Method that defines the [[Behavior]] for handling the power flow + * calculations. Generally used for power flow calculations only and only if + * all data required are already received as requested. + * + * @param gridAgentData + * state data of the actor + * @param currentTick + * current simulation tick + * @return + * a [[Behavior]] */ - when(HandlePowerFlowCalculations) { - - // main method for power flow calculations - case Event( - DoPowerFlowTrigger(currentTick, _), - gridAgentBaseData: GridAgentBaseData - ) => - log.debug( - "Received the following power values to the corresponding nodes: {}", - gridAgentBaseData.receivedValueStore.nodeToReceivedPower - ) - - val gridModel = gridAgentBaseData.gridEnv.gridModel - - val (operatingPoint, slackNodeVoltages) = composeOperatingPoint( - gridModel.gridComponents.nodes, - gridModel.gridComponents.transformers, - gridModel.gridComponents.transformers3w, - gridModel.nodeUuidToIndexMap, - gridAgentBaseData.receivedValueStore, - gridModel.mainRefSystem - ) - - newtonRaphsonPF( - gridModel, - gridAgentBaseData.powerFlowParams.maxIterations, - operatingPoint, - slackNodeVoltages - )(gridAgentBaseData.powerFlowParams.epsilon) match { - // if res is valid, ask our assets (if any) for updated power values based on the newly determined nodal voltages - case validPowerFlowResult: ValidNewtonRaphsonPFResult => - log.debug( - "{}", - composeValidNewtonRaphsonPFResultVoltagesDebugString( - validPowerFlowResult, - gridModel - ) + private def handlePowerFlowCalculations( + gridAgentData: GridAgentData, + currentTick: Long + ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + (ctx, message) => + (message, gridAgentData) match { + + // main method for power flow calculations + case ( + DoPowerFlowTrigger(currentTick, _), + gridAgentBaseData: GridAgentBaseData + ) => + ctx.log.debug( + "Received the following power values to the corresponding nodes: {}", + gridAgentBaseData.receivedValueStore.nodeToReceivedPower ) - val powerFlowDoneData = - PowerFlowDoneData(gridAgentBaseData, validPowerFlowResult) + val gridModel = gridAgentBaseData.gridEnv.gridModel - val sweepValueStoreOpt = Some( - SweepValueStore( - validPowerFlowResult, - gridModel.gridComponents.nodes, - gridModel.nodeUuidToIndexMap - ) + val (operatingPoint, slackNodeVoltages) = composeOperatingPoint( + gridModel.gridComponents.nodes, + gridModel.gridComponents.transformers, + gridModel.gridComponents.transformers3w, + gridModel.nodeUuidToIndexMap, + gridAgentBaseData.receivedValueStore, + gridModel.mainRefSystem ) - askForAssetPowers( - currentTick, - sweepValueStoreOpt, - gridAgentBaseData.gridEnv.nodeToAssetAgents, - gridModel.mainRefSystem, - gridAgentBaseData.powerFlowParams.sweepTimeout - ) match { - case None => - // when we don't have assets we can skip another request for different asset behaviour due to changed - // voltage values and go back to SimulateGrid directly - log.debug( - s"No generation or load assets in the grid. Going back to {}.", - SimulateGrid - ) - unstashAll() // we can answer the stashed grid power requests now - goto(SimulateGrid) using powerFlowDoneData - case Some(_) => - // will return a future based on the `ask-pattern` which will be processed below - stay() using powerFlowDoneData - } - case failedNewtonRaphsonPFResult: FailedNewtonRaphsonPFResult => - val powerFlowDoneData = - PowerFlowDoneData(gridAgentBaseData, failedNewtonRaphsonPFResult) - log.warning( - "Power flow calculation before asking for updated powers did finally not converge!" - ) - unstashAll() // we can answer the stashed grid power requests now and report a failed power flow back - goto(SimulateGrid) using powerFlowDoneData - } + newtonRaphsonPF( + gridModel, + gridAgentBaseData.powerFlowParams.maxIterations, + operatingPoint, + slackNodeVoltages + )(gridAgentBaseData.powerFlowParams.epsilon)(ctx.log) match { + // if res is valid, ask our assets (if any) for updated power values based on the newly determined nodal voltages + case validPowerFlowResult: ValidNewtonRaphsonPFResult => + ctx.log.debug( + "{}", + composeValidNewtonRaphsonPFResultVoltagesDebugString( + validPowerFlowResult, + gridModel + ) + ) - // handler for the future provided by `askForAssetPowers` to check if there are any changes in generation/load - // of assets based on updated nodal voltages - case Event( - receivedPowerValues: ReceivedPowerValues, - powerFlowDoneData: PowerFlowDoneData - ) => - val gridAgentBaseData = powerFlowDoneData.gridAgentBaseData - - // check if we have changed values from our assets - // if yes, we do another PF with adapted values - // if no, we are done with the pf and ready to report to our parent grid - val changed = receivedPowerValues.values.exists { - case (_, _: AssetPowerChangedMessage) => true - case _ => false - } + val powerFlowDoneData = + PowerFlowDoneData(gridAgentBaseData, validPowerFlowResult) - if (changed) { - log.debug( - "Assets have changed their exchanged power with the grid. Update nodal powers and prepare new power flow." - ) - val updatedGridAgentBaseData: GridAgentBaseData = - receivedPowerValues match { - case receivedPowers: ReceivedPowerValues => - gridAgentBaseData.updateWithReceivedPowerValues( - receivedPowers, - replace = true - ) - case unknownValuesReceived => - throw new DBFSAlgorithmException( - s"Received unsuitable values: $unknownValuesReceived" + val sweepValueStoreOpt = Some( + SweepValueStore( + validPowerFlowResult, + gridModel.gridComponents.nodes, + gridModel.nodeUuidToIndexMap + ) ) - } + askForAssetPowers( + currentTick, + sweepValueStoreOpt, + gridAgentBaseData.gridEnv.nodeToAssetAgents, + gridModel.mainRefSystem, + gridAgentBaseData.powerFlowParams.sweepTimeout + )(ctx) match { + case None => + // when we don't have assets we can skip another request for different asset behaviour due to changed + // voltage values and go back to SimulateGrid directly + ctx.log.debug( + s"No generation or load assets in the grid. Going back to SimulateGrid." + ) - // check if we have enough data for a power flow calculation - // if yes, go to the powerflow - // if no, stay and wait - val readyForPowerFlow = - updatedGridAgentBaseData.allRequestedDataReceived - log.debug( - "{}", - if (readyForPowerFlow) - "Got answers for all my requests for Slack Voltages and Power Values." - else - "Still waiting for answers my requests for Slack Voltages and Power Values." - ) + // we can answer the stashed grid power requests now + buffer.unstashAll( + simulateGrid(powerFlowDoneData, currentTick) + ) - goToPowerFlowCalculationOrStay( - readyForPowerFlow, - updatedGridAgentBaseData - ) + case Some(_) => + // will return a future based on the `ask-pattern` which will be processed below + handlePowerFlowCalculations(powerFlowDoneData, currentTick) + } - } else { - // no changes from assets, we want to go back to SimulateGrid and report the LF results to our parent grids if any requests - log.debug( - s"Assets have not changed their exchanged power or no voltage dependent behaviour. Going back to {}.", - SimulateGrid - ) - unstashAll() // we can answer the stashed grid power requests now - goto(SimulateGrid) using powerFlowDoneData + case failedNewtonRaphsonPFResult: FailedNewtonRaphsonPFResult => + val powerFlowDoneData = + PowerFlowDoneData( + gridAgentBaseData, + failedNewtonRaphsonPFResult + ) + ctx.log.warn( + "Power flow calculation before asking for updated powers did finally not converge!" + ) + // we can answer the stashed grid power requests now and report a failed power flow back + buffer.unstashAll(simulateGrid(powerFlowDoneData, currentTick)) + } - } + // handler for the future provided by `askForAssetPowers` to check if there are any changes in generation/load + // of assets based on updated nodal voltages + case ( + ValuesAdapter(receivedPowerValues: ReceivedPowerValues), + powerFlowDoneData: PowerFlowDoneData + ) => + val gridAgentBaseData = powerFlowDoneData.gridAgentBaseData + + // check if we have changed values from our assets + // if yes, we do another PF with adapted values + // if no, we are done with the pf and ready to report to our parent grid + val changed = receivedPowerValues.values.exists { + case (_, _: AssetPowerChangedMessage) => true + case _ => false + } - // executed after request from the superior grid to execute a new sweep (forward sweep state) - // this means we requested an update of the slack voltage values, but for now don't request (and hence don't expect) - // updated power values for our power flow calculations - case Event( - receivedSlackValues: ReceivedSlackVoltageValues, - gridAgentBaseData: GridAgentBaseData - ) => - log.debug( - "Received Slack values for new forward sweep with same power but updated voltage values" - ) + if (changed) { + ctx.log.debug( + "Assets have changed their exchanged power with the grid. Update nodal powers and prepare new power flow." + ) + val updatedGridAgentBaseData: GridAgentBaseData = + receivedPowerValues match { + case receivedPowers: ReceivedPowerValues => + gridAgentBaseData.updateWithReceivedPowerValues( + receivedPowers, + replace = true + ) + case unknownValuesReceived => + throw new DBFSAlgorithmException( + s"Received unsuitable values: $unknownValuesReceived" + ) + } - // power flow - val gridModel = gridAgentBaseData.gridEnv.gridModel - val previousSweepData = gridAgentBaseData.sweepValueStores.getOrElse( - gridAgentBaseData.currentSweepNo - 1, - throw new DBFSAlgorithmException( - s"$actorName Unable to get results from previous sweep ${gridAgentBaseData.currentSweepNo - 1}!" - ) - ) + // check if we have enough data for a power flow calculation + // if yes, go to the powerflow + // if no, stay and wait + val readyForPowerFlow = + updatedGridAgentBaseData.allRequestedDataReceived + ctx.log.debug( + "{}", + if (readyForPowerFlow) + "Got answers for all my requests for Slack Voltages and Power Values." + else + "Still waiting for answers my requests for Slack Voltages and Power Values." + ) - val (operatingPoint, slackNodeVoltages) = - composeOperatingPointWithUpdatedSlackVoltages( - receivedSlackValues, - previousSweepData.sweepData, - gridModel.gridComponents.transformers, - gridModel.gridComponents.transformers3w, - gridModel.mainRefSystem - ) + goToPowerFlowCalculationOrStay( + readyForPowerFlow, + updatedGridAgentBaseData, + currentTick, + handlePowerFlowCalculations + )(ctx) - newtonRaphsonPF( - gridModel, - gridAgentBaseData.powerFlowParams.maxIterations, - operatingPoint, - slackNodeVoltages - )(gridAgentBaseData.powerFlowParams.epsilon) match { - case validPowerFlowResult: ValidNewtonRaphsonPFResult => - log.debug( - "{}", - composeValidNewtonRaphsonPFResultVoltagesDebugString( - validPowerFlowResult, - gridModel + } else { + // no changes from assets, we want to go back to SimulateGrid and report the LF results to our parent grids if any requests + ctx.log.debug( + s"Assets have not changed their exchanged power or no voltage dependent behaviour. Going back to SimulateGrid." ) - ) + // we can answer the stashed grid power requests now + buffer.unstashAll(simulateGrid(powerFlowDoneData, currentTick)) + } - // update the data - val sweepValueStore = SweepValueStore( - validPowerFlowResult, - gridModel.gridComponents.nodes, - gridModel.nodeUuidToIndexMap + // executed after request from the superior grid to execute a new sweep (forward sweep state) + // this means we requested an update of the slack voltage values, but for now don't request (and hence don't expect) + // updated power values for our power flow calculations + case ( + ValuesAdapter(receivedSlackValues: ReceivedSlackVoltageValues), + gridAgentBaseData: GridAgentBaseData + ) => + ctx.log.debug( + "Received Slack values for new forward sweep with same power but updated voltage values" ) - val updatedSweepValueStore = - gridAgentBaseData.sweepValueStores + (gridAgentBaseData.currentSweepNo -> sweepValueStore) - // send request to child grids and assets for updated p/q values - // we start the grid simulation by requesting the p/q values of all the nodes we are responsible for - // as well as the slack voltage power from our superior grid - // 1. assets p/q values - val askForAssetPowersOpt = - askForAssetPowers( - currentTick, - Some(sweepValueStore), - gridAgentBaseData.gridEnv.nodeToAssetAgents, - gridModel.mainRefSystem, - gridAgentBaseData.powerFlowParams.sweepTimeout + // power flow + val gridModel = gridAgentBaseData.gridEnv.gridModel + val previousSweepData = gridAgentBaseData.sweepValueStores.getOrElse( + gridAgentBaseData.currentSweepNo - 1, + throw new DBFSAlgorithmException( + s"$actorName Unable to get results from previous sweep ${gridAgentBaseData.currentSweepNo - 1}!" ) + ) - // 2. inferior grids p/q values - val askForInferiorGridPowersOpt = - askInferiorGridsForPowers( - gridAgentBaseData.currentSweepNo, - gridAgentBaseData.gridEnv.subgridGateToActorRef, - gridAgentBaseData.inferiorGridGates, - gridAgentBaseData.powerFlowParams.sweepTimeout + val (operatingPoint, slackNodeVoltages) = + composeOperatingPointWithUpdatedSlackVoltages( + receivedSlackValues, + previousSweepData.sweepData, + gridModel.gridComponents.transformers, + gridModel.gridComponents.transformers3w, + gridModel.mainRefSystem ) - // when we don't have inferior grids and no assets both methods return None and we can skip doing another power - // flow calculation otherwise we go back to simulate grid and wait for the answers - (askForAssetPowersOpt, askForInferiorGridPowersOpt) match { - case (None, None) => - log.debug( - "I don't have assets or child grids. " + - "Going back to SimulateGrid and provide the power flow result if there is any request left." + newtonRaphsonPF( + gridModel, + gridAgentBaseData.powerFlowParams.maxIterations, + operatingPoint, + slackNodeVoltages + )(gridAgentBaseData.powerFlowParams.epsilon)(ctx.log) match { + case validPowerFlowResult: ValidNewtonRaphsonPFResult => + ctx.log.debug( + "{}", + composeValidNewtonRaphsonPFResultVoltagesDebugString( + validPowerFlowResult, + gridModel + ) ) - val powerFlowDoneData = - PowerFlowDoneData(gridAgentBaseData, validPowerFlowResult) + // update the data + val sweepValueStore = SweepValueStore( + validPowerFlowResult, + gridModel.gridComponents.nodes, + gridModel.nodeUuidToIndexMap + ) + val updatedSweepValueStore = + gridAgentBaseData.sweepValueStores + (gridAgentBaseData.currentSweepNo -> sweepValueStore) + + // send request to child grids and assets for updated p/q values + // we start the grid simulation by requesting the p/q values of all the nodes we are responsible for + // as well as the slack voltage power from our superior grid + // 1. assets p/q values + val askForAssetPowersOpt = + askForAssetPowers( + currentTick, + Some(sweepValueStore), + gridAgentBaseData.gridEnv.nodeToAssetAgents, + gridModel.mainRefSystem, + gridAgentBaseData.powerFlowParams.sweepTimeout + )(ctx) + + // 2. inferior grids p/q values + val askForInferiorGridPowersOpt = + askInferiorGridsForPowers( + gridAgentBaseData.currentSweepNo, + gridAgentBaseData.gridEnv.subgridGateToActorRef, + gridAgentBaseData.inferiorGridGates, + gridAgentBaseData.powerFlowParams.sweepTimeout + )(ctx) + + // when we don't have inferior grids and no assets both methods return None and we can skip doing another power + // flow calculation otherwise we go back to simulate grid and wait for the answers + (askForAssetPowersOpt, askForInferiorGridPowersOpt) match { + case (None, None) => + ctx.log.debug( + "I don't have assets or child grids. " + + "Going back to SimulateGrid and provide the power flow result if there is any request left." + ) - unstashAll() // we can answer the stashed grid power requests now - goto(SimulateGrid) using powerFlowDoneData + val powerFlowDoneData = + PowerFlowDoneData(gridAgentBaseData, validPowerFlowResult) - case _ => - log.debug( - "Going back to SimulateGrid and wait for my assets or inferior grids to return." - ) + // we can answer the stashed grid power requests now + buffer.unstashAll( + simulateGrid(powerFlowDoneData, currentTick) + ) + + case _ => + ctx.log.debug( + "Going back to SimulateGrid and wait for my assets or inferior grids to return." + ) - // go back to simulate grid - goto(SimulateGrid) using gridAgentBaseData - .updateWithReceivedSlackVoltages(receivedSlackValues) - .copy(sweepValueStores = updatedSweepValueStore) + // go back to simulate grid + simulateGrid( + gridAgentBaseData + .updateWithReceivedSlackVoltages(receivedSlackValues) + .copy(sweepValueStores = updatedSweepValueStore), + currentTick + ) + } + + case failedNewtonRaphsonPFResult: FailedNewtonRaphsonPFResult => + val powerFlowDoneData = + PowerFlowDoneData( + gridAgentBaseData, + failedNewtonRaphsonPFResult + ) + ctx.log.warn( + "Power flow with updated slack voltage did finally not converge!" + ) + // we can answer the stashed grid power requests now and report a failed power flow back + buffer.unstashAll(simulateGrid(powerFlowDoneData, currentTick)) } - case failedNewtonRaphsonPFResult: FailedNewtonRaphsonPFResult => - val powerFlowDoneData = - PowerFlowDoneData( - gridAgentBaseData, - failedNewtonRaphsonPFResult - ) - log.warning( - "Power flow with updated slack voltage did finally not converge!" + // happens only when we received slack data and power values before we received a request to provide grid data + // (only possible when first simulation triggered and this agent is faster in this state as the request + // by a superior grid arrives) + case ( + PMAdapter(requestGridPowerMessage: RequestGridPowerMessage), + _: GridAgentBaseData + ) => + ctx.log.debug( + "Received Request for Grid Power too early. Stashing away" ) - unstashAll() // we can answer the stashed grid power requests now and report a failed power flow back - goto(SimulateGrid) using powerFlowDoneData - } + buffer.stash(PMAdapter(requestGridPowerMessage)) + Behaviors.same + + // happens only when we received slack data and power values before we received a request to provide grid + // (only possible when first simulation triggered and this agent is faster + // with its power flow calculation in this state as the request by a superior grid arrives) + case ( + PMAdapter(requestGridPowerMessage: RequestGridPowerMessage), + _: PowerFlowDoneData + ) => + ctx.log.debug( + "Received Request for Grid Power too early. Stashing away" + ) + + buffer.stash(PMAdapter(requestGridPowerMessage)) + Behaviors.same - // happens only when we received slack data and power values before we received a request to provide grid data - // (only possible when first simulation triggered and this agent is faster in this state as the request - // by a superior grid arrives) - case Event( - _: RequestGridPowerMessage, - _: GridAgentBaseData - ) => - log.debug("Received Request for Grid Power too early. Stashing away") - stash() - stay() - - // happens only when we received slack data and power values before we received a request to provide gride - // (only possible when first simulation triggered and this agent is faster - // with its power flow calculation in this state as the request by a superior grid arrives) - case Event( - _: RequestGridPowerMessage, - _: PowerFlowDoneData - ) => - log.debug("Received Request for Grid Power too early. Stashing away") - stash() - stay() + case (StopGridAgent, _) => + Behaviors.stopped + case (_, _) => + Behaviors.unhandled + } } - // should be reached by the superior (dummy) grid agent only - when(CheckPowerDifferences) { + /** Method used for checking the power difference.

This method should only + * be reached by the superior (dummy) grid agent. + * @param gridAgentBaseData + * state data of the actor + * @return + * a [[Behavior]] + */ + private def checkPowerDifferences( + gridAgentBaseData: GridAgentBaseData + ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { - case Event( - CheckPowerDifferencesTrigger(currentTick), - gridAgentBaseData: GridAgentBaseData - ) => - log.debug("Starting the power differences check ...") + case (ctx, CheckPowerDifferencesTrigger(currentTick)) => + ctx.log.debug("Starting the power differences check ...") val currentSweepNo = gridAgentBaseData.currentSweepNo val gridModel = gridAgentBaseData.gridEnv.gridModel @@ -770,7 +861,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { val nodeData = operationPoint.map(StateData(_)) ValidNewtonRaphsonPFResult(-1, nodeData, DenseMatrix(0d, 0d)) } else { - log.debug( + ctx.log.debug( "This grid contains a three winding transformer. Perform power flow calculations before assessing the power deviations." ) newtonRaphsonPF( @@ -778,9 +869,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentBaseData.powerFlowParams.maxIterations, operationPoint, slackNodeVoltages - )(gridAgentBaseData.powerFlowParams.epsilon) match { + )(gridAgentBaseData.powerFlowParams.epsilon)(ctx.log) match { case validPowerFlowResult: ValidNewtonRaphsonPFResult => - log.debug( + ctx.log.debug( "{}", composeValidNewtonRaphsonPFResultVoltagesDebugString( validPowerFlowResult, @@ -805,13 +896,17 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // the difference is checked @ the higher nodes of our transformers => the slack nodes // if we are either in the first backward sweep OR if the deviation is bigger as allowed, we need a second sweep if (gridAgentBaseData.sweepValueStores.isEmpty) { - log.debug("Sweep value store is empty. Starting a second sweep ...") + ctx.log.debug( + "Sweep value store is empty. Starting a second sweep ..." + ) goToSimulateGridForNextSweepWith( updatedGridAgentBaseData, currentTick ) } else { - log.debug("Sweep value store is not empty. Check for deviation ...") + ctx.log.debug( + "Sweep value store is not empty. Check for deviation ..." + ) // calculate deviation vector for all nodes val previousSweepNodePower: DenseVector[Complex] = @@ -850,7 +945,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { Math.abs(complex.imag) >= allowedDeviation }) match { case Some(deviation) => // next sweep - log.debug( + ctx.log.debug( "Deviation between the last two sweeps: {}", deviation ) @@ -859,56 +954,62 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { currentTick ) case None => // we're done - log.debug("We found a result! :-)") + ctx.log.debug("We found a result! :-)") - log.debug( + ctx.log.debug( "Final deviation: {}", (previousSweepNodePower - currentSweepNodePower).toScalaVector ) // go back to SimulateGrid and trigger a finish - self ! FinishGridSimulationTrigger(currentTick) - goto(SimulateGrid) - + ctx.self ! FinishGridSimulationTrigger(currentTick) + simulateGrid(gridAgentBaseData, currentTick) } } case failedResult: PowerFlowResult.FailedPowerFlowResult => - log.warning( + ctx.log.warn( "Power flow for high voltage branch of three winding transformer failed after {} iterations. Cause: {}", failedResult.iteration, failedResult.cause ) - self ! FinishGridSimulationTrigger(currentTick) - handlePowerFlowFailure(gridAgentBaseData) - goto(SimulateGrid) using gridAgentBaseData + ctx.self ! FinishGridSimulationTrigger(currentTick) + handlePowerFlowFailure(gridAgentBaseData)(ctx) + simulateGrid(gridAgentBaseData, currentTick) } + + case (_, StopGridAgent) => + Behaviors.stopped + + case (_, _) => + Behaviors.unhandled } /** Checks if all data has been received and if yes checks if the there are * any failed power flow indications from inferior grids. If both == true, - * then no state change is triggered but the sweep value store is updated - * with a [[FailedPowerFlow]] information as well, the now used data is set - * to [[PowerFlowDoneData]] and this is escalated to the superior grid(s). If - * there is no [[FailedPowerFlow]] in the [[GridAgentBaseData]] a state - * transition to [[HandlePowerFlowCalculations]] is triggered. + * then no [[Behavior]] change is triggered but the sweep value store is + * updated with a [[FailedPowerFlow]] information as well, the now used data + * is set to [[PowerFlowDoneData]] and this is escalated to the superior + * grid(s). If there is no [[FailedPowerFlow]] in the [[GridAgentBaseData]] a + * behavior transition to [[handlePowerFlowCalculations]] is triggered. * - * If allReceived == false, no state transition is triggered + * If allReceived == false, no [[Behavior]] transition is triggered * * @param allReceived * indicates if all requested data has been received * @param gridAgentBaseData * the current or updated data of the [[GridAgent]] * @return - * either the same state the agent is currently in or a transition to - * [[HandlePowerFlowCalculations]] + * either the same behavior the agent is currently in or a transition to + * [[handlePowerFlowCalculations]] */ private def goToPowerFlowCalculationOrStay( allReceived: Boolean, - gridAgentBaseData: GridAgentBaseData - ): FSM.State[AgentState, GridAgentData] = { - + gridAgentBaseData: GridAgentBaseData, + currentTick: Long, + behavior: (GridAgentData, Long) => Behavior[GridAgentMessage] + )(implicit ctx: ActorContext[GridAgentMessage]): Behavior[GridAgentMessage] = if (allReceived) { - log.debug( + ctx.log.debug( "All power values of inferior grids, assets + voltage superior grid slack voltages received." ) @@ -918,26 +1019,33 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { .exists(v => v.exists(k => k._2.contains(FailedPowerFlow))) if (powerFlowFailedSomewhereInInferior) { - log.warning("Received Failed Power Flow Result. Escalate to my parent.") - unstashAll() // we want to answer the requests from our parent - stay() using PowerFlowDoneData( + ctx.log.warn( + "Received Failed Power Flow Result. Escalate to my parent." + ) + + // we want to answer the requests from our parent + val powerFlowDoneData = PowerFlowDoneData( gridAgentBaseData, FailedNewtonRaphsonPFResult(-1, CalculationFailed) ) + + buffer.unstashAll(behavior(powerFlowDoneData, currentTick)) } else { - self ! DoPowerFlowTrigger(currentTick, gridAgentBaseData.currentSweepNo) - goto(HandlePowerFlowCalculations) using gridAgentBaseData + ctx.self ! DoPowerFlowTrigger( + currentTick, + gridAgentBaseData.currentSweepNo + ) + handlePowerFlowCalculations(gridAgentBaseData, currentTick) } } else { - log.debug( + ctx.log.debug( "Still waiting for asset or grid power values or slack voltage information of inferior grids" ) - stay() using gridAgentBaseData - } - } + buffer.unstashAll(behavior(gridAgentBaseData, currentTick)) + } /** Normally only reached by the superior (dummy) agent! * @@ -947,8 +1055,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * this step is skipped and the simulation goes on or this leads to a * termination of the simulation due to a failed power flow calculation. * - * If there is no [[FailedPowerFlow]] in the [[GridAgentBaseData]] a state - * transition to [[CheckPowerDifferences]] is triggered. + * If there is no [[FailedPowerFlow]] in the [[GridAgentBaseData]] a + * [[Behavior]] transition to [[checkPowerDifferences]] is triggered. * * If allReceived == false, no state transition is triggered * @@ -959,15 +1067,21 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * @param gridAgentBaseData * the current or updated data of the [[GridAgent]] * @return - * either the same state the agent is currently in or a transition to - * [[CheckPowerDifferences]] + * either the same behavior the agent is currently in or a transition to + * [[checkPowerDifferences]] */ private def goToCheckPowerDifferencesOrStay( allReceived: Boolean, - gridAgentBaseData: GridAgentBaseData - ): FSM.State[AgentState, GridAgentData] = { + gridAgentBaseData: GridAgentBaseData, + currentTick: Long, + behavior: (GridAgentData, Long) => Behavior[GridAgentMessage] + )(implicit + ctx: ActorContext[GridAgentMessage] + ): Behavior[GridAgentMessage] = { if (allReceived) { - log.debug("All power values of child assets + inferior grids received.") + ctx.log.debug( + "All power values of child assets + inferior grids received." + ) // if our superior grid received a FailedPowerFlow from the inferior grids it has to trigger a finish // of the simulation which will either result in a skip of this time step OR a termination of the simulation run @@ -979,60 +1093,63 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) ) if (powerFlowFailedSomewhere) { - log.warning("Power flow failed! This incident will be reported!") - self ! FinishGridSimulationTrigger(currentTick) + ctx.log.warn("Power flow failed! This incident will be reported!") + ctx.self ! FinishGridSimulationTrigger(currentTick) + handlePowerFlowFailure(gridAgentBaseData) - goto(SimulateGrid) using gridAgentBaseData + simulateGrid(gridAgentBaseData, currentTick) } else { - self ! CheckPowerDifferencesTrigger(currentTick) - goto(CheckPowerDifferences) using gridAgentBaseData + ctx.self ! CheckPowerDifferencesTrigger(currentTick) + checkPowerDifferences(gridAgentBaseData) } } else { - log.debug( + ctx.log.debug( "Still waiting for asset or grid power values or slack voltage information of inferior grids" ) - stay() using gridAgentBaseData + + buffer.unstashAll(behavior(gridAgentBaseData, currentTick)) } } + /** Method for handling failed power flows. + * @param gridAgentBaseData + * state data of the actor + */ private def handlePowerFlowFailure( gridAgentBaseData: GridAgentBaseData - ): Unit = { + )(implicit ctx: ActorContext[GridAgentMessage]): Unit = { environmentRefs.runtimeEventListener ! PowerFlowFailed if (gridAgentBaseData.powerFlowParams.stopOnFailure) { - log.error("Stopping because of failed power flow.") - self ! PoisonPill + ctx.log.error("Stopping because of failed power flow.") + Behaviors.stopped } } /** Normally only reached by the superior (dummy) agent! * - * Triggers a state transition to [[SimulateGrid]], informs the + * Triggers a [[Behavior]] transition to [[simulateGrid]], informs the * [[edu.ie3.simona.scheduler.Scheduler]] about the finish of this sweep and * requests a new trigger for itself for a new sweep * * @param gridAgentBaseData * the [[GridAgentBaseData]] that should be used in the next sweep in - * [[SimulateGrid]] + * [[simulateGrid]] * @param currentTick * current tick the agent is in * @return - * a state transition to [[SimulateGrid]] + * a behavior transition to [[simulateGrid]] */ private def goToSimulateGridForNextSweepWith( gridAgentBaseData: GridAgentBaseData, currentTick: Long - ): FSM.State[AgentState, GridAgentData] = { - - releaseTick() + ): Behavior[GridAgentMessage] = { environmentRefs.scheduler ! Completion( - self.toTyped, + activationAdapter, Some(currentTick) ) - goto(SimulateGrid) using gridAgentBaseData - + simulateGrid(gridAgentBaseData, currentTick) } /** Triggers an execution of the pekko `ask` pattern for all power values of @@ -1044,79 +1161,77 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * the current sweep value store containing the current node voltage for * the assets * @param nodeToAssetAgents - * a map contains a mapping between nodes and the [[ActorRef]] s located @ - * those nodes + * a map contains a mapping between nodes and the [[classicRef]] s located + * \@ those nodes * @param refSystem * the reference system of the [[edu.ie3.simona.model.grid.GridModel]] of * this [[GridAgent]] * @param askTimeout * a timeout for the request - * @return - * Some(Future[ReceivedPowerValues]) if this grids contains assets or None - * if no request has been send due to non-existence of assets */ private def askForAssetPowers( currentTick: Long, sweepValueStore: Option[SweepValueStore], - nodeToAssetAgents: Map[UUID, Set[ActorRef]], + nodeToAssetAgents: Map[UUID, Set[ActorRef[ParticipantMessage]]], refSystem: RefSystem, askTimeout: Duration - ): Option[Future[ReceivedPowerValues]] = { - + )(implicit + ctx: ActorContext[GridAgentMessage] + ): Option[Future[ValuesAdapter]] = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) + implicit val ec: ExecutionContext = ctx.executionContext - log.debug(s"asking assets for power values: {}", nodeToAssetAgents) - - if (nodeToAssetAgents.values.flatten.nonEmpty) - Some( - Future - .sequence( - nodeToAssetAgents.flatten { case (nodeUuid, assetActorRefs) => - assetActorRefs.map(assetAgent => { - - val (eInPu, fInPU) = - sweepValueStore match { - case Some(sweepValueStore) => - val (eInSi, fInSi) = refSystem.vInSi( - sweepValueStore.sweepData - .find(_.nodeUuid == nodeUuid) - .getOrElse( - throw new DBFSAlgorithmException( - s"Provided Sweep value store contains no data for node with id $nodeUuid" - ) - ) - .stateData - .voltage - ) - ( - refSystem.vInPu(eInSi), - refSystem.vInPu(fInSi) - ) - case None => - ( - Each(1d), - Each(0d) - ) - } + ctx.log.debug(s"asking assets for power values: {}", nodeToAssetAgents) - (assetAgent ? RequestAssetPowerMessage( - currentTick, - eInPu, - fInPU - )).map { - case providedPowerValuesMessage: AssetPowerChangedMessage => - (assetAgent, providedPowerValuesMessage) - case assetPowerUnchangedMessage: AssetPowerUnchangedMessage => - (assetAgent, assetPowerUnchangedMessage) + if (nodeToAssetAgents.values.flatten.nonEmpty) { + val future = Future + .sequence( + nodeToAssetAgents.flatten { case (nodeUuid, assetActorRefs) => + assetActorRefs.map(assetAgent => { + + val (eInPu, fInPU) = + sweepValueStore match { + case Some(sweepValueStore) => + val (eInSi, fInSi) = refSystem.vInSi( + sweepValueStore.sweepData + .find(_.nodeUuid == nodeUuid) + .getOrElse( + throw new DBFSAlgorithmException( + s"Provided Sweep value store contains no data for node with id $nodeUuid" + ) + ) + .stateData + .voltage + ) + ( + refSystem.vInPu(eInSi), + refSystem.vInPu(fInSi) + ) + case None => + ( + Each(1d), + Each(0d) + ) } - }) - }.toVector - ) - .map(ReceivedAssetPowerValues) - .pipeTo(self) - ) - else - None + + (assetAgent.toClassic ? RequestAssetPowerMessage( + currentTick, + eInPu, + fInPU + )).map { + case providedPowerValuesMessage: AssetPowerChangedMessage => + (assetAgent, providedPowerValuesMessage) + case assetPowerUnchangedMessage: AssetPowerUnchangedMessage => + (assetAgent, assetPowerUnchangedMessage) + } + }) + }.toVector + ) + .map(res => ValuesAdapter(ReceivedAssetPowerValues(res))) + + pipeToSelf(future, ctx) + Some(future) + } else None } /** Triggers an execution of the pekko `ask` pattern for all power values @ @@ -1129,23 +1244,26 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * [[ActorRef]] s of [[GridAgent]] s @ these nodes * @param askTimeout * a timeout for the request - * @return - * Some(Future[ReceivedPowerValues]) if this grids has connected inferior - * grids or None if this no inferior grids */ private def askInferiorGridsForPowers( currentSweepNo: Int, - subGridGateToActorRef: Map[SubGridGate, ActorRef], + subGridGateToActorRef: Map[SubGridGate, ActorRef[GridAgentMessage]], inferiorGridGates: Seq[SubGridGate], askTimeout: Duration - ): Option[Future[ReceivedPowerValues]] = { + )(implicit + ctx: ActorContext[GridAgentMessage] + ): Option[Future[ValuesAdapter]] = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) - log.debug( + implicit val ec: ExecutionContext = ctx.executionContext + implicit val scheduler: Scheduler = ctx.system.scheduler + + ctx.log.debug( s"asking inferior grids for power values: {}", inferiorGridGates ) + Option.when(inferiorGridGates.nonEmpty) { - Future + val future = Future .sequence( inferiorGridGates .map { inferiorGridGate => @@ -1161,20 +1279,30 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { inferiorGridGates } .map { case (inferiorGridAgentRef, inferiorGridGateNodes) => - (inferiorGridAgentRef ? RequestGridPowerMessage( - currentSweepNo, - inferiorGridGateNodes.distinct - )).map { - case provideGridPowerMessage: ProvideGridPowerMessage => - (inferiorGridAgentRef, provideGridPowerMessage) - case FailedPowerFlow => - (inferiorGridAgentRef, FailedPowerFlow) - } + inferiorGridAgentRef + .ask[GridAgentMessage](ref => + PMAdapter( + RequestGridPowerMessage( + currentSweepNo, + inferiorGridGateNodes.distinct, + ref + ) + ) + ) + .map { + case PMAdapter( + provideGridPowerMessage: ProvideGridPowerMessage + ) => + (inferiorGridAgentRef, provideGridPowerMessage) + case PMAdapter(FailedPowerFlow) => + (inferiorGridAgentRef, FailedPowerFlow) + } } .toVector ) - .map(ReceivedGridPowerValues) - .pipeTo(self) + .map(res => ValuesAdapter(ReceivedGridPowerValues(res))) + pipeToSelf(future, ctx) + future } } @@ -1188,39 +1316,52 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * [[ActorRef]] s of [[GridAgent]] s @ these nodes * @param askTimeout * a timeout for the request - * @return - * Some(Future[ReceivedSlackValues]) if this grids has connected superior - * grids or None if this no superior grids */ private def askSuperiorGridsForSlackVoltages( currentSweepNo: Int, - subGridGateToActorRef: Map[SubGridGate, ActorRef], + subGridGateToActorRef: Map[SubGridGate, ActorRef[GridAgentMessage]], superiorGridGates: Vector[SubGridGate], askTimeout: Duration - ): Option[Future[ReceivedSlackVoltageValues]] = { + )(implicit + ctx: ActorContext[GridAgentMessage] + ): Option[Future[ValuesAdapter]] = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) - log.debug( + implicit val ec: ExecutionContext = ctx.executionContext + implicit val scheduler: Scheduler = ctx.system.scheduler + + ctx.log.debug( s"asking superior grids for slack voltage values: {}", superiorGridGates ) Option.when(superiorGridGates.nonEmpty) { - Future + val future = Future .sequence( superiorGridGates .groupBy(subGridGateToActorRef(_)) .map { case (superiorGridAgent, gridGates) => - (superiorGridAgent ? RequestSlackVoltageMessage( - currentSweepNo, - gridGates.map(_.superiorNode.getUuid) - )).map { case providedSlackValues: ProvideSlackVoltageMessage => - (superiorGridAgent, providedSlackValues) - } + superiorGridAgent + .ask[GridAgentMessage](ref => + VMAdapter( + RequestSlackVoltageMessage( + currentSweepNo, + gridGates.map(_.superiorNode.getUuid), + ref + ) + ) + ) + .map { + case VMAdapter( + providedSlackValues: ProvideSlackVoltageMessage + ) => + (superiorGridAgent, providedSlackValues) + } } .toVector ) - .map(ReceivedSlackVoltageValues) - .pipeTo(self) + .map(res => ValuesAdapter(ReceivedSlackVoltageValues(res))) + pipeToSelf(future, ctx) + future } } @@ -1236,10 +1377,10 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * @param currentTimestamp * the current time stamp */ - def createAndSendPowerFlowResults( + private def createAndSendPowerFlowResults( gridAgentBaseData: GridAgentBaseData, currentTimestamp: ZonedDateTime - ): Unit = { + )(implicit log: Logger): Unit = { gridAgentBaseData.sweepValueStores.lastOption.foreach { case (_, valueStore) => notifyListener( @@ -1247,10 +1388,26 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentBaseData.gridEnv.gridModel, valueStore )( - currentTimestamp + currentTimestamp, + log ) ) } } + /** Simple method to pipe a future to itself. + * @param future + * value + * @param ctx + * context + */ + private def pipeToSelf( + future: Future[ValuesAdapter], + ctx: ActorContext[GridAgentMessage] + ): Unit = { + ctx.pipeToSelf[ValuesAdapter](future) { + case Success(value) => value + case Failure(exception) => ValuesAdapter(ReceivedFailure(exception)) + } + } } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index b8677f607a..b5339bcf15 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -6,29 +6,33 @@ package edu.ie3.simona.agent.grid -import edu.ie3.simona.agent.grid.GridAgent.Create +import edu.ie3.simona.actor.SimonaActorNaming +import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentBaseData, - GridAgentInitData, - GridAgentUninitializedData + GridAgentInitData } -import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} -import edu.ie3.simona.agent.state.GridAgentState.{Initializing, SimulateGrid} -import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} +import edu.ie3.simona.agent.grid.GridAgentMessage._ +import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.event.ResultEvent +import edu.ie3.simona.event.notifier.Notifier import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel -import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation } import edu.ie3.simona.ontology.messages.{Activation, StopMessage} -import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.TimeUtil -import org.apache.pekko.actor.{ActorRef, Props, Stash} -import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps +import org.apache.pekko.actor.typed.scaladsl.adapter.{ + ClassicActorRefOps, + TypedActorContextOps +} +import org.apache.pekko.actor.typed.scaladsl.{Behaviors, StashBuffer} +import org.apache.pekko.actor.typed.{ActorRef, Behavior} +import org.apache.pekko.actor.{ActorRef => classicRef} import java.time.ZonedDateTime import java.time.temporal.ChronoUnit @@ -36,142 +40,108 @@ import java.util.UUID import scala.language.postfixOps object GridAgent { - def props( + def apply( environmentRefs: EnvironmentRefs, simonaConfig: SimonaConfig, - listener: Iterable[ActorRef] - ): Props = - Props( - new GridAgent( + listener: Iterable[classicRef] + ): Behavior[GridAgentMessage] = Behaviors.withStash(100) { buffer => + Behaviors.setup[GridAgentMessage] { context => + context.messageAdapter(values => ValuesAdapter(values)) + context.messageAdapter(msg => PMAdapter(msg)) + context.messageAdapter(msg => VMAdapter(msg)) + val activationAdapter: ActorRef[Activation] = + context.messageAdapter[Activation](msg => ActivationAdapter(msg)) + + // val initialization + val resolution: Long = simonaConfig.simona.powerflow.resolution.get( + ChronoUnit.SECONDS + ) // this determines the agents regular time bin it wants to be triggered e.g one hour + + val simStartTime: ZonedDateTime = TimeUtil.withDefaults + .toZonedDateTime(simonaConfig.simona.time.startDateTime) + + val gridAgentController = + new GridAgentController( + context.toClassic, + environmentRefs, + simStartTime, + TimeUtil.withDefaults + .toZonedDateTime(simonaConfig.simona.time.endDateTime), + simonaConfig.simona.runtime.participant, + simonaConfig.simona.output.participant, + resolution, + listener.map(_.toTyped[ResultEvent]), + context.log + ) + + val agent = GridAgent( environmentRefs, simonaConfig, - listener + listener, + resolution, + simStartTime, + gridAgentController, + buffer, + activationAdapter, + SimonaActorNaming.actorName(context.self) ) - ) - /** GridAgent initialization data can only be constructed once all GridAgent - * actors are created. Thus, we need an extra initialization message. - * @param gridAgentInitData - * The initialization data - */ - final case class Create( - gridAgentInitData: GridAgentInitData, - unlockKey: ScheduleKey - ) - - /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to - * execute a power flow calculation - * - * @param tick - * current tick - */ - final case class DoPowerFlowTrigger(tick: Long, currentSweepNo: Int) - - /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to - * activate the superior grid agent to check for deviation after two sweeps - * and see if the power flow converges - * - * @param tick - * current tick - */ - final case class CheckPowerDifferencesTrigger(tick: Long) - - /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to - * trigger the [[edu.ie3.simona.agent.grid.GridAgent]] s to prepare - * themselves for a new sweep - * - * @param tick - * current tick - */ - final case class PrepareNextSweepTrigger(tick: Long) - - /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to - * indicate that a result has been found and each - * [[edu.ie3.simona.agent.grid.GridAgent]] should do it's cleanup work - * - * @param tick - * current tick - */ - final case class FinishGridSimulationTrigger(tick: Long) + agent.uninitialized + } + } } -class GridAgent( - val environmentRefs: EnvironmentRefs, +final case class GridAgent( + environmentRefs: EnvironmentRefs, simonaConfig: SimonaConfig, - val listener: Iterable[ActorRef] -) extends SimonaAgent[GridAgentData] - with DBFSAlgorithm - with Stash { - - // val initialization - protected val resolution: Long = simonaConfig.simona.powerflow.resolution.get( - ChronoUnit.SECONDS - ) // this determines the agents regular time bin it wants to be triggered e.g one hour - - protected val simStartTime: ZonedDateTime = TimeUtil.withDefaults - .toZonedDateTime(simonaConfig.simona.time.startDateTime) - - private val gridAgentController = - new GridAgentController( - context, - environmentRefs, - simStartTime, - TimeUtil.withDefaults - .toZonedDateTime(simonaConfig.simona.time.endDateTime), - simonaConfig.simona.runtime.participant, - simonaConfig.simona.output.participant, - resolution, - listener, - log - ) - - override def postStop(): Unit = { - log.debug("{} shutdown", self) - } + override val listener: Iterable[classicRef], + resolution: Long, + simStartTime: ZonedDateTime, + gridAgentController: GridAgentController, + buffer: StashBuffer[GridAgentMessage], + activationAdapter: ActorRef[Activation], + actorName: String +) extends DBFSAlgorithm + with Notifier { + + protected def uninitialized: Behavior[GridAgentMessage] = + Behaviors.receiveMessage[GridAgentMessage] { + case CreateGridAgent(gridAgentInitData, unlockKey) => + environmentRefs.scheduler ! ScheduleActivation( + activationAdapter, + INIT_SIM_TICK, + Some(unlockKey) + ) - override def preStart(): Unit = { - log.debug("{} started!", self) - } + initializing(gridAgentInitData) - // general agent states - // first fsm state of the agent - startWith(Uninitialized, GridAgentUninitializedData) - - when(Uninitialized) { - case Event( - Create(gridAgentInitData, unlockKey), - _ - ) => - environmentRefs.scheduler ! ScheduleActivation( - self.toTyped, - INIT_SIM_TICK, - Some(unlockKey) - ) + case GridAgentMessage.StopGridAgent => + Behaviors.stopped - goto(Initializing) using gridAgentInitData - } + case _ => + Behaviors.unhandled + } - when(Initializing) { - case Event( - Activation(INIT_SIM_TICK), - gridAgentInitData: GridAgentInitData - ) => + protected def initializing( + gridAgentInitData: GridAgentInitData + ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + case (ctx, ActivationAdapter(Activation(INIT_SIM_TICK))) => // fail fast sanity checks - failFast(gridAgentInitData) + failFast(gridAgentInitData, SimonaActorNaming.actorName(ctx.self)) - log.debug( + ctx.log.debug( s"Inferior Subnets: {}; Inferior Subnet Nodes: {}", gridAgentInitData.inferiorGridIds, gridAgentInitData.inferiorGridNodeUuids ) - log.debug( + ctx.log.debug( s"Superior Subnets: {}; Superior Subnet Nodes: {}", gridAgentInitData.superiorGridIds, gridAgentInitData.superiorGridNodeUuids ) - log.debug("Received InitializeTrigger.") + ctx.log.debug("Received InitializeTrigger.") // build the assets concurrently val subGridContainer = gridAgentInitData.subGridContainer @@ -179,21 +149,22 @@ class GridAgent( val thermalGridsByBusId = gridAgentInitData.thermalIslandGrids.map { thermalGrid => thermalGrid.bus().getUuid -> thermalGrid }.toMap - log.debug(s"Thermal island grids: ${thermalGridsByBusId.size}") + ctx.log.debug(s"Thermal island grids: ${thermalGridsByBusId.size}") // get the [[GridModel]] val gridModel = GridModel( subGridContainer, refSystem, - TimeUtil.withDefaults - .toZonedDateTime(simonaConfig.simona.time.startDateTime), + TimeUtil.withDefaults.toZonedDateTime( + simonaConfig.simona.time.startDateTime + ), TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.endDateTime ) ) /* Reassure, that there are also calculation models for the given uuids */ - val nodeToAssetAgentsMap: Map[UUID, Set[ActorRef]] = + val nodeToAssetAgentsMap: Map[UUID, Set[ActorRef[ParticipantMessage]]] = gridAgentController .buildSystemParticipants(subGridContainer, thermalGridsByBusId) .map { case (uuid: UUID, actorSet) => @@ -222,55 +193,62 @@ class GridAgent( simonaConfig.simona.powerflow.sweepTimeout, simonaConfig.simona.powerflow.stopOnFailure ), - log, - actorName + ctx.log, + ctx.self.toString ) - log.debug("Je suis initialized") + ctx.log.debug("Je suis initialized") environmentRefs.scheduler ! Completion( - self.toTyped, + activationAdapter, Some(resolution) ) - goto(Idle) using gridAgentBaseData - } + idle(gridAgentBaseData) - when(Idle) { + case (_, StopGridAgent) => + Behaviors.stopped - // needs to be set here to handle if the messages arrive too early - // before a transition to GridAgentBehaviour took place - case Event(RequestGridPowerMessage(_, _), _: GridAgentBaseData) => - stash() - stay() + case (_, _) => + Behaviors.unhandled + } - case Event( - Activation(tick), - gridAgentBaseData: GridAgentBaseData - ) => - unstashAll() + protected def idle( + gridAgentBaseData: GridAgentBaseData + ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + case (_, pm: PMAdapter) => + // needs to be set here to handle if the messages arrive too early + // before a transition to GridAgentBehaviour took place + buffer.stash(pm) + Behaviors.same + case (_, ActivationAdapter(activation: Activation)) => environmentRefs.scheduler ! Completion( - self.toTyped, - Some(tick) + activationAdapter, + Some(activation.tick) ) + buffer.unstashAll(simulateGrid(gridAgentBaseData, activation.tick)) - goto(SimulateGrid) using gridAgentBaseData - - case Event(StopMessage(_), data: GridAgentBaseData) => + case (ctx, ResultMessageAdapter(StopMessage(_))) => // shutdown children - data.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => - actors.foreach(context.stop) + gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => + actors.foreach(a => ctx.stop(a)) } // we are done - stop() - } + Behaviors.stopped - // everything else - whenUnhandled(myUnhandled()) + case (_, StopGridAgent) => + Behaviors.stopped - private def failFast(gridAgentInitData: GridAgentInitData): Unit = { + case _ => + Behaviors.unhandled + } + + private def failFast( + gridAgentInitData: GridAgentInitData, + actorName: String + ): Unit = { if ( gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty ) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala index 9ec4aca397..ebd5848693 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala @@ -6,14 +6,12 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps -import org.apache.pekko.actor.{ActorContext, ActorRef} -import org.apache.pekko.event.LoggingAdapter import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.models.input.container.{SubGridContainer, ThermalGrid} import edu.ie3.datamodel.models.input.system._ import edu.ie3.simona.actor.SimonaActorNaming._ import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.agent.participant.data.secondary.SecondaryDataService.{ ActorEvMovementsService, ActorWeatherService @@ -27,12 +25,20 @@ import edu.ie3.simona.agent.participant.statedata.ParticipantStateData.Participa import edu.ie3.simona.agent.participant.wec.WecAgent import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.config.SimonaConfig._ +import edu.ie3.simona.event.ResultEvent import edu.ie3.simona.event.notifier.NotifierConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.ontology.messages.SchedulerMessage.ScheduleActivation import edu.ie3.simona.util.ConfigUtil import edu.ie3.simona.util.ConfigUtil._ import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.adapter.{ + ClassicActorRefOps, + TypedActorRefOps +} +import org.apache.pekko.actor.{ActorContext, ActorRef => classicRef} +import org.slf4j.Logger import java.time.ZonedDateTime import java.util.UUID @@ -62,20 +68,20 @@ import scala.jdk.CollectionConverters._ * @since 2019-07-18 */ class GridAgentController( - gridAgentContext: ActorContext, + gridAgentContext: ActorContext, // TODO: Change to typed after the participants are typed environmentRefs: EnvironmentRefs, simulationStartDate: ZonedDateTime, simulationEndDate: ZonedDateTime, participantsConfig: SimonaConfig.Simona.Runtime.Participant, outputConfig: SimonaConfig.Simona.Output.Participant, resolution: Long, - listener: Iterable[ActorRef], - log: LoggingAdapter + listener: Iterable[ActorRef[ResultEvent]], + log: Logger ) extends LazyLogging { def buildSystemParticipants( subGridContainer: SubGridContainer, thermalIslandGridsByBusId: Map[UUID, ThermalGrid] - ): Map[UUID, Set[ActorRef]] = { + ): Map[UUID, Set[ActorRef[ParticipantMessage]]] = { val systemParticipants = filterSysParts(subGridContainer, environmentRefs) @@ -127,7 +133,7 @@ class GridAgentController( // only include evcs if ev data service is present case evcsInput: EvcsInput if environmentRefs.evDataService.isEmpty => - log.warning( + log.warn( s"Evcs ${evcsInput.getId} has been removed because no ev movements service is present." ) (notProcessedElements, availableSystemParticipants) @@ -137,7 +143,7 @@ class GridAgentController( } if (notProcessedElements.nonEmpty) - log.warning( + log.warn( s"The following elements have been removed, " + s"as the agents are not implemented yet: $notProcessedElements" ) @@ -170,7 +176,7 @@ class GridAgentController( participants: Vector[SystemParticipantInput], thermalIslandGridsByBusId: Map[UUID, ThermalGrid], environmentRefs: EnvironmentRefs - ): Map[UUID, Set[ActorRef]] = { + ): Map[UUID, Set[ActorRef[ParticipantMessage]]] = { /* Prepare the config util for the participant models, which (possibly) utilizes as map to speed up the initialization * phase */ val participantConfigUtil = @@ -190,11 +196,11 @@ class GridAgentController( thermalIslandGridsByBusId, environmentRefs ) - introduceAgentToEnvironment(actorRef) + introduceAgentToEnvironment(actorRef.toClassic) // return uuid to actorRef node.getUuid -> actorRef }) - .toSet[(UUID, ActorRef)] + .toSet[(UUID, ActorRef[ParticipantMessage])] .groupMap(entry => entry._1)(entry => entry._2) } @@ -205,7 +211,7 @@ class GridAgentController( participantInputModel: SystemParticipantInput, thermalIslandGridsByBusId: Map[UUID, ThermalGrid], environmentRefs: EnvironmentRefs - ): ActorRef = participantInputModel match { + ): ActorRef[ParticipantMessage] = participantInputModel match { case input: FixedFeedInInput => buildFixedFeedIn( input, @@ -325,36 +331,38 @@ class GridAgentController( * @param outputConfig * Configuration of the output behavior * @return - * The [[FixedFeedInAgent]] 's [[ActorRef]] + * The [[FixedFeedInAgent]] 's [[classicRef]] */ private def buildFixedFeedIn( fixedFeedInInput: FixedFeedInInput, modelConfiguration: FixedFeedInRuntimeConfig, - primaryServiceProxy: ActorRef, + primaryServiceProxy: classicRef, simulationStartDate: ZonedDateTime, simulationEndDate: ZonedDateTime, resolution: Long, requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig - ): ActorRef = - gridAgentContext.simonaActorOf( - FixedFeedInAgent.props( - environmentRefs.scheduler, - ParticipantInitializeStateData( - fixedFeedInInput, - modelConfiguration, - primaryServiceProxy, - None, - simulationStartDate, - simulationEndDate, - resolution, - requestVoltageDeviationThreshold, - outputConfig + ): ActorRef[ParticipantMessage] = + gridAgentContext + .simonaActorOf( + FixedFeedInAgent.props( + environmentRefs.scheduler, + ParticipantInitializeStateData( + fixedFeedInInput, + modelConfiguration, + primaryServiceProxy, + None, + simulationStartDate, + simulationEndDate, + resolution, + requestVoltageDeviationThreshold, + outputConfig + ), + listener.map(_.toClassic) ), - listener - ), - fixedFeedInInput.getId - ) + fixedFeedInInput.getId + ) + .toTyped /** Creates a load agent and determines the needed additional information for * later initialization of the agent. @@ -376,36 +384,38 @@ class GridAgentController( * @param outputConfig * Configuration of the output behavior * @return - * The [[LoadAgent]] 's [[ActorRef]] + * The [[LoadAgent]] 's [[classicRef]] */ private def buildLoad( loadInput: LoadInput, modelConfiguration: LoadRuntimeConfig, - primaryServiceProxy: ActorRef, + primaryServiceProxy: classicRef, simulationStartDate: ZonedDateTime, simulationEndDate: ZonedDateTime, resolution: Long, requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig - ): ActorRef = - gridAgentContext.simonaActorOf( - LoadAgent.props( - environmentRefs.scheduler, - ParticipantInitializeStateData( - loadInput, - modelConfiguration, - primaryServiceProxy, - None, - simulationStartDate, - simulationEndDate, - resolution, - requestVoltageDeviationThreshold, - outputConfig + ): ActorRef[ParticipantMessage] = + gridAgentContext + .simonaActorOf( + LoadAgent.props( + environmentRefs.scheduler, + ParticipantInitializeStateData( + loadInput, + modelConfiguration, + primaryServiceProxy, + None, + simulationStartDate, + simulationEndDate, + resolution, + requestVoltageDeviationThreshold, + outputConfig + ), + listener.map(_.toClassic) ), - listener - ), - loadInput.getId - ) + loadInput.getId + ) + .toTyped /** Creates a pv agent and determines the needed additional information for * later initialization of the agent. @@ -429,37 +439,39 @@ class GridAgentController( * @param outputConfig * Configuration of the output behavior * @return - * The [[PvAgent]] 's [[ActorRef]] + * The [[PvAgent]] 's [[classicRef]] */ private def buildPv( pvInput: PvInput, modelConfiguration: PvRuntimeConfig, - primaryServiceProxy: ActorRef, - weatherService: ActorRef, + primaryServiceProxy: classicRef, + weatherService: classicRef, simulationStartDate: ZonedDateTime, simulationEndDate: ZonedDateTime, resolution: Long, requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig - ): ActorRef = - gridAgentContext.simonaActorOf( - PvAgent.props( - environmentRefs.scheduler, - ParticipantInitializeStateData( - pvInput, - modelConfiguration, - primaryServiceProxy, - Some(Vector(ActorWeatherService(weatherService))), - simulationStartDate, - simulationEndDate, - resolution, - requestVoltageDeviationThreshold, - outputConfig + ): ActorRef[ParticipantMessage] = + gridAgentContext + .simonaActorOf( + PvAgent.props( + environmentRefs.scheduler, + ParticipantInitializeStateData( + pvInput, + modelConfiguration, + primaryServiceProxy, + Some(Vector(ActorWeatherService(weatherService))), + simulationStartDate, + simulationEndDate, + resolution, + requestVoltageDeviationThreshold, + outputConfig + ), + listener.map(_.toClassic) ), - listener - ), - pvInput.getId - ) + pvInput.getId + ) + .toTyped /** Creates an Evcs agent and determines the needed additional information for * later initialization of the agent. @@ -483,19 +495,19 @@ class GridAgentController( * @param outputConfig * Configuration of the output behavior * @return - * The [[EvcsAgent]] 's [[ActorRef]] + * The [[EvcsAgent]] 's [[classicRef]] */ private def buildEvcs( evcsInput: EvcsInput, modelConfiguration: EvcsRuntimeConfig, - primaryServiceProxy: ActorRef, - evMovementsService: ActorRef, + primaryServiceProxy: classicRef, + evMovementsService: classicRef, simulationStartDate: ZonedDateTime, simulationEndDate: ZonedDateTime, resolution: Long, requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig - ): ActorRef = { + ): ActorRef[ParticipantMessage] = { val sources = Some( Vector( ActorEvMovementsService( @@ -503,23 +515,25 @@ class GridAgentController( ) ) ) - gridAgentContext.simonaActorOf( - EvcsAgent.props( - environmentRefs.scheduler, - ParticipantInitializeStateData( - evcsInput, - modelConfiguration, - primaryServiceProxy, - sources, - simulationStartDate, - simulationEndDate, - resolution, - requestVoltageDeviationThreshold, - outputConfig - ), - listener + gridAgentContext + .simonaActorOf( + EvcsAgent.props( + environmentRefs.scheduler, + ParticipantInitializeStateData( + evcsInput, + modelConfiguration, + primaryServiceProxy, + sources, + simulationStartDate, + simulationEndDate, + resolution, + requestVoltageDeviationThreshold, + outputConfig + ), + listener.map(_.toClassic) + ) ) - ) + .toTyped } /** Builds an [[HpAgent]] from given input @@ -544,30 +558,32 @@ class GridAgentController( hpInput: HpInput, thermalGrid: ThermalGrid, modelConfiguration: HpRuntimeConfig, - primaryServiceProxy: ActorRef, - weatherService: ActorRef, + primaryServiceProxy: classicRef, + weatherService: classicRef, requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig - ): ActorRef = - gridAgentContext.simonaActorOf( - HpAgent.props( - environmentRefs.scheduler, - ParticipantInitializeStateData( - hpInput, - thermalGrid, - modelConfiguration, - primaryServiceProxy, - Some(Vector(ActorWeatherService(weatherService))), - simulationStartDate, - simulationEndDate, - resolution, - requestVoltageDeviationThreshold, - outputConfig + ): ActorRef[ParticipantMessage] = + gridAgentContext + .simonaActorOf( + HpAgent.props( + environmentRefs.scheduler, + ParticipantInitializeStateData( + hpInput, + thermalGrid, + modelConfiguration, + primaryServiceProxy, + Some(Vector(ActorWeatherService(weatherService))), + simulationStartDate, + simulationEndDate, + resolution, + requestVoltageDeviationThreshold, + outputConfig + ), + listener.map(_.toClassic) ), - listener - ), - hpInput.getId - ) + hpInput.getId + ) + .toTyped /** Creates a pv agent and determines the needed additional information for * later initialization of the agent. @@ -591,37 +607,39 @@ class GridAgentController( * @param outputConfig * Configuration of the output behavior * @return - * The [[WecAgent]] 's [[ActorRef]] + * The [[WecAgent]] 's [[classicRef]] */ private def buildWec( wecInput: WecInput, modelConfiguration: WecRuntimeConfig, - primaryServiceProxy: ActorRef, - weatherService: ActorRef, + primaryServiceProxy: classicRef, + weatherService: classicRef, simulationStartDate: ZonedDateTime, simulationEndDate: ZonedDateTime, resolution: Long, requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig - ): ActorRef = - gridAgentContext.simonaActorOf( - WecAgent.props( - environmentRefs.scheduler, - ParticipantInitializeStateData( - wecInput, - modelConfiguration, - primaryServiceProxy, - Some(Vector(ActorWeatherService(weatherService))), - simulationStartDate, - simulationEndDate, - resolution, - requestVoltageDeviationThreshold, - outputConfig + ): ActorRef[ParticipantMessage] = + gridAgentContext + .simonaActorOf( + WecAgent.props( + environmentRefs.scheduler, + ParticipantInitializeStateData( + wecInput, + modelConfiguration, + primaryServiceProxy, + Some(Vector(ActorWeatherService(weatherService))), + simulationStartDate, + simulationEndDate, + resolution, + requestVoltageDeviationThreshold, + outputConfig + ), + listener.map(_.toClassic) ), - listener - ), - wecInput.getId - ) + wecInput.getId + ) + .toTyped /** Introduces the given agent to scheduler * @@ -629,11 +647,11 @@ class GridAgentController( * Reference to the actor to add to the environment */ private def introduceAgentToEnvironment( - actorRef: ActorRef + actorRef: classicRef ): Unit = { gridAgentContext.watch(actorRef) environmentRefs.scheduler ! ScheduleActivation( - actorRef.toTyped, + actorRef.toTyped, // TODO: Add participant adapter INIT_SIM_TICK ) } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala index 038d72cbc5..4a498be6b3 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala @@ -6,8 +6,6 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.ActorRef -import org.apache.pekko.event.LoggingAdapter import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.datamodel.models.input.container.{SubGridContainer, ThermalGrid} import edu.ie3.powerflow.model.PowerFlowResult @@ -17,6 +15,7 @@ import edu.ie3.simona.agent.grid.ReceivedValues.{ ReceivedSlackVoltageValues } import edu.ie3.simona.agent.grid.ReceivedValuesStore.NodeToReceivedPower +import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.model.grid.{GridModel, RefSystem} import edu.ie3.simona.ontology.messages.PowerMessage.{ FailedPowerFlow, @@ -24,6 +23,8 @@ import edu.ie3.simona.ontology.messages.PowerMessage.{ ProvideGridPowerMessage, ProvidePowerMessage } +import org.apache.pekko.actor.typed.ActorRef +import org.slf4j.Logger import java.util.UUID @@ -33,14 +34,10 @@ sealed trait GridAgentData */ object GridAgentData { - /** Initial state data of the [[GridAgent]] - */ - final case object GridAgentUninitializedData extends GridAgentData - /** Data that is send to the [[GridAgent]] directly after startup. It contains * the main information for initialization. This data should include all * [[GridAgent]] individual data, for data that is the same for all - * [[GridAgent]] s please use [[GridAgent.props()]] + * [[GridAgent]] s please use [[GridAgent.apply()]] * * @param subGridContainer * raw grid information in the input data format @@ -54,7 +51,7 @@ object GridAgentData { final case class GridAgentInitData( subGridContainer: SubGridContainer, thermalIslandGrids: Seq[ThermalGrid], - subGridGateToActorRef: Map[SubGridGate, ActorRef], + subGridGateToActorRef: Map[SubGridGate, ActorRef[GridAgentMessage]], refSystem: RefSystem ) extends GridAgentData with GridAgentDataHelper { @@ -101,12 +98,12 @@ object GridAgentData { def apply( gridModel: GridModel, - subgridGateToActorRef: Map[SubGridGate, ActorRef], - nodeToAssetAgents: Map[UUID, Set[ActorRef]], + subgridGateToActorRef: Map[SubGridGate, ActorRef[GridAgentMessage]], + nodeToAssetAgents: Map[UUID, Set[ActorRef[ParticipantMessage]]], superiorGridNodeUuids: Vector[UUID], inferiorGridGates: Vector[SubGridGate], powerFlowParams: PowerFlowParams, - log: LoggingAdapter, + log: Logger, actorName: String ): GridAgentBaseData = { @@ -194,7 +191,7 @@ object GridAgentData { currentSweepNo: Int, receivedValueStore: ReceivedValuesStore, sweepValueStores: Map[Int, SweepValueStore], - log: LoggingAdapter, + log: Logger, actorName: String ) extends GridAgentData with GridAgentDataHelper { @@ -301,7 +298,7 @@ object GridAgentData { private def updateNodalReceivedPower( powerResponse: PowerResponseMessage, nodeToReceived: NodeToReceivedPower, - senderRef: ActorRef, + senderRef: ActorRef[_], replace: Boolean ): NodeToReceivedPower = { // extract the nodeUuid that corresponds to the sender's actorRef and check if we expect a message from the sender @@ -359,7 +356,7 @@ object GridAgentData { */ private def getNodeUuidForSender( nodeToReceivedPower: NodeToReceivedPower, - senderRef: ActorRef, + senderRef: ActorRef[_], replace: Boolean ): Option[UUID] = nodeToReceivedPower diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala new file mode 100644 index 0000000000..c466cab896 --- /dev/null +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala @@ -0,0 +1,110 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.agent.grid + +import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData +import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage +import edu.ie3.simona.ontology.messages.{ + Activation, + PowerMessage, + VoltageMessage +} +import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey +import org.apache.pekko.actor.typed.ActorRef + +/** Trait for [[GridAgent]] messages. + */ +sealed trait GridAgentMessage + +/** Defines all messages that can be received by a [[GridAgent]] without the + * need for an adapter. + */ +object GridAgentMessage { + + /** GridAgent initialization data can only be constructed once all GridAgent + * actors are created. Thus, we need an extra initialization message. + * + * @param gridAgentInitData + * The initialization data + */ + final case class CreateGridAgent( + gridAgentInitData: GridAgentInitData, + unlockKey: ScheduleKey + ) extends GridAgentMessage + + /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to + * execute a power flow calculation + * + * @param tick + * current tick + */ + final case class DoPowerFlowTrigger(tick: Long, currentSweepNo: Int) + extends GridAgentMessage + + /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to + * activate the superior grid agent to check for deviation after two sweeps + * and see if the power flow converges + * + * @param tick + * current tick + */ + final case class CheckPowerDifferencesTrigger(tick: Long) + extends GridAgentMessage + + /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to + * trigger the [[edu.ie3.simona.agent.grid.GridAgent]] s to prepare + * themselves for a new sweep + * + * @param tick + * current tick + */ + final case class PrepareNextSweepTrigger(tick: Long) extends GridAgentMessage + + /** Trigger used inside of [[edu.ie3.simona.agent.grid.DBFSAlgorithm]] to + * indicate that a result has been found and each + * [[edu.ie3.simona.agent.grid.GridAgent]] should do it's cleanup work + * + * @param tick + * current tick + */ + final case class FinishGridSimulationTrigger(tick: Long) + extends GridAgentMessage + + /** Message that should be send by the + */ + final object StopGridAgent extends GridAgentMessage + + /** Wrapper for string messages. NOTICE: Only for internal use. + * @param str + * message + * @param sender + * of the message + */ + private[grid] final case class StringAdapter( + str: String, + sender: ActorRef[GridAgentMessage] + ) extends GridAgentMessage + + /** Wrapper for activation values + * + * @param activation + * the tick + */ + final case class ActivationAdapter(activation: Activation) + extends GridAgentMessage + + final case class PMAdapter(msg: PowerMessage) extends GridAgentMessage + + final case class VMAdapter(msg: VoltageMessage) extends GridAgentMessage + + final case class ValuesAdapter(values: ReceivedValues) + extends GridAgentMessage + + final case class ResultMessageAdapter(msg: ResultMessage) + extends GridAgentMessage + +} diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridEnvironment.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridEnvironment.scala index 39dadc489f..89702688e3 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridEnvironment.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridEnvironment.scala @@ -6,11 +6,12 @@ package edu.ie3.simona.agent.grid -import java.util.UUID - -import org.apache.pekko.actor.ActorRef import edu.ie3.datamodel.graph.SubGridGate +import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.model.grid.GridModel +import org.apache.pekko.actor.typed.ActorRef + +import java.util.UUID /** Wrapper class containing all information on the grid environment a * [[GridAgent]] has access to @@ -25,6 +26,6 @@ import edu.ie3.simona.model.grid.GridModel */ final case class GridEnvironment( gridModel: GridModel, - subgridGateToActorRef: Map[SubGridGate, ActorRef], - nodeToAssetAgents: Map[UUID, Set[ActorRef]] + subgridGateToActorRef: Map[SubGridGate, ActorRef[GridAgentMessage]], + nodeToAssetAgents: Map[UUID, Set[ActorRef[ParticipantMessage]]] ) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala index ecd073b1cf..86172838a0 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridResultsSupport.scala @@ -6,7 +6,6 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.event.LoggingAdapter import breeze.math.Complex import edu.ie3.datamodel.models.input.connector.ConnectorPort import edu.ie3.datamodel.models.result.NodeResult @@ -29,6 +28,7 @@ import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ import edu.ie3.simona.model.grid._ import edu.ie3.util.quantities.PowerSystemUnits import edu.ie3.util.scala.quantities.QuantityUtil +import org.slf4j.Logger import squants.space.Degrees import squants.{Amperes, Angle, ElectricCurrent} import tech.units.indriya.quantity.Quantities @@ -43,8 +43,6 @@ import scala.math._ */ private[grid] trait GridResultsSupport { - protected val log: LoggingAdapter - /** Creates a tuple as [[PowerFlowResultEvent]] s entities based on the * provided grid data * @@ -61,7 +59,7 @@ private[grid] trait GridResultsSupport { def createResultModels( grid: GridModel, sweepValueStore: SweepValueStore - )(implicit timestamp: ZonedDateTime): PowerFlowResultEvent = { + )(implicit timestamp: ZonedDateTime, log: Logger): PowerFlowResultEvent = { // no sanity check for duplicated uuid result data as we expect valid data at this point implicit val sweepValueStoreData: Map[UUID, SweepValueStoreData] = sweepValueStore.sweepData @@ -111,7 +109,8 @@ private[grid] trait GridResultsSupport { private def buildLineResults(lines: Set[LineModel])(implicit sweepValueStoreData: Map[UUID, SweepValueStoreData], iNominal: squants.ElectricCurrent, - timestamp: ZonedDateTime + timestamp: ZonedDateTime, + log: Logger ): Set[LineResult] = { lines.flatMap(lineModel => { sweepValueStoreData @@ -128,7 +127,7 @@ private[grid] trait GridResultsSupport { ) ) case None => - log.warning( + log.warn( "Cannot find power flow result data for line {} with nodeA {} and nodeB {}", lineModel.uuid, lineModel.nodeAUuid, @@ -158,7 +157,8 @@ private[grid] trait GridResultsSupport { implicit sweepValueStoreData: Map[UUID, SweepValueStoreData], iNominal: ElectricCurrent, - timestamp: ZonedDateTime + timestamp: ZonedDateTime, + log: Logger ): Set[Transformer2WResult] = { transformers.flatMap(trafo2w => { sweepValueStoreData @@ -175,7 +175,7 @@ private[grid] trait GridResultsSupport { ) ) case None => - log.warning( + log.warn( "Cannot find power flow result data for transformer2w {} with hvNode {} and lvNode {}", trafo2w.uuid, trafo2w.hvNodeUuid, @@ -205,7 +205,8 @@ private[grid] trait GridResultsSupport { implicit sweepValueStoreData: Map[UUID, SweepValueStoreData], iNominal: ElectricCurrent, - timestamp: ZonedDateTime + timestamp: ZonedDateTime, + log: Logger ): Set[PartialTransformer3wResult] = transformers3w.flatMap { trafo3w => { (trafo3w.powerFlowCase match { @@ -233,7 +234,7 @@ private[grid] trait GridResultsSupport { ) ) case None => - log.warning( + log.warn( s"Cannot find power flow result data for transformer3w {} with nodeHv {}, nodeMv {}, nodeLv {} and internalNode ${trafo3w.nodeInternalUuid}", trafo3w.uuid, trafo3w.hvNodeUuid, diff --git a/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala b/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala index afc26f47c1..a768f1574b 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala @@ -6,7 +6,6 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.event.LoggingAdapter import breeze.math.Complex import edu.ie3.powerflow.NewtonRaphsonPF import edu.ie3.powerflow.model.NodeData.{PresetData, StateData} @@ -20,6 +19,7 @@ import edu.ie3.simona.model.grid._ import edu.ie3.simona.ontology.messages.PowerMessage.ProvidePowerMessage import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage import edu.ie3.util.scala.quantities.Kilovars +import org.slf4j.Logger import squants.electro.ElectricPotential import squants.energy.Kilowatts @@ -32,8 +32,6 @@ import scala.util.{Failure, Success, Try} */ trait PowerFlowSupport { - protected val log: LoggingAdapter - /** Composes the current operation point needed by * [[edu.ie3.powerflow.NewtonRaphsonPF.calculate()]] * @@ -561,7 +559,7 @@ trait PowerFlowSupport { maxIterations: Int, operatingPoint: Array[PresetData], slackVoltages: WithForcedStartVoltages - )(epsilons: Vector[Double]): PowerFlowResult = { + )(epsilons: Vector[Double])(implicit log: Logger): PowerFlowResult = { epsilons.headOption match { case Some(epsilon) => val admittanceMatrix = diff --git a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala index 53f04d5af8..2342144296 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala @@ -6,9 +6,11 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.ActorRef +import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.ontology.messages.PowerMessage.PowerResponseMessage import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage +import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey +import org.apache.pekko.actor.typed.ActorRef /** Serves as a wrapper class that allows for matches against received values in * [[DBFSAlgorithm]] @@ -17,11 +19,18 @@ sealed trait ReceivedValues object ReceivedValues { - type ActorPowerRequestResponse = (ActorRef, PowerResponseMessage) - type ActorSlackVoltageRequestResponse = (ActorRef, ProvideSlackVoltageMessage) + type ParticipantPowerRequestResponse = + ( + ActorRef[_], + PowerResponseMessage + ) // necessary, because participants are still classic actors + type GridPowerRequestResponse = + (ActorRef[GridAgentMessage], PowerResponseMessage) + type ActorSlackVoltageRequestResponse = + (ActorRef[GridAgentMessage], ProvideSlackVoltageMessage) sealed trait ReceivedPowerValues extends ReceivedValues { - def values: Vector[ActorPowerRequestResponse] + def values: Vector[(ActorRef[_], PowerResponseMessage)] } /** Wrapper for received asset power values (p, q) @@ -30,7 +39,7 @@ object ReceivedValues { * the asset power values and their senders */ final case class ReceivedAssetPowerValues( - values: Vector[ActorPowerRequestResponse] + values: Vector[ParticipantPowerRequestResponse] ) extends ReceivedPowerValues /** Wrapper for received grid power values (p, q) @@ -39,7 +48,7 @@ object ReceivedValues { * the grid power values and their senders */ final case class ReceivedGridPowerValues( - values: Vector[ActorPowerRequestResponse] + values: Vector[GridPowerRequestResponse] ) extends ReceivedPowerValues /** Wrapper for received slack voltage values (v) @@ -51,4 +60,11 @@ object ReceivedValues { values: Vector[ActorSlackVoltageRequestResponse] ) extends ReceivedValues + /** Wrapper for received exception. + * @param exception + * that was received + */ + final case class ReceivedFailure( + exception: Throwable + ) extends ReceivedValues } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala index 4c083629f3..3d2125ee5c 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala @@ -6,17 +6,20 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.ActorRef import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.simona.agent.grid.ReceivedValuesStore.{ NodeToReceivedPower, NodeToReceivedSlackVoltage } +import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.ontology.messages.PowerMessage.{ PowerResponseMessage, ProvidePowerMessage } import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps +import org.apache.pekko.actor.{ActorRef => classicRef} import java.util.UUID @@ -47,7 +50,7 @@ final case class ReceivedValuesStore private ( object ReceivedValuesStore { type NodeToReceivedPower = - Map[UUID, Map[ActorRef, Option[PowerResponseMessage]]] + Map[UUID, Map[ActorRef[_], Option[PowerResponseMessage]]] type NodeToReceivedSlackVoltage = Map[UUID, Option[ExchangeVoltage]] @@ -68,8 +71,10 @@ object ReceivedValuesStore { * `empty` [[ReceivedValuesStore]] with pre-initialized options as `None` */ def empty( - nodeToAssetAgents: Map[UUID, Set[ActorRef]], - inferiorSubGridGateToActorRef: Map[SubGridGate, ActorRef], + nodeToAssetAgents: Map[UUID, Set[ActorRef[ParticipantMessage]]], + inferiorSubGridGateToActorRef: Map[SubGridGate, ActorRef[ + GridAgentMessage + ]], superiorGridNodeUuids: Vector[UUID] ): ReceivedValuesStore = { val (nodeToReceivedPower, nodeToReceivedSlackVoltage) = @@ -94,12 +99,14 @@ object ReceivedValuesStore { * `empty` [[NodeToReceivedPower]] with pre-initialized options as `None` */ private def buildEmptyNodeToReceivedPowerMap( - nodeToAssetAgents: Map[UUID, Set[ActorRef]], - inferiorSubGridGateToActorRef: Map[SubGridGate, ActorRef] + nodeToAssetAgents: Map[UUID, Set[ActorRef[ParticipantMessage]]], + inferiorSubGridGateToActorRef: Map[SubGridGate, ActorRef[ + GridAgentMessage + ]] ): NodeToReceivedPower = { /* Collect everything, that I expect from my asset agents */ val assetsToReceivedPower: NodeToReceivedPower = nodeToAssetAgents.collect { - case (uuid: UUID, actorRefs: Set[ActorRef]) => + case (uuid: UUID, actorRefs: Set[ActorRef[ParticipantMessage]]) => (uuid, actorRefs.map(actorRef => actorRef -> None).toMap) } @@ -118,7 +125,7 @@ object ReceivedValuesStore { val actorRefToMessage = subordinateToReceivedPower .getOrElse( couplingNodeUuid, - Map.empty[ActorRef, Option[ProvidePowerMessage]] + Map.empty[ActorRef[_], Option[ProvidePowerMessage]] ) + (inferiorSubGridRef -> None) /* Update the existing map */ @@ -156,8 +163,10 @@ object ReceivedValuesStore { * `empty` [[NodeToReceivedSlackVoltage]] and [[NodeToReceivedPower]] */ private def buildEmptyReceiveMaps( - nodeToAssetAgents: Map[UUID, Set[ActorRef]], - inferiorSubGridGateToActorRef: Map[SubGridGate, ActorRef], + nodeToAssetAgents: Map[UUID, Set[ActorRef[ParticipantMessage]]], + inferiorSubGridGateToActorRef: Map[SubGridGate, ActorRef[ + GridAgentMessage + ]], superiorGridNodeUuids: Vector[UUID] ): (NodeToReceivedPower, NodeToReceivedSlackVoltage) = { ( diff --git a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala index 063ff508f5..6f8aa9a459 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala @@ -6,11 +6,9 @@ package edu.ie3.simona.agent.participant -import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps -import org.apache.pekko.actor.{ActorRef, FSM} import edu.ie3.datamodel.models.input.system.SystemParticipantInput import edu.ie3.simona.agent.SimonaAgent -import edu.ie3.simona.agent.grid.GridAgent.FinishGridSimulationTrigger +import edu.ie3.simona.agent.grid.GridAgentMessage.FinishGridSimulationTrigger import edu.ie3.simona.agent.participant.ParticipantAgent.{ StartCalculationTrigger, getAndCheckNodalVoltage @@ -50,6 +48,8 @@ import edu.ie3.simona.ontology.messages.services.ServiceMessage.{ } import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.scala.quantities.ReactivePower +import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps +import org.apache.pekko.actor.{ActorRef, FSM} import squants.{Dimensionless, Power} import java.time.ZonedDateTime @@ -721,6 +721,8 @@ abstract class ParticipantAgent[ object ParticipantAgent { + trait ParticipantMessage + final case class StartCalculationTrigger(tick: Long) /** Verifies that a nodal voltage value has been provided in the model diff --git a/src/main/scala/edu/ie3/simona/agent/state/GridAgentState.scala b/src/main/scala/edu/ie3/simona/agent/state/GridAgentState.scala deleted file mode 100644 index f602b4dabe..0000000000 --- a/src/main/scala/edu/ie3/simona/agent/state/GridAgentState.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* - * © 2020. TU Dortmund University, - * Institute of Energy Systems, Energy Efficiency and Energy Economics, - * Research group Distribution grid planning and operation - */ - -package edu.ie3.simona.agent.state - -sealed trait GridAgentState extends AgentState - -object GridAgentState { - - case object Initializing extends GridAgentState - - case object SimulateGrid extends GridAgentState - - case object CheckPowerDifferences extends GridAgentState - - case object HandlePowerFlowCalculations extends GridAgentState - -} diff --git a/src/main/scala/edu/ie3/simona/event/notifier/Notifier.scala b/src/main/scala/edu/ie3/simona/event/notifier/Notifier.scala index 916a97f9cb..b271a913e9 100644 --- a/src/main/scala/edu/ie3/simona/event/notifier/Notifier.scala +++ b/src/main/scala/edu/ie3/simona/event/notifier/Notifier.scala @@ -6,10 +6,10 @@ package edu.ie3.simona.event.notifier -import org.apache.pekko.actor.{Actor, ActorRef} import edu.ie3.simona.event.Event +import org.apache.pekko.actor.ActorRef -trait Notifier extends Actor { +trait Notifier { def listener: Iterable[ActorRef] diff --git a/src/main/scala/edu/ie3/simona/ontology/messages/PowerMessage.scala b/src/main/scala/edu/ie3/simona/ontology/messages/PowerMessage.scala index d82961cd5a..5caf8967ab 100644 --- a/src/main/scala/edu/ie3/simona/ontology/messages/PowerMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/messages/PowerMessage.scala @@ -6,8 +6,10 @@ package edu.ie3.simona.ontology.messages +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.util.scala.quantities.ReactivePower +import org.apache.pekko.actor.typed.ActorRef import squants.{Dimensionless, Power} import java.util.UUID @@ -79,7 +81,8 @@ object PowerMessage { */ final case class RequestGridPowerMessage( currentSweepNo: Int, - nodeUuids: Seq[UUID] + nodeUuids: Seq[UUID], + sender: ActorRef[GridAgentMessage] ) extends PowerRequestMessage /** Provide complex power at the nodes that the sender's sub grid shares with diff --git a/src/main/scala/edu/ie3/simona/ontology/messages/VoltageMessage.scala b/src/main/scala/edu/ie3/simona/ontology/messages/VoltageMessage.scala index 3c836b599d..10a0e653fa 100644 --- a/src/main/scala/edu/ie3/simona/ontology/messages/VoltageMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/messages/VoltageMessage.scala @@ -6,7 +6,9 @@ package edu.ie3.simona.ontology.messages +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import org.apache.pekko.actor.typed.ActorRef import java.util.UUID import squants.electro.ElectricPotential @@ -27,7 +29,8 @@ object VoltageMessage { */ final case class RequestSlackVoltageMessage( currentSweepNo: Int, - nodeUuids: Seq[UUID] + nodeUuids: Seq[UUID], + sender: ActorRef[GridAgentMessage] ) extends VoltageMessage /** Provide complex voltage at the nodes that the sender's sub grid shares diff --git a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala index 7a619552eb..94ee03ebee 100644 --- a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala +++ b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala @@ -10,15 +10,17 @@ import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps import org.apache.pekko.actor.SupervisorStrategy.Stop import org.apache.pekko.actor.{ Actor, - ActorRef, AllForOneStrategy, Props, Stash, SupervisorStrategy, - Terminated + Terminated, + ActorRef => classicRef } import com.typesafe.scalalogging.LazyLogging import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.grid.GridAgentMessage +import edu.ie3.simona.agent.grid.GridAgentMessage.StopGridAgent import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.StopMessage import edu.ie3.simona.scheduler.TimeAdvancer @@ -34,6 +36,7 @@ import edu.ie3.simona.sim.SimonaSim.{ SimonaSimStateData } import edu.ie3.simona.sim.setup.{ExtSimSetupData, SimonaSetup} +import org.apache.pekko.actor.typed.ActorRef import scala.concurrent.duration.DurationInt import scala.language.postfixOps @@ -70,34 +73,32 @@ class SimonaSim(simonaSetup: SimonaSetup) /* start listener */ // output listener - val systemParticipantsListener: Seq[ActorRef] = + val systemParticipantsListener: Seq[classicRef] = simonaSetup.systemParticipantsListener(context) // runtime event listener - val runtimeEventListener - : org.apache.pekko.actor.typed.ActorRef[RuntimeEvent] = + val runtimeEventListener: ActorRef[RuntimeEvent] = simonaSetup.runtimeEventListener(context) /* start scheduler */ - val timeAdvancer - : org.apache.pekko.actor.typed.ActorRef[TimeAdvancer.Incoming] = + val timeAdvancer: ActorRef[TimeAdvancer.Incoming] = simonaSetup.timeAdvancer(context, self, runtimeEventListener) - val scheduler: ActorRef = simonaSetup.scheduler(context, timeAdvancer) + val scheduler: classicRef = simonaSetup.scheduler(context, timeAdvancer) /* start services */ // primary service proxy - val primaryServiceProxy: ActorRef = + val primaryServiceProxy: classicRef = simonaSetup.primaryServiceProxy(context, scheduler) // weather service - val weatherService: ActorRef = + val weatherService: classicRef = simonaSetup.weatherService(context, scheduler) val extSimulationData: ExtSimSetupData = simonaSetup.extSimulations(context, scheduler) /* start grid agents */ - val gridAgents: Iterable[ActorRef] = simonaSetup.gridAgents( + val gridAgents: Iterable[ActorRef[GridAgentMessage]] = simonaSetup.gridAgents( context, EnvironmentRefs( scheduler, @@ -116,7 +117,7 @@ class SimonaSim(simonaSetup: SimonaSetup) context.watch(scheduler) context.watch(primaryServiceProxy) context.watch(weatherService) - gridAgents.foreach(context.watch) + gridAgents.foreach(ref => context.watch(ref.toClassic)) override def receive: Receive = simonaSimReceive(SimonaSimStateData()) @@ -195,9 +196,9 @@ class SimonaSim(simonaSetup: SimonaSetup) } def waitingForListener( - initSimSender: ActorRef, + initSimSender: classicRef, successful: Boolean, - remainingListeners: Seq[ActorRef] + remainingListeners: Seq[classicRef] ): Receive = { case Terminated(actor) if remainingListeners.contains(actor) => val updatedRemainingListeners = remainingListeners.filterNot(_ == actor) @@ -231,8 +232,8 @@ class SimonaSim(simonaSetup: SimonaSetup) simulationSuccessful: Boolean ): Unit = { gridAgents.foreach { gridAgentRef => - context.unwatch(gridAgentRef) - gridAgentRef ! StopMessage(simulationSuccessful) + context.unwatch(gridAgentRef.toClassic) + gridAgentRef ! StopGridAgent } context.unwatch(scheduler) @@ -270,7 +271,7 @@ object SimonaSim { case object EmergencyShutdownInitiated private[SimonaSim] final case class SimonaSimStateData( - initSimSender: ActorRef = ActorRef.noSender + initSimSender: classicRef = classicRef.noSender ) def props(simonaSetup: SimonaSetup): Props = diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SetupHelper.scala b/src/main/scala/edu/ie3/simona/sim/setup/SetupHelper.scala index 1e319ecbcc..f689589755 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SetupHelper.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SetupHelper.scala @@ -6,7 +6,6 @@ package edu.ie3.simona.sim.setup -import org.apache.pekko.actor.ActorRef import com.typesafe.config.{Config => TypesafeConfig} import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.graph.SubGridGate @@ -14,6 +13,7 @@ import edu.ie3.datamodel.models.input.container.{SubGridContainer, ThermalGrid} import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.datamodel.utils.ContainerUtils import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.config.RefSystemParser.ConfigRefSystems import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.InitializationException @@ -23,6 +23,7 @@ import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.util.ConfigUtil.{GridOutputConfigUtil, OutputConfigUtil} import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig import edu.ie3.simona.util.{EntityMapperUtil, ResultFileHierarchy} +import org.apache.pekko.actor.typed.ActorRef /** Methods to support the setup of a simona simulation * @@ -54,7 +55,7 @@ trait SetupHelper extends LazyLogging { */ def buildGridAgentInitData( subGridContainer: SubGridContainer, - subGridToActorRef: Map[Int, ActorRef], + subGridToActorRef: Map[Int, ActorRef[GridAgentMessage]], gridGates: Set[SubGridGate], configRefSystems: ConfigRefSystems, thermalGrids: Seq[ThermalGrid] @@ -95,10 +96,10 @@ trait SetupHelper extends LazyLogging { * A mapping from [[SubGridGate]] to corresponding actor reference */ def buildGateToActorRef( - subGridToActorRefMap: Map[Int, ActorRef], + subGridToActorRefMap: Map[Int, ActorRef[GridAgentMessage]], subGridGates: Set[SubGridGate], currentSubGrid: Int - ): Map[SubGridGate, ActorRef] = + ): Map[SubGridGate, ActorRef[GridAgentMessage]] = subGridGates .groupBy(gate => (gate.superiorNode, gate.inferiorNode)) .flatMap(_._2.headOption) @@ -140,10 +141,10 @@ trait SetupHelper extends LazyLogging { * The actor reference of the sub grid to look for */ def getActorRef( - subGridToActorRefMap: Map[Int, ActorRef], + subGridToActorRefMap: Map[Int, ActorRef[GridAgentMessage]], currentSubGrid: Int, queriedSubGrid: Int - ): ActorRef = { + ): ActorRef[GridAgentMessage] = { subGridToActorRefMap.get(queriedSubGrid) match { case Some(hit) => hit case _ => diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala b/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala index caad2d1b7b..597c8e9127 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala @@ -6,12 +6,19 @@ package edu.ie3.simona.sim.setup -import org.apache.pekko.actor.{ActorContext, ActorRef, ActorSystem} +import org.apache.pekko.actor.{ + ActorSystem, + ActorContext => classicContext, + ActorRef => classicRef +} import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.datamodel.models.input.connector.Transformer3WInput import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.scheduler.TimeAdvancer +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.ActorContext /** Trait that can be used to setup a customized simona simulation by providing * implementations for all setup information required by a @@ -43,8 +50,8 @@ trait SimonaSetup { * An actor reference to the runtime event listener */ def runtimeEventListener( - context: ActorContext - ): org.apache.pekko.actor.typed.ActorRef[RuntimeEvent] + context: classicContext + ): ActorRef[RuntimeEvent] /** Creates a sequence of system participant event listeners * @@ -54,8 +61,8 @@ trait SimonaSetup { * A sequence of actor references to runtime event listeners */ def systemParticipantsListener( - context: ActorContext - ): Seq[ActorRef] + context: classicContext + ): Seq[classicRef] /** Creates a primary service proxy. The proxy is the first instance to ask * for primary data. If necessary, it delegates the registration request to @@ -69,9 +76,9 @@ trait SimonaSetup { * An actor reference to the service */ def primaryServiceProxy( - context: ActorContext, - scheduler: ActorRef - ): ActorRef + context: classicContext, + scheduler: classicRef + ): classicRef /** Creates a weather service * @@ -84,9 +91,9 @@ trait SimonaSetup { * the service */ def weatherService( - context: ActorContext, - scheduler: ActorRef - ): ActorRef + context: classicContext, + scheduler: classicRef + ): classicRef /** Loads external simulations and provides corresponding actors and init data * @@ -98,8 +105,8 @@ trait SimonaSetup { * External simulations and their init data */ def extSimulations( - context: ActorContext, - scheduler: ActorRef + context: classicContext, + scheduler: classicRef ): ExtSimSetupData /** Creates the time advancer @@ -114,10 +121,10 @@ trait SimonaSetup { * An actor reference to the time advancer */ def timeAdvancer( - context: ActorContext, - simulation: ActorRef, - runtimeEventListener: org.apache.pekko.actor.typed.ActorRef[RuntimeEvent] - ): org.apache.pekko.actor.typed.ActorRef[TimeAdvancer.Incoming] + context: classicContext, + simulation: classicRef, + runtimeEventListener: ActorRef[RuntimeEvent] + ): ActorRef[TimeAdvancer.Incoming] /** Creates a scheduler service * @@ -129,9 +136,9 @@ trait SimonaSetup { * An actor reference to the scheduler */ def scheduler( - context: ActorContext, - timeAdvancer: org.apache.pekko.actor.typed.ActorRef[TimeAdvancer.Incoming] - ): ActorRef + context: classicContext, + timeAdvancer: ActorRef[TimeAdvancer.Incoming] + ): classicRef /** Creates all the needed grid agents * @@ -146,10 +153,10 @@ trait SimonaSetup { * be used when setting up the agents */ def gridAgents( - context: ActorContext, + context: classicContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ActorRef] - ): Iterable[ActorRef] + systemParticipantListener: Seq[classicRef] + ): Iterable[ActorRef[GridAgentMessage]] /** SIMONA links sub grids connected by a three winding transformer a bit * different. Therefore, the internal node has to be set as superior node. diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala index 246fda0101..829c015f63 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala @@ -6,12 +6,6 @@ package edu.ie3.simona.sim.setup -import org.apache.pekko.actor.typed.scaladsl.adapter.{ - ClassicActorContextOps, - ClassicActorRefOps, - TypedActorRefOps -} -import org.apache.pekko.actor.{ActorContext, ActorRef, ActorSystem} import com.typesafe.config.Config import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.graph.SubGridTopologyGraph @@ -19,7 +13,8 @@ import edu.ie3.datamodel.models.input.container.{GridContainer, ThermalGrid} import edu.ie3.datamodel.models.input.thermal.ThermalBusInput import edu.ie3.simona.actor.SimonaActorNaming._ import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgent +import edu.ie3.simona.agent.grid.GridAgentMessage.CreateGridAgent +import edu.ie3.simona.agent.grid.{GridAgent, GridAgentMessage} import edu.ie3.simona.api.ExtSimAdapter import edu.ie3.simona.api.data.ExtData import edu.ie3.simona.api.data.ev.{ExtEvData, ExtEvSimulation} @@ -42,6 +37,17 @@ import edu.ie3.simona.util.ResultFileHierarchy import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.simona.util.TickUtil.RichZonedDateTime import edu.ie3.util.TimeUtil +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.adapter.{ + ClassicActorContextOps, + ClassicActorRefOps, + TypedActorRefOps +} +import org.apache.pekko.actor.{ + ActorSystem, + ActorContext => classicContext, + ActorRef => classicRef +} import java.util.concurrent.LinkedBlockingQueue import scala.jdk.CollectionConverters._ @@ -61,10 +67,10 @@ class SimonaStandaloneSetup( ) extends SimonaSetup { override def gridAgents( - context: ActorContext, + context: classicContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ActorRef] - ): Iterable[ActorRef] = { + systemParticipantListener: Seq[classicRef] + ): Iterable[ActorRef[GridAgentMessage]] = { /* get the grid */ val subGridTopologyGraph = GridProvider @@ -129,16 +135,16 @@ class SimonaStandaloneSetup( thermalGrids ) - currentActorRef ! GridAgent.Create(gridAgentInitData, key) + currentActorRef ! CreateGridAgent(gridAgentInitData, key) currentActorRef } } override def primaryServiceProxy( - context: ActorContext, - scheduler: ActorRef - ): ActorRef = { + context: classicContext, + scheduler: classicRef + ): classicRef = { val simulationStart = TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.startDateTime ) @@ -158,9 +164,9 @@ class SimonaStandaloneSetup( } override def weatherService( - context: ActorContext, - scheduler: ActorRef - ): ActorRef = { + context: classicContext, + scheduler: classicRef + ): classicRef = { val weatherService = context.simonaActorOf( WeatherService.props( scheduler, @@ -181,8 +187,8 @@ class SimonaStandaloneSetup( } override def extSimulations( - context: ActorContext, - scheduler: ActorRef + context: classicContext, + scheduler: classicRef ): ExtSimSetupData = { val jars = ExtSimLoader.scanInputFolder() @@ -206,7 +212,7 @@ class SimonaStandaloneSetup( // setup data services that belong to this external simulation val (extData, extDataInit): ( Iterable[ExtData], - Iterable[(Class[_ <: SimonaService[_]], ActorRef)] + Iterable[(Class[_ <: SimonaService[_]], classicRef)] ) = extLink.getExtDataSimulations.asScala.zipWithIndex.map { case (_: ExtEvSimulation, dIndex) => @@ -244,10 +250,10 @@ class SimonaStandaloneSetup( } override def timeAdvancer( - context: ActorContext, - simulation: ActorRef, - runtimeEventListener: org.apache.pekko.actor.typed.ActorRef[RuntimeEvent] - ): org.apache.pekko.actor.typed.ActorRef[TimeAdvancer.Incoming] = { + context: classicContext, + simulation: classicRef, + runtimeEventListener: ActorRef[RuntimeEvent] + ): ActorRef[TimeAdvancer.Incoming] = { val startDateTime = TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.startDateTime ) @@ -267,9 +273,9 @@ class SimonaStandaloneSetup( } override def scheduler( - context: ActorContext, - timeAdvancer: org.apache.pekko.actor.typed.ActorRef[TimeAdvancer.Incoming] - ): ActorRef = + context: classicContext, + timeAdvancer: ActorRef[TimeAdvancer.Incoming] + ): classicRef = context .spawn( Scheduler( @@ -280,8 +286,8 @@ class SimonaStandaloneSetup( .toClassic override def runtimeEventListener( - context: ActorContext - ): org.apache.pekko.actor.typed.ActorRef[RuntimeEvent] = + context: classicContext + ): ActorRef[RuntimeEvent] = context .spawn( RuntimeEventListener( @@ -293,8 +299,8 @@ class SimonaStandaloneSetup( ) override def systemParticipantsListener( - context: ActorContext - ): Seq[ActorRef] = { + context: classicContext + ): Seq[classicRef] = { // append ResultEventListener as well to write raw output files ArgsParser .parseListenerConfigOption(simonaConfig.simona.event.listener) @@ -317,17 +323,17 @@ class SimonaStandaloneSetup( def buildSubGridToActorRefMap( subGridTopologyGraph: SubGridTopologyGraph, - context: ActorContext, + context: classicContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ActorRef] - ): Map[Int, ActorRef] = { + systemParticipantListener: Seq[classicRef] + ): Map[Int, ActorRef[GridAgentMessage]] = { subGridTopologyGraph .vertexSet() .asScala .map(subGridContainer => { val gridAgentRef = - context.simonaActorOf( - GridAgent.props( + context.spawn( + GridAgent( environmentRefs, simonaConfig, systemParticipantListener diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala index 5beb87d7b0..9dcb20b9e9 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala @@ -6,18 +6,13 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.ActorSystem -import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps -import org.apache.pekko.testkit.TestProbe -import com.typesafe.config.ConfigFactory import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgent.FinishGridSimulationTrigger import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid +import edu.ie3.simona.agent.grid.GridAgentMessage._ import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent +import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage import edu.ie3.simona.model.grid.RefSystem -import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.SchedulerMessage.{ @@ -26,15 +21,17 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ } import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGrid -import edu.ie3.simona.test.common.{ - ConfigTestData, - TestKitWithShutdown, - TestSpawnerClassic -} +import edu.ie3.simona.test.common.{ConfigTestData, TestSpawnerTyped} import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.scala.quantities.Megavars +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + ScalaTestWithActorTestKit, + TestProbe +} +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps import squants.electro.Kilovolts import squants.energy.Megawatts @@ -49,22 +46,14 @@ import scala.language.postfixOps * interaction or cover this behaviour by another (integration) test! */ class DBFSAlgorithmCenGridSpec - extends TestKitWithShutdown( - ActorSystem( - "DBFSAlgorithmCenGridSpec", - ConfigFactory - .parseString(""" - |pekko.loggers =["org.apache.pekko.event.slf4j.Slf4jLogger"] - |pekko.loglevel="OFF" - """.stripMargin) - ) - ) + extends ScalaTestWithActorTestKit with DBFSMockGridAgents with ConfigTestData with DbfsTestGrid - with TestSpawnerClassic { + with TestSpawnerTyped { - private val scheduler = TestProbe("scheduler") + private val scheduler: TestProbe[SchedulerMessage] = + TestProbe[SchedulerMessage]("scheduler") private val runtimeEvents = TestProbe("runtimeEvents") private val primaryService = TestProbe("primaryService") private val weatherService = TestProbe("weatherService") @@ -86,23 +75,24 @@ class DBFSAlgorithmCenGridSpec ) private val environmentRefs = EnvironmentRefs( - scheduler = scheduler.ref, - runtimeEventListener = runtimeEvents.ref, - primaryServiceProxy = primaryService.ref, - weather = weatherService.ref, + scheduler = scheduler.ref.toClassic, + runtimeEventListener = runtimeEvents.ref.toClassic, + primaryServiceProxy = primaryService.ref.toClassic, + weather = weatherService.ref.toClassic, evDataService = None ) - val resultListener: TestProbe = TestProbe("resultListener") + val resultListener: TestProbe[ResultMessage] = + TestProbe[ResultMessage]("resultListener") "A GridAgent actor in center position with async test" should { val centerGridAgent = - system.actorOf( - GridAgent.props( + testKit.spawn( + GridAgent( environmentRefs, simonaConfig, - listener = Iterable(resultListener.ref) + listener = Iterable(resultListener.ref.toClassic) ) ) @@ -130,40 +120,29 @@ class DBFSAlgorithmCenGridSpec ) val key = - ScheduleLock.singleKey(TSpawner, scheduler.ref.toTyped, INIT_SIM_TICK) - scheduler.expectMsgType[ScheduleActivation] // lock activation scheduled + ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) + scheduler + .expectMessageType[ScheduleActivation] // lock activation scheduled - centerGridAgent ! GridAgent.Create( + centerGridAgent ! CreateGridAgent( gridAgentInitData, key ) - scheduler.expectMsg( - ScheduleActivation(centerGridAgent.toTyped, INIT_SIM_TICK, Some(key)) - ) - scheduler.send(centerGridAgent, Activation(INIT_SIM_TICK)) - scheduler.expectMsg( - Completion( - centerGridAgent.toTyped, - Some(3600) - ) - ) + val msg = scheduler.expectMessageType[ScheduleActivation] + msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) + centerGridAgent ! ActivationAdapter(Activation(INIT_SIM_TICK)) + val completionMessage = scheduler.expectMessageType[Completion] + completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) } - s"go to $SimulateGrid when it receives an activity start trigger" in { + s"go to SimulateGrid when it receives an activity start trigger" in { - scheduler.send( - centerGridAgent, - Activation(3600) - ) + centerGridAgent ! ActivationAdapter(Activation(3600)) - scheduler.expectMsg( - Completion( - centerGridAgent.toTyped, - Some(3600) - ) - ) + val msg = scheduler.expectMessageType[Completion] + msg shouldBe Completion(msg.actor, Some(3600)) } s"start the simulation when activation is sent" in { @@ -171,7 +150,7 @@ class DBFSAlgorithmCenGridSpec val firstSweepNo = 0 // send the start grid simulation trigger - scheduler.send(centerGridAgent, Activation(3600)) + centerGridAgent ! ActivationAdapter(Activation(3600)) /* We expect one grid power request message per inferior grid */ @@ -188,7 +167,6 @@ class DBFSAlgorithmCenGridSpec // normally the inferior grid agents ask for the slack voltage as well to do their power flow calculations // we simulate this behaviour now by doing the same for our three inferior grid agents - inferiorGrid11.requestSlackVoltage(centerGridAgent, firstSweepNo) inferiorGrid12.requestSlackVoltage(centerGridAgent, firstSweepNo) @@ -239,8 +217,7 @@ class DBFSAlgorithmCenGridSpec // we now answer the request of our centerGridAgent // with three fake grid power messages and one fake slack voltage message - inferiorGrid11.gaProbe.send( - firstPowerRequestSender11, + firstPowerRequestSender11 ! PMAdapter( ProvideGridPowerMessage( inferiorGrid11.nodeUuids.map(nodeUuid => ExchangePower( @@ -252,8 +229,7 @@ class DBFSAlgorithmCenGridSpec ) ) - inferiorGrid12.gaProbe.send( - firstPowerRequestSender12, + firstPowerRequestSender12 ! PMAdapter( ProvideGridPowerMessage( inferiorGrid12.nodeUuids.map(nodeUuid => ExchangePower( @@ -265,8 +241,7 @@ class DBFSAlgorithmCenGridSpec ) ) - inferiorGrid13.gaProbe.send( - firstPowerRequestSender13, + firstPowerRequestSender13 ! PMAdapter( ProvideGridPowerMessage( inferiorGrid13.nodeUuids.map(nodeUuid => ExchangePower( @@ -278,8 +253,7 @@ class DBFSAlgorithmCenGridSpec ) ) - superiorGridAgent.gaProbe.send( - firstSlackVoltageRequestSender, + firstSlackVoltageRequestSender ! VMAdapter( ProvideSlackVoltageMessage( firstSweepNo, Seq( @@ -327,8 +301,7 @@ class DBFSAlgorithmCenGridSpec superiorGridAgent.expectSlackVoltageRequest(secondSweepNo) // the superior grid would answer with updated slack voltage values - superiorGridAgent.gaProbe.send( - secondSlackAskSender, + secondSlackAskSender ! VMAdapter( ProvideSlackVoltageMessage( secondSweepNo, Seq( @@ -411,8 +384,8 @@ class DBFSAlgorithmCenGridSpec // we now answer the requests of our centerGridAgent // with three fake grid power message - inferiorGrid11.gaProbe.send( - secondPowerRequestSender11, + + secondPowerRequestSender11 ! PMAdapter( ProvideGridPowerMessage( inferiorGrid11.nodeUuids.map(nodeUuid => ExchangePower( @@ -424,8 +397,7 @@ class DBFSAlgorithmCenGridSpec ) ) - inferiorGrid12.gaProbe.send( - secondPowerRequestSender12, + secondPowerRequestSender12 ! PMAdapter( ProvideGridPowerMessage( inferiorGrid12.nodeUuids.map(nodeUuid => ExchangePower( @@ -437,8 +409,7 @@ class DBFSAlgorithmCenGridSpec ) ) - inferiorGrid13.gaProbe.send( - secondPowerRequestSender13, + secondPowerRequestSender13 ! PMAdapter( ProvideGridPowerMessage( inferiorGrid13.nodeUuids.map(nodeUuid => ExchangePower( @@ -468,27 +439,23 @@ class DBFSAlgorithmCenGridSpec // normally the slack node would send a FinishGridSimulationTrigger to all // connected inferior grids, because the slack node is just a mock, we imitate this behavior - superiorGridAgent.gaProbe.send( - centerGridAgent, - FinishGridSimulationTrigger(3600) - ) + centerGridAgent ! FinishGridSimulationTrigger(3600) // after a FinishGridSimulationTrigger is send the inferior grids, they themselves will send the // Trigger forward the trigger to their connected inferior grids. Therefore the inferior grid // agent should receive a FinishGridSimulationTrigger - inferiorGrid11.gaProbe.expectMsg(FinishGridSimulationTrigger(3600)) - inferiorGrid12.gaProbe.expectMsg(FinishGridSimulationTrigger(3600)) - inferiorGrid13.gaProbe.expectMsg(FinishGridSimulationTrigger(3600)) + inferiorGrid11.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) + + inferiorGrid12.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) + + inferiorGrid13.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a CompletionMessage - scheduler.expectMsg( - Completion( - centerGridAgent.toTyped, - Some(7200) - ) - ) + val cm = scheduler.expectMessageType[Completion] + cm shouldBe Completion(cm.actor, Some(7200)) - resultListener.expectMsgPF() { + val resultMessage = resultListener.expectMessageType[ResultMessage] + resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => // we expect results for 4 nodes, 5 lines and 2 transformer2ws powerFlowResultEvent.nodeResults.size shouldBe 4 diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala index 85b4bb041a..5c63c8a0e8 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala @@ -6,17 +6,12 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.ActorSystem -import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps -import org.apache.pekko.testkit.{ImplicitSender, TestProbe} -import com.typesafe.config.ConfigFactory import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgent.FinishGridSimulationTrigger import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid +import edu.ie3.simona.agent.grid.GridAgentMessage._ +import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage import edu.ie3.simona.model.grid.RefSystem -import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ FailedPowerFlow, @@ -28,15 +23,17 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ } import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGrid -import edu.ie3.simona.test.common.{ - ConfigTestData, - TestKitWithShutdown, - TestSpawnerClassic -} +import edu.ie3.simona.test.common.{ConfigTestData, TestSpawnerTyped} import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.scala.quantities.Megavars +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + ScalaTestWithActorTestKit, + TestProbe +} +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps import squants.electro.Kilovolts import squants.energy.Megawatts @@ -44,23 +41,14 @@ import scala.concurrent.duration.DurationInt import scala.language.postfixOps class DBFSAlgorithmFailedPowerFlowSpec - extends TestKitWithShutdown( - ActorSystem( - "DBFSAlgorithmSpec", - ConfigFactory - .parseString(""" - |pekko.loggers =["org.apache.pekko.event.slf4j.Slf4jLogger"] - |pekko.loglevel="OFF" - """.stripMargin) - ) - ) + extends ScalaTestWithActorTestKit with DBFSMockGridAgents with ConfigTestData - with ImplicitSender with DbfsTestGrid - with TestSpawnerClassic { + with TestSpawnerTyped { - private val scheduler = TestProbe("scheduler") + private val scheduler: TestProbe[SchedulerMessage] = + TestProbe[SchedulerMessage]("scheduler") private val runtimeEvents = TestProbe("runtimeEvents") private val primaryService = TestProbe("primaryService") private val weatherService = TestProbe("weatherService") @@ -74,23 +62,24 @@ class DBFSAlgorithmFailedPowerFlowSpec InferiorGA(TestProbe("inferiorGridAgent"), Seq(node1.getUuid)) private val environmentRefs = EnvironmentRefs( - scheduler = scheduler.ref, - runtimeEventListener = runtimeEvents.ref, - primaryServiceProxy = primaryService.ref, - weather = weatherService.ref, + scheduler = scheduler.ref.toClassic, + runtimeEventListener = runtimeEvents.ref.toClassic, + primaryServiceProxy = primaryService.ref.toClassic, + weather = weatherService.ref.toClassic, evDataService = None ) - val resultListener: TestProbe = TestProbe("resultListener") + val resultListener: TestProbe[ResultMessage] = + TestProbe[ResultMessage]("resultListener") "A GridAgent actor in center position with async test" should { val centerGridAgent = - system.actorOf( - GridAgent.props( + testKit.spawn( + GridAgent( environmentRefs, simonaConfig, - listener = Iterable(resultListener.ref) + listener = Iterable(resultListener.ref.toClassic) ) ) @@ -115,49 +104,40 @@ class DBFSAlgorithmFailedPowerFlowSpec ) val key = - ScheduleLock.singleKey(TSpawner, scheduler.ref.toTyped, INIT_SIM_TICK) - scheduler.expectMsgType[ScheduleActivation] // lock activation scheduled + ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) + scheduler.expectMessageType[SchedulerMessage] // lock activation scheduled - centerGridAgent ! GridAgent.Create( + centerGridAgent ! CreateGridAgent( gridAgentInitData, key ) - scheduler.expectMsg( - ScheduleActivation(centerGridAgent.toTyped, INIT_SIM_TICK, Some(key)) - ) - scheduler.send(centerGridAgent, Activation(INIT_SIM_TICK)) - scheduler.expectMsg( - Completion( - centerGridAgent.toTyped, - Some(3600) - ) + val message = scheduler.expectMessageType[ScheduleActivation] + message shouldBe ScheduleActivation( + message.actor, + INIT_SIM_TICK, + Some(key) ) + centerGridAgent ! ActivationAdapter(Activation(INIT_SIM_TICK)) + scheduler.expectMessage(Completion(message.actor, Some(3600))) } - s"go to $SimulateGrid when it receives an activation" in { + s"go to SimulateGrid when it receives an activation" in { // send init data to agent - scheduler.send( - centerGridAgent, - Activation(3600) - ) + centerGridAgent ! ActivationAdapter(Activation(3600)) // we expect a completion message - scheduler.expectMsg( - Completion( - centerGridAgent.toTyped, - Some(3600) - ) - ) + val message = scheduler.expectMessageType[Completion] + message shouldBe Completion(message.actor, Some(3600)) } s"start the simulation when an activation is sent is sent, handle failed power flow if it occurs" in { val sweepNo = 0 // send the start grid simulation trigger - scheduler.send(centerGridAgent, Activation(3600)) + centerGridAgent ! ActivationAdapter(Activation(3600)) // we expect a request for grid power values here for sweepNo $sweepNo val powerRequestSender = inferiorGridAgent.expectGridPowerRequest() @@ -186,8 +166,7 @@ class DBFSAlgorithmFailedPowerFlowSpec // we now answer the request of our centerGridAgent // with a fake grid power message and one fake slack voltage message - inferiorGridAgent.gaProbe.send( - powerRequestSender, + powerRequestSender ! PMAdapter( ProvideGridPowerMessage( inferiorGridAgent.nodeUuids.map(nodeUuid => ExchangePower( @@ -199,8 +178,7 @@ class DBFSAlgorithmFailedPowerFlowSpec ) ) - superiorGridAgent.gaProbe.send( - slackVoltageRequestSender, + slackVoltageRequestSender ! VMAdapter( ProvideSlackVoltageMessage( sweepNo, Seq( @@ -221,27 +199,23 @@ class DBFSAlgorithmFailedPowerFlowSpec // the requested power is to high for the grid to handle, therefore the superior grid agent // receives a FailedPowerFlow message // wait 30 seconds max for power flow to finish - superiorGridAgent.gaProbe.expectMsg(30 seconds, FailedPowerFlow) + superiorGridAgent.gaProbe.expectMessage( + 30 seconds, + PMAdapter(FailedPowerFlow) + ) // normally the slack node would send a FinishGridSimulationTrigger to all // connected inferior grids, because the slack node is just a mock, we imitate this behavior - superiorGridAgent.gaProbe.send( - centerGridAgent, - FinishGridSimulationTrigger(3600) - ) + centerGridAgent ! FinishGridSimulationTrigger(3600) // after a FinishGridSimulationTrigger is send to the inferior grids, they themselves will // forward the trigger to their connected inferior grids. Therefore the inferior grid agent // should receive a FinishGridSimulationTrigger - inferiorGridAgent.gaProbe.expectMsg(FinishGridSimulationTrigger(3600)) + inferiorGridAgent.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a CompletionMessage - scheduler.expectMsg( - Completion( - centerGridAgent.toTyped, - Some(7200) - ) - ) + val message = scheduler.expectMessageType[Completion] + message shouldBe Completion(message.actor, Some(7200)) resultListener.expectNoMessage() diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala index f104f20bbf..3f1c8bc02d 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala @@ -6,20 +6,17 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.typed.scaladsl.adapter.{ - ClassicActorRefOps, - TypedActorRefOps -} -import org.apache.pekko.actor.{ActorRef, ActorSystem} -import org.apache.pekko.testkit.{ImplicitSender, TestProbe} -import com.typesafe.config.ConfigFactory import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgent.FinishGridSimulationTrigger import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid +import edu.ie3.simona.agent.grid.GridAgentMessage.{ + ActivationAdapter, + VMAdapter, + CreateGridAgent, + FinishGridSimulationTrigger +} +import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage import edu.ie3.simona.model.grid.RefSystem -import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, @@ -27,53 +24,50 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ } import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.ontology.messages.services.ServiceMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.PrimaryServiceRegistrationMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.RegistrationResponseMessage.RegistrationFailedMessage +import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGridWithParticipants -import edu.ie3.simona.test.common.{ - ConfigTestData, - TestKitWithShutdown, - TestSpawnerClassic -} +import edu.ie3.simona.test.common.{ConfigTestData, TestSpawnerTyped} import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.scala.quantities.Megavars +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + ScalaTestWithActorTestKit, + TestProbe +} +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps import squants.electro.Kilovolts import squants.energy.Megawatts import scala.language.postfixOps class DBFSAlgorithmParticipantSpec - extends TestKitWithShutdown( - ActorSystem( - "DBFSAlgorithmSpec", - ConfigFactory - .parseString(""" - |pekko.loggers =["org.apache.pekko.event.slf4j.Slf4jLogger"] - |pekko.loglevel="OFF" - """.stripMargin) - ) - ) + extends ScalaTestWithActorTestKit with DBFSMockGridAgents with ConfigTestData - with ImplicitSender with DbfsTestGridWithParticipants - with TestSpawnerClassic { + with TestSpawnerTyped { - private val scheduler = TestProbe("scheduler") + private val scheduler: TestProbe[SchedulerMessage] = + TestProbe[SchedulerMessage]("scheduler") private val runtimeEvents = TestProbe("runtimeEvents") - private val primaryService = TestProbe("primaryService") + private val primaryService: TestProbe[ServiceMessage] = + TestProbe[ServiceMessage]("primaryService") private val weatherService = TestProbe("weatherService") private val environmentRefs = EnvironmentRefs( - scheduler = scheduler.ref, - runtimeEventListener = runtimeEvents.ref, - primaryServiceProxy = primaryService.ref, - weather = weatherService.ref, + scheduler = scheduler.ref.toClassic, + runtimeEventListener = runtimeEvents.ref.toClassic, + primaryServiceProxy = primaryService.ref.toClassic, + weather = weatherService.ref.toClassic, evDataService = None ) - protected val resultListener: TestProbe = TestProbe("resultListener") + protected val resultListener: TestProbe[ResultMessage] = + TestProbe[ResultMessage]("resultListener") private val superiorGridAgent = SuperiorGA( TestProbe("superiorGridAgent_1000"), @@ -81,18 +75,18 @@ class DBFSAlgorithmParticipantSpec ) "Test participant" should { - val gridAgentWithParticipants = system.actorOf( - GridAgent.props( + val gridAgentWithParticipants = testKit.spawn( + GridAgent( environmentRefs, simonaConfig, - Iterable(resultListener.ref) + Iterable(resultListener.ref.toClassic) ) ) s"initialize itself when it receives an init activation" in { // this subnet has 1 superior grid (ehv) and 3 inferior grids (mv). Map the gates to test probes accordingly - val subGridGateToActorRef: Map[SubGridGate, ActorRef] = + val subGridGateToActorRef: Map[SubGridGate, ActorRef[GridAgentMessage]] = hvSubGridGates.map { gate => gate -> superiorGridAgent.ref }.toMap @@ -105,74 +99,58 @@ class DBFSAlgorithmParticipantSpec ) val key = - ScheduleLock.singleKey(TSpawner, scheduler.ref.toTyped, INIT_SIM_TICK) - scheduler.expectMsgType[ScheduleActivation] // lock activation scheduled - - gridAgentWithParticipants ! GridAgent.Create(gridAgentInitData, key) - scheduler.expectMsg( - ScheduleActivation( - gridAgentWithParticipants.toTyped, - INIT_SIM_TICK, - Some(key) - ) - ) + ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) + scheduler + .expectMessageType[ScheduleActivation] // lock activation scheduled + + gridAgentWithParticipants ! CreateGridAgent(gridAgentInitData, key) + + val msg = scheduler.expectMessageType[ScheduleActivation] + msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) // send init data to agent and expect a CompletionMessage - scheduler.send(gridAgentWithParticipants, Activation(INIT_SIM_TICK)) - - val loadAgent = - scheduler.expectMsgPF() { - case ScheduleActivation( - loadAgent, - INIT_SIM_TICK, - _ - ) => - loadAgent - } - - scheduler.expectMsg( - Completion( - gridAgentWithParticipants.toTyped, - Some(3600) - ) - ) + gridAgentWithParticipants ! ActivationAdapter(Activation(INIT_SIM_TICK)) + + val message = scheduler.expectMessageType[ScheduleActivation] - scheduler.send(loadAgent.toClassic, Activation(INIT_SIM_TICK)) + val loadAgent: ActorRef[Activation] = message match { + case ScheduleActivation( + loadAgent, + INIT_SIM_TICK, + _ + ) => + loadAgent + } - primaryService.expectMsg( + val completionMessage = scheduler.expectMessageType[Completion] + completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) + + loadAgent ! Activation(INIT_SIM_TICK) + + primaryService.expectMessage( PrimaryServiceRegistrationMessage(load1.getUuid) ) - primaryService.send(loadAgent.toClassic, RegistrationFailedMessage) + loadAgent.toClassic ! RegistrationFailedMessage - scheduler.expectMsg(Completion(loadAgent, Some(0))) + scheduler.expectMessage(Completion(loadAgent, Some(0))) // triggering the loadAgent's calculation - scheduler.send( - loadAgent.toClassic, - Activation(0) - ) + loadAgent ! Activation(0) + // the load agent should send a CompletionMessage - scheduler.expectMsg(Completion(loadAgent, None)) + scheduler.expectMessage(Completion(loadAgent, None)) } - s"go to $SimulateGrid when it receives an activity start trigger" in { + s"go to SimulateGrid when it receives an activity start trigger" in { // send init data to agent - scheduler.send( - gridAgentWithParticipants, - Activation(3600) - ) + gridAgentWithParticipants ! ActivationAdapter(Activation(3600)) // we expect a completion message - scheduler.expectMsg( - Completion( - gridAgentWithParticipants.toTyped, - Some(3600) - ) - ) - + val message = scheduler.expectMessageType[Completion] + message shouldBe Completion(message.actor, Some(3600)) } s"check the request asset power message indirectly" in { @@ -181,7 +159,7 @@ class DBFSAlgorithmParticipantSpec // send the start grid simulation trigger // the gird agent should send a RequestAssetPowerMessage to the load agent - scheduler.send(gridAgentWithParticipants, Activation(3600)) + gridAgentWithParticipants ! ActivationAdapter(Activation(3600)) // we expect a request for voltage values of our slack node // (voltages are requested by our agent under test from the superior grid) @@ -190,8 +168,7 @@ class DBFSAlgorithmParticipantSpec // we now answer the request of our gridAgentsWithParticipants // with a fake slack voltage message - superiorGridAgent.gaProbe.send( - firstSlackVoltageRequestSender, + firstSlackVoltageRequestSender ! VMAdapter( ProvideSlackVoltageMessage( firstSweepNo, Seq( @@ -238,8 +215,7 @@ class DBFSAlgorithmParticipantSpec superiorGridAgent.expectSlackVoltageRequest(secondSweepNo) // the superior grid would answer with updated slack voltage values - superiorGridAgent.gaProbe.send( - secondSlackAskSender, + secondSlackAskSender ! VMAdapter( ProvideSlackVoltageMessage( secondSweepNo, Seq( @@ -266,17 +242,10 @@ class DBFSAlgorithmParticipantSpec // normally the superior grid agent would send a FinishGridSimulationTrigger to the inferior grid agent after the convergence // (here we do it by hand) - superiorGridAgent.gaProbe.send( - gridAgentWithParticipants, - FinishGridSimulationTrigger(3600L) - ) + gridAgentWithParticipants ! FinishGridSimulationTrigger(3600L) - scheduler.expectMsg( - Completion( - gridAgentWithParticipants.toTyped, - Some(7200) - ) - ) + val message = scheduler.expectMessageType[Completion] + message shouldBe Completion(message.actor, Some(7200)) } } } diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala index ca8687a44b..30f031e6f5 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala @@ -6,19 +6,19 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps -import org.apache.pekko.actor.{ActorRef, ActorSystem} -import org.apache.pekko.testkit.{ImplicitSender, TestProbe} -import com.typesafe.config.ConfigFactory import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgent.FinishGridSimulationTrigger import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid +import edu.ie3.simona.agent.grid.GridAgentMessage.{ + ActivationAdapter, + CreateGridAgent, + FinishGridSimulationTrigger, + PMAdapter +} import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent +import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage import edu.ie3.simona.model.grid.RefSystem -import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ ProvideGridPowerMessage, @@ -28,16 +28,19 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation } +import edu.ie3.simona.ontology.messages.services.ServiceMessage +import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGrid -import edu.ie3.simona.test.common.{ - ConfigTestData, - TestKitWithShutdown, - TestSpawnerClassic, - UnitSpec -} +import edu.ie3.simona.test.common.{ConfigTestData, TestSpawnerTyped, UnitSpec} import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.scala.quantities.Megavars +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + ScalaTestWithActorTestKit, + TestProbe +} +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps import squants.energy.Megawatts import java.util.UUID @@ -50,49 +53,43 @@ import scala.language.postfixOps * [[GridAgent]] are simulated by the TestKit. */ class DBFSAlgorithmSupGridSpec - extends TestKitWithShutdown( - ActorSystem( - "DBFSAlgorithmSpec", - ConfigFactory - .parseString(""" - |pekko.loggers =["org.apache.pekko.event.slf4j.Slf4jLogger"] - |pekko.loglevel="OFF" - """.stripMargin) - ) - ) + extends ScalaTestWithActorTestKit with UnitSpec with ConfigTestData - with ImplicitSender with DbfsTestGrid - with TestSpawnerClassic { + with TestSpawnerTyped { - private val scheduler: TestProbe = TestProbe("scheduler") + private val scheduler: TestProbe[SchedulerMessage] = + TestProbe[SchedulerMessage]("scheduler") private val runtimeEvents = TestProbe("runtimeEvents") - private val primaryService: TestProbe = TestProbe("primaryService") - private val weatherService: TestProbe = TestProbe("weatherService") - private val hvGrid: TestProbe = TestProbe("hvGrid") + private val primaryService: TestProbe[ServiceMessage] = + TestProbe[ServiceMessage]("primaryService") + private val weatherService = TestProbe("weatherService") + private val hvGrid: TestProbe[GridAgentMessage] = + TestProbe[GridAgentMessage]("hvGrid") private val environmentRefs = EnvironmentRefs( - scheduler = scheduler.ref, - runtimeEventListener = runtimeEvents.ref, - primaryServiceProxy = primaryService.ref, - weather = weatherService.ref, + scheduler = scheduler.ref.toClassic, + runtimeEventListener = runtimeEvents.ref.toClassic, + primaryServiceProxy = primaryService.ref.toClassic, + weather = weatherService.ref.toClassic, evDataService = None ) - val resultListener: TestProbe = TestProbe("resultListener") + val resultListener: TestProbe[ResultMessage] = + TestProbe[ResultMessage]("resultListener") "A GridAgent actor in superior position with async test" should { - val superiorGridAgentFSM: ActorRef = system.actorOf( - GridAgent.props( + val superiorGridAgentFSM: ActorRef[GridAgentMessage] = testKit.spawn( + GridAgent( environmentRefs, simonaConfig, - listener = Iterable(resultListener.ref) + listener = Iterable(resultListener.ref.toClassic) ) ) s"initialize itself when it receives an init activation" in { - val subnetGatesToActorRef: Map[SubGridGate, ActorRef] = + val subnetGatesToActorRef: Map[SubGridGate, ActorRef[GridAgentMessage]] = ehvSubGridGates.map(gate => gate -> hvGrid.ref).toMap val gridAgentInitData = @@ -104,30 +101,28 @@ class DBFSAlgorithmSupGridSpec ) val key = - ScheduleLock.singleKey(TSpawner, scheduler.ref.toTyped, INIT_SIM_TICK) - scheduler.expectMsgType[ScheduleActivation] // lock activation scheduled - - superiorGridAgentFSM ! GridAgent.Create(gridAgentInitData, key) - scheduler.expectMsg( - ScheduleActivation( - superiorGridAgentFSM.toTyped, - INIT_SIM_TICK, - Some(key) - ) - ) + ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) + scheduler + .expectMessageType[ScheduleActivation] // lock activation scheduled + + superiorGridAgentFSM ! CreateGridAgent(gridAgentInitData, key) - scheduler.send(superiorGridAgentFSM, Activation(INIT_SIM_TICK)) - scheduler.expectMsg(Completion(superiorGridAgentFSM.toTyped, Some(3600))) + val am = scheduler.expectMessageType[ScheduleActivation] + am shouldBe ScheduleActivation(am.actor, INIT_SIM_TICK, Some(key)) + superiorGridAgentFSM ! ActivationAdapter(Activation(INIT_SIM_TICK)) + + val cm = scheduler.expectMessageType[Completion] + cm shouldBe Completion(cm.actor, Some(3600)) } - s"go to $SimulateGrid when it receives an activity start trigger" in { + s"go to SimulateGrid when it receives an activity start trigger" in { // send init data to agent - scheduler.send(superiorGridAgentFSM, Activation(3600)) + superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) // we expect a completion message - scheduler.expectMsg(Completion(superiorGridAgentFSM.toTyped, Some(3600))) - + val message = scheduler.expectMessageType[Completion] + message shouldBe Completion(message.actor, Some(3600)) } s"start the simulation, do 2 sweeps and should end afterwards when no deviation on nodal " + @@ -139,25 +134,27 @@ class DBFSAlgorithmSupGridSpec Vector(UUID.fromString("9fe5fa33-6d3b-4153-a829-a16f4347bc4e")) // send the start grid simulation trigger - scheduler.send(superiorGridAgentFSM, Activation(3600)) + superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) // we expect a request for grid power values here for sweepNo $sweepNo - hvGrid.expectMsgPF() { - case requestGridPowerMessage: RequestGridPowerMessage => + val message = hvGrid.expectMessageType[PMAdapter] + + val lastSender = message match { + case PMAdapter(requestGridPowerMessage: RequestGridPowerMessage) => requestGridPowerMessage.currentSweepNo shouldBe sweepNo requestGridPowerMessage.nodeUuids should contain allElementsOf requestedConnectionNodeUuids + + requestGridPowerMessage.sender case x => fail( s"Invalid message received when expecting a request for grid power values! Message was $x" ) - } // we return with a fake grid power message // / as we are using the ask pattern, we cannot send it to the grid agent directly but have to send it to the // / ask sender - hvGrid.send( - hvGrid.lastSender, + lastSender ! PMAdapter( ProvideGridPowerMessage( requestedConnectionNodeUuids.map { uuid => ExchangePower( @@ -172,12 +169,18 @@ class DBFSAlgorithmSupGridSpec // we expect a completion message here and that the agent goes back to simulate grid // and waits until the newly scheduled StartGridSimulationTrigger is send // wait 30 seconds max for power flow to finish - scheduler.expectMsgPF(30 seconds) { + val completionMessage = + scheduler.expectMessageType[Completion](130 seconds) + + completionMessage match { case Completion(_, Some(3600)) => // we expect another completion message when the agent is in SimulateGrid again case Completion(_, Some(7200)) => // agent should be in Idle again and listener should contain power flow result data - resultListener.expectMsgPF() { + val resultMessage = + resultListener.expectMessageType[ResultMessage] + + resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => powerFlowResultEvent.nodeResults.headOption match { case Some(value) => @@ -196,7 +199,7 @@ class DBFSAlgorithmSupGridSpec // no failed power flow runtimeEvents.expectNoMessage() - hvGrid.expectMsg(FinishGridSimulationTrigger(3600)) + hvGrid.expectMessage(FinishGridSimulationTrigger(3600)) case x => fail( @@ -240,12 +243,11 @@ class DBFSAlgorithmSupGridSpec ) // bring agent in simulate grid state - scheduler.send(superiorGridAgentFSM, Activation(3600)) + superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) // we expect a completion message - scheduler.expectMsg( - Completion(superiorGridAgentFSM.toTyped, Some(3600)) - ) + val message = scheduler.expectMessageType[Completion] + message shouldBe Completion(message.actor, Some(3600)) // go on with testing the sweep behaviour for (sweepNo <- 0 to maxNumberOfTestSweeps) { @@ -254,13 +256,17 @@ class DBFSAlgorithmSupGridSpec Vector(UUID.fromString("9fe5fa33-6d3b-4153-a829-a16f4347bc4e")) // send the start grid simulation trigger - scheduler.send(superiorGridAgentFSM, Activation(3600)) + superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) // we expect a request for grid power values here for sweepNo $sweepNo - hvGrid.expectMsgPF() { - case requestGridPowerMessage: RequestGridPowerMessage => + val message = hvGrid.expectMessageType[GridAgentMessage] + + val lastSender = message match { + case PMAdapter(requestGridPowerMessage: RequestGridPowerMessage) => requestGridPowerMessage.currentSweepNo shouldBe sweepNo requestGridPowerMessage.nodeUuids should contain allElementsOf requestedConnectionNodeUuids + + requestGridPowerMessage.sender case x => fail( s"Invalid message received when expecting a request for grid power values! Message was $x" @@ -270,8 +276,7 @@ class DBFSAlgorithmSupGridSpec // we return with a fake grid power message // / as we are using the ask pattern, we cannot send it to the grid agent directly but have to send it to the // / ask sender - hvGrid.send( - hvGrid.lastSender, + lastSender ! PMAdapter( ProvideGridPowerMessage( requestedConnectionNodeUuids.map { uuid => ExchangePower( @@ -288,13 +293,19 @@ class DBFSAlgorithmSupGridSpec // Simulate Grid // wait 30 seconds max for power flow to finish - scheduler.expectMsgPF(30 seconds) { + val completionMessage = + scheduler.expectMessageType[Completion](30 seconds) + + completionMessage match { case Completion(_, Some(3600)) => // when we received a FinishGridSimulationTrigger (as inferior grid agent) // we expect another completion message then as well (scheduler view) case Completion(_, Some(7200)) => // after doing cleanup stuff, our agent should go back to idle again and listener should contain power flow result data - resultListener.expectMsgPF() { + val resultMessage = + resultListener.expectMessageType[ResultMessage] + + resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => powerFlowResultEvent.nodeResults.headOption match { case Some(value) => @@ -313,7 +324,7 @@ class DBFSAlgorithmSupGridSpec // no failed power flow runtimeEvents.expectNoMessage() - hvGrid.expectMsg(FinishGridSimulationTrigger(3600)) + hvGrid.expectMessage(FinishGridSimulationTrigger(3600)) case x => fail( diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala index 0f19e2055d..61ecde6092 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala @@ -6,8 +6,8 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.ActorRef -import org.apache.pekko.testkit.TestProbe +import edu.ie3.simona.agent.grid.GridAgentMessage.{PMAdapter, VMAdapter} +import org.apache.pekko.actor.typed.ActorRef import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ ProvideGridPowerMessage, @@ -20,6 +20,7 @@ import edu.ie3.simona.ontology.messages.VoltageMessage.{ } import edu.ie3.simona.test.common.UnitSpec import edu.ie3.util.scala.quantities.{Megavars, ReactivePower} +import org.apache.pekko.actor.testkit.typed.scaladsl.TestProbe import squants.Power import squants.electro.Volts import squants.energy.Megawatts @@ -40,36 +41,41 @@ trait DBFSMockGridAgents extends UnitSpec { : squants.electro.ElectricPotential = Volts(1e-6) sealed trait GAActorAndModel { - val gaProbe: TestProbe + val gaProbe: TestProbe[GridAgentMessage] val nodeUuids: Seq[UUID] - def ref: ActorRef = gaProbe.ref + def ref: ActorRef[GridAgentMessage] = gaProbe.ref } final case class InferiorGA( - override val gaProbe: TestProbe, + override val gaProbe: TestProbe[GridAgentMessage], override val nodeUuids: Seq[UUID] ) extends GAActorAndModel { - def expectGridPowerRequest(): ActorRef = { - gaProbe - .expectMsgType[RequestGridPowerMessage] - .nodeUuids should contain allElementsOf nodeUuids + def expectGridPowerRequest(): ActorRef[GridAgentMessage] = { + val message = gaProbe.expectMessageType[GridAgentMessage] - gaProbe.lastSender + message match { + case PMAdapter(requestGridPowerMessage: RequestGridPowerMessage) => + requestGridPowerMessage.nodeUuids should contain allElementsOf nodeUuids + + requestGridPowerMessage.sender + } } def expectSlackVoltageProvision( expectedSweepNo: Int, expectedExchangedVoltages: Seq[ExchangeVoltage] ): Unit = { - inside(gaProbe.expectMsgType[ProvideSlackVoltageMessage]) { - case ProvideSlackVoltageMessage(sweepNo, exchangedVoltages) => - sweepNo shouldBe expectedSweepNo + val message = gaProbe.expectMessageType[GridAgentMessage] + + message match { + case VMAdapter(msg: ProvideSlackVoltageMessage) => + msg.currentSweepNo shouldBe expectedSweepNo - exchangedVoltages.size shouldBe expectedExchangedVoltages.size + msg.nodalSlackVoltages.size shouldBe expectedExchangedVoltages.size expectedExchangedVoltages.foreach { expectedVoltage => - exchangedVoltages.find( + msg.nodalSlackVoltages.find( _.nodeUuid == expectedVoltage.nodeUuid ) match { case Some(ExchangeVoltage(_, actualE, actualF)) => @@ -85,42 +91,51 @@ trait DBFSMockGridAgents extends UnitSpec { } } - def requestSlackVoltage(receiver: ActorRef, sweepNo: Int): Unit = - gaProbe.send( - receiver, - RequestSlackVoltageMessage(sweepNo, nodeUuids) + def requestSlackVoltage( + receiver: ActorRef[GridAgentMessage], + sweepNo: Int + ): Unit = + receiver ! VMAdapter( + RequestSlackVoltageMessage(sweepNo, nodeUuids, gaProbe.ref) ) } final case class SuperiorGA( - override val gaProbe: TestProbe, + override val gaProbe: TestProbe[GridAgentMessage], override val nodeUuids: Seq[UUID] ) extends GAActorAndModel { - def expectSlackVoltageRequest(expectedSweepNo: Int): ActorRef = { - inside( - gaProbe - .expectMsgType[RequestSlackVoltageMessage] - ) { - case RequestSlackVoltageMessage(msgSweepNo: Int, msgUuids: Seq[UUID]) => - msgSweepNo shouldBe expectedSweepNo - msgUuids should have size nodeUuids.size - msgUuids should contain allElementsOf nodeUuids - } + def expectSlackVoltageRequest( + expectedSweepNo: Int + ): ActorRef[GridAgentMessage] = { + val message = gaProbe.expectMessageType[GridAgentMessage] + + message match { + case VMAdapter( + requestSlackVoltageMessage: RequestSlackVoltageMessage + ) => + requestSlackVoltageMessage.currentSweepNo shouldBe expectedSweepNo + requestSlackVoltageMessage.nodeUuids should have size nodeUuids.size + requestSlackVoltageMessage.nodeUuids should contain allElementsOf nodeUuids - gaProbe.lastSender + requestSlackVoltageMessage.sender + } } def expectGridPowerProvision( expectedExchangedPowers: Seq[ExchangePower], maxDuration: FiniteDuration = 30 seconds ): Unit = { - inside(gaProbe.expectMsgType[ProvideGridPowerMessage](maxDuration)) { - case ProvideGridPowerMessage(exchangedPower) => - exchangedPower should have size expectedExchangedPowers.size + val message = gaProbe.expectMessageType[GridAgentMessage](maxDuration) + + message match { + case PMAdapter(msg: ProvideGridPowerMessage) => + msg.nodalResidualPower should have size expectedExchangedPowers.size expectedExchangedPowers.foreach { expectedPower => - exchangedPower.find(_.nodeUuid == expectedPower.nodeUuid) match { + msg.nodalResidualPower.find( + _.nodeUuid == expectedPower.nodeUuid + ) match { case Some(ExchangePower(_, actualP, actualQ)) => (actualP ~= expectedPower.p) shouldBe true (actualQ ~= expectedPower.q) shouldBe true @@ -131,17 +146,15 @@ trait DBFSMockGridAgents extends UnitSpec { ) } } - } } - def requestGridPower(receiver: ActorRef, sweepNo: Int): Unit = { - gaProbe.send( - receiver, - RequestGridPowerMessage( - sweepNo, - nodeUuids - ) + def requestGridPower( + receiver: ActorRef[GridAgentMessage], + sweepNo: Int + ): Unit = { + receiver ! PMAdapter( + RequestGridPowerMessage(sweepNo, nodeUuids, gaProbe.ref) ) } } diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala index e58ad3c2fb..6c7e9ce9be 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala @@ -6,26 +6,32 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.{ - Actor, - ActorIdentity, - ActorRef, - ActorSystem, - Identify, - Props -} -import org.apache.pekko.testkit.ImplicitSender -import org.apache.pekko.util.Timeout -import com.typesafe.config.ConfigFactory import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.grid.GridAgentMessage.StringAdapter import edu.ie3.simona.io.result.ResultSinkType import edu.ie3.simona.sim.setup.SimonaStandaloneSetup +import edu.ie3.simona.test.common.ConfigTestData import edu.ie3.simona.test.common.input.TransformerInputTestData -import edu.ie3.simona.test.common.{ConfigTestData, TestKitWithShutdown} import edu.ie3.simona.util.ResultFileHierarchy import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig +import org.apache.pekko.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit +import org.apache.pekko.actor.typed.receptionist.Receptionist.{ + Listing, + Register, + Subscribe +} +import org.apache.pekko.actor.typed.receptionist.ServiceKey +import org.apache.pekko.actor.typed.scaladsl.AskPattern.Askable +import org.apache.pekko.actor.typed.scaladsl.Behaviors +import org.apache.pekko.actor.typed.scaladsl.adapter.{ + TypedActorContextOps, + TypedActorRefOps +} +import org.apache.pekko.actor.typed.{ActorRef, Scheduler} +import org.apache.pekko.actor.{ActorRef => classicRef} +import org.apache.pekko.util.Timeout import org.scalatest.wordspec.AnyWordSpecLike import java.util.concurrent.TimeUnit @@ -33,17 +39,7 @@ import scala.concurrent.Await import scala.concurrent.duration.Duration class GridAgentSetup2WSpec - extends TestKitWithShutdown( - ActorSystem( - "GridAgentSetupSpec", - ConfigFactory - .parseString(""" - |pekko.loggers =["org.apache.pekko.event.slf4j.Slf4jLogger"] - |pekko.loglevel="OFF" - """.stripMargin) - ) - ) - with ImplicitSender + extends ScalaTestWithActorTestKit with AnyWordSpecLike with TransformerInputTestData with ConfigTestData @@ -52,18 +48,26 @@ class GridAgentSetup2WSpec "The setup of grid agents" must { "provide two grid agents on presence of a two winding transformer" in { - import org.apache.pekko.pattern._ implicit val timeout: Timeout = Timeout(1, TimeUnit.SECONDS) + implicit val scheduler: Scheduler = system.scheduler // in order to get an actor system we need a tmp actor that calls the corresponding method - Await.ready( - system.actorOf(Props(new Actor { - override def receive: Receive = { case "setup" => + val serviceKey = ServiceKey[GridAgentMessage]("gridAgent") + + val actor = testKit.spawn(Behaviors.setup[GridAgentMessage] { ctx => + ctx.system.receptionist ! Register(serviceKey, ctx.self) + + Behaviors.receive[GridAgentMessage] { + case (ctx, StringAdapter("ping", sender)) => + // replying to ping signal + sender ! StringAdapter("pong", ctx.self) + Behaviors.same + case (ctx, StringAdapter("setup", _)) => val environmentRefs = EnvironmentRefs( - scheduler = self, - runtimeEventListener = self, - primaryServiceProxy = self, - weather = ActorRef.noSender, + scheduler = ctx.self.toClassic, + runtimeEventListener = ctx.self.toClassic, + primaryServiceProxy = ctx.self.toClassic, + weather = classicRef.noSender, evDataService = None ) @@ -82,43 +86,45 @@ class GridAgentSetup2WSpec ) ).buildSubGridToActorRefMap( gridContainer.getSubGridTopologyGraph, - context, + ctx.toClassic, environmentRefs, - Seq.empty[ActorRef] + Seq.empty[classicRef] ) - sender() ! "done" - } - })) ? "setup", - Duration(1, TimeUnit.SECONDS) + ctx.self ! StringAdapter("done", ctx.self) + Behaviors.same + } + }) + + Await.ready( + actor.ask[GridAgentMessage](ref => StringAdapter("setup", ref)), + Duration(10, TimeUnit.SECONDS) ) - val sel = system.actorSelection("user/**/GridAgent_*") - sel ! Identify(0) + testKit.spawn(Behaviors.setup[Listing] { ctx => + logger.debug("Subscribing to the actors.") + ctx.system.receptionist ! Subscribe(serviceKey, ctx.self) - logger.debug("Waiting 500 ms to collect all responses") - val responses: Seq[ActorIdentity] = - receiveWhile( - max = Duration.create(500, "ms"), - idle = Duration.create(250, "ms") - ) { case msg: ActorIdentity => - msg - } - logger.debug("All responses received. Evaluating...") + Behaviors.receiveMessagePartial[Listing] { + case serviceKey.Listing(listings) => + logger.debug("All responses received. Evaluating...") - responses.size should be(2) + listings.size should be(2) - val regex = """GridAgent_\d*""".r - val expectedSenders = Vector("GridAgent_1", "GridAgent_2") - val actualSenders = responses - .collect { case actorId: ActorIdentity => - val actorRefString = actorId.getActorRef.toString - regex.findFirstIn(actorRefString) - } - .flatten - .sorted - .toVector + val regex = """GridAgent_\d*""".r + val expectedSenders = Vector("GridAgent_1", "GridAgent_2") + val actualSenders = listings + .collect { case actorId: ActorRef[GridAgentMessage] => + val actorRefString = actorId.toString + regex.findFirstIn(actorRefString) + } + .flatten + .toVector - actualSenders should be(expectedSenders) + actualSenders should be(expectedSenders) + + Behaviors.same + } + }) } } } diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala index f2b2d44f41..19771d39ff 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala @@ -6,29 +6,31 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.{ - Actor, - ActorIdentity, - ActorRef, - ActorSystem, - Identify, - Props -} -import org.apache.pekko.testkit.ImplicitSender -import org.apache.pekko.util.Timeout -import com.typesafe.config.ConfigFactory import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.grid.GridAgentMessage.StringAdapter import edu.ie3.simona.io.result.ResultSinkType import edu.ie3.simona.sim.setup.SimonaStandaloneSetup -import edu.ie3.simona.test.common.{ - ConfigTestData, - TestKitWithShutdown, - ThreeWindingTestData -} +import edu.ie3.simona.test.common.{ConfigTestData, ThreeWindingTestData} import edu.ie3.simona.util.ResultFileHierarchy import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig +import org.apache.pekko.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit +import org.apache.pekko.actor.typed.receptionist.Receptionist.{ + Listing, + Register, + Subscribe +} +import org.apache.pekko.actor.typed.receptionist.ServiceKey +import org.apache.pekko.actor.typed.scaladsl.AskPattern.Askable +import org.apache.pekko.actor.typed.scaladsl.Behaviors +import org.apache.pekko.actor.typed.scaladsl.adapter.{ + TypedActorContextOps, + TypedActorRefOps +} +import org.apache.pekko.actor.typed.{ActorRef, Scheduler} +import org.apache.pekko.actor.{ActorRef => classicRef} +import org.apache.pekko.util.Timeout import org.scalatest.wordspec.AnyWordSpecLike import java.util.concurrent.TimeUnit @@ -36,17 +38,7 @@ import scala.concurrent.Await import scala.concurrent.duration.Duration class GridAgentSetup3WSpec - extends TestKitWithShutdown( - ActorSystem( - "GridAgentSetupSpec", - ConfigFactory - .parseString(""" - |pekko.loggers =["org.apache.pekko.event.slf4j.Slf4jLogger"] - |pekko.loglevel="DEBUG" - """.stripMargin) - ) - ) - with ImplicitSender + extends ScalaTestWithActorTestKit with AnyWordSpecLike with ThreeWindingTestData with ConfigTestData @@ -54,18 +46,27 @@ class GridAgentSetup3WSpec "The setup of grid agents" must { "provide three grid agents on presence of a three winding transformer" in { - import org.apache.pekko.pattern._ implicit val timeout: Timeout = Timeout(1, TimeUnit.SECONDS) + implicit val scheduler: Scheduler = system.scheduler // in order to get an actor system we need a tmp actor that calls the corresponding method - Await.ready( - system.actorOf(Props(new Actor { - override def receive: Receive = { case "setup" => + val serviceKey = ServiceKey[GridAgentMessage]("gridAgent") + + val actor = testKit.spawn(Behaviors.setup[GridAgentMessage] { ctx => + ctx.system.receptionist ! Register(serviceKey, ctx.self) + + Behaviors.receive[GridAgentMessage] { + case (ctx, StringAdapter("ping", sender)) => + // replying to ping signal + sender ! StringAdapter("pong", ctx.self) + Behaviors.same + + case (ctx, StringAdapter("setup", _)) => val environmentRefs = EnvironmentRefs( - scheduler = self, - runtimeEventListener = self, - primaryServiceProxy = self, - weather = ActorRef.noSender, + scheduler = ctx.self.toClassic, + runtimeEventListener = ctx.self.toClassic, + primaryServiceProxy = ctx.self.toClassic, + weather = classicRef.noSender, evDataService = None ) @@ -84,42 +85,45 @@ class GridAgentSetup3WSpec ) ).buildSubGridToActorRefMap( threeWindingTestGrid.getSubGridTopologyGraph, - context, + ctx.toClassic, environmentRefs, - Seq.empty[ActorRef] + Seq.empty[classicRef] ) - sender() ! "done" - } - })) ? "setup", - Duration(1, TimeUnit.SECONDS) + ctx.self ! StringAdapter("done", ctx.self) + Behaviors.same + } + }) + + Await.ready( + actor.ask[GridAgentMessage](ref => StringAdapter("setup", ref)), + Duration(10, TimeUnit.SECONDS) ) - val sel = system.actorSelection("user/**/GridAgent_*") - sel ! Identify(0) + testKit.spawn(Behaviors.setup[Listing] { ctx => + logger.debug("Subscribing to the actors.") + ctx.system.receptionist ! Subscribe(serviceKey, ctx.self) - logger.debug("Waiting 500ms to collect all responses") - val responses: Seq[ActorIdentity] = - receiveWhile( - max = Duration.create(500, "ms"), - idle = Duration.create(250, "ms") - ) { case msg: ActorIdentity => - msg - } - logger.debug("All responses received. Evaluating...") - - responses.size should be(3) - val regex = """GridAgent_\d*""".r - val expectedSenders = Vector("GridAgent_1", "GridAgent_2", "GridAgent_3") - val actualSenders = responses - .collect { case actorId: ActorIdentity => - val actorRefString = actorId.getActorRef.toString - regex.findFirstIn(actorRefString) - } - .flatten - .sorted - .toVector + Behaviors.receiveMessagePartial[Listing] { + case serviceKey.Listing(listings) => + logger.debug("All responses received. Evaluating...") + + listings.size should be(3) + val regex = """GridAgent_\d*""".r + val expectedSenders = + Vector("GridAgent_1", "GridAgent_2", "GridAgent_3") + val actualSenders = listings + .collect { case actorId: ActorRef[GridAgentMessage] => + val actorRefString = actorId.toString + regex.findFirstIn(actorRefString) + } + .flatten + .toVector - actualSenders should be(expectedSenders) + actualSenders should be(expectedSenders) + + Behaviors.same + } + }) } } diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala index c9d17d2379..529b27780c 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridResultsSupportSpec.scala @@ -6,7 +6,6 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.event.{LoggingAdapter, NoLogging} import breeze.math.Complex import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.input.connector.ConnectorPort @@ -61,7 +60,6 @@ class GridResultsSupportSpec with GridInputTestData with TableDrivenPropertyChecks { - override protected val log: LoggingAdapter = NoLogging implicit val currentTolerance: squants.electro.ElectricCurrent = Amperes(1e-6) implicit val angleTolerance: squants.Angle = Degrees(1e-6) diff --git a/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala index 66805b06d9..bf2717d845 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala @@ -6,8 +6,6 @@ package edu.ie3.simona.agent.grid -import org.apache.pekko.actor.ActorRef -import org.apache.pekko.event.{LoggingAdapter, NoLogging} import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower @@ -16,6 +14,12 @@ import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.common.model.grid.BasicGridWithSwitches import edu.ie3.util.quantities.QuantityUtils.RichQuantityDouble import edu.ie3.util.scala.quantities.Megavars +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + ScalaTestWithActorTestKit, + TestProbe +} +import org.apache.pekko.actor.typed.ActorRef +import org.slf4j.{Logger, LoggerFactory} import squants.electro.Kilovolts import squants.energy.Megawatts import tech.units.indriya.ComparableQuantity @@ -31,12 +35,16 @@ import javax.measure.quantity.Angle * order to comprehend the expected test results. */ class PowerFlowSupportSpec - extends UnitSpec + extends ScalaTestWithActorTestKit + with UnitSpec with BasicGridWithSwitches with PowerFlowSupport with GridResultsSupport { - override val log: LoggingAdapter = NoLogging + implicit val log: Logger = + LoggerFactory.getLogger(PowerFlowSupportSpec.super.getClass) + val actorRef: ActorRef[GridAgentMessage] = + TestProbe[GridAgentMessage]("noSender").ref /** Setting voltage at slack node to 110 kV and introducing a load of 1 MW at * node 1 @@ -55,7 +63,7 @@ class PowerFlowSupportSpec ), nodeToReceivedPower = Map( node1.uuid -> Map( - ActorRef.noSender -> Some( + actorRef -> Some( ExchangePower( node1.uuid, Megawatts(1d), @@ -119,7 +127,10 @@ class PowerFlowSupportSpec ) val pfResult = - createResultModels(gridModel, sweepValueStore)(ZonedDateTime.now()) + createResultModels(gridModel, sweepValueStore)( + ZonedDateTime.now(), + log + ) // left/top side segments should have similar currents val loadLinesLeft = @@ -220,7 +231,7 @@ class PowerFlowSupportSpec gridModel.gridComponents.nodes, gridModel.nodeUuidToIndexMap ) - )(ZonedDateTime.now()) + )(ZonedDateTime.now(), log) // left/top side segments (lines that are adjacent to the open switch) should have no load val loadLinesLeft = @@ -305,7 +316,7 @@ class PowerFlowSupportSpec gridModel.gridComponents.nodes, gridModel.nodeUuidToIndexMap ) - )(ZonedDateTime.now()) + )(ZonedDateTime.now(), log) // left/top side segments (lines that are adjacent to the open switch) should have load val expectedLoadLines = diff --git a/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala index e4d9fedf2c..37159c59c9 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala @@ -6,37 +6,35 @@ package edu.ie3.simona.agent.grid -import java.util.UUID - -import org.apache.pekko.actor.{ActorRef, ActorSystem} -import org.apache.pekko.testkit.{TestKit, TestProbe} -import com.typesafe.config.ConfigFactory import edu.ie3.datamodel.graph.SubGridGate -import edu.ie3.simona.test.common.{TestKitWithShutdown, UnitSpec} +import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage +import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.common.model.grid.SubGridGateMokka +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + ScalaTestWithActorTestKit, + TestProbe +} +import org.apache.pekko.actor.typed.ActorRef + +import java.util.UUID class ReceivedValuesStoreSpec - extends TestKitWithShutdown( - ActorSystem( - "ReceivedValuesStoreSpec", - ConfigFactory - .parseString(""" - |pekko.loggers =["org.apache.pekko.event.slf4j.Slf4jLogger"] - |pekko.loglevel="OFF" - """.stripMargin) - ) - ) + extends ScalaTestWithActorTestKit with UnitSpec with SubGridGateMokka { // test actorRefs - val actorProbe1: TestProbe = TestProbe() - val actorProbe2: TestProbe = TestProbe() - val actorProbe3: TestProbe = TestProbe() + val actorProbe1: TestProbe[ParticipantMessage] = + TestProbe[ParticipantMessage]() + val actorProbe2: TestProbe[ParticipantMessage] = + TestProbe[ParticipantMessage]() + val actorProbe3: TestProbe[ParticipantMessage] = + TestProbe[ParticipantMessage]() + val actorProbe4: TestProbe[GridAgentMessage] = TestProbe[GridAgentMessage]() // test data used by almost all tests // / node to asset agents mapping - val nodeToAssetAgentsMap: Map[UUID, Set[ActorRef]] = Map( + val nodeToAssetAgentsMap: Map[UUID, Set[ActorRef[ParticipantMessage]]] = Map( UUID.fromString("dd9a5b54-94bb-4201-9108-2b1b7d689546") -> Set( actorProbe1.ref ), @@ -46,13 +44,14 @@ class ReceivedValuesStoreSpec ) // / subnet gate mapping for inferior grids - val inferiorSubGridGateToActorRefMap: Map[SubGridGate, ActorRef] = Map( + val inferiorSubGridGateToActorRefMap + : Map[SubGridGate, ActorRef[GridAgentMessage]] = Map( build2wSubGridGate( UUID.fromString("5cd55ab5-a7d2-499f-a25f-6dbc3845c5e8"), 1, UUID.fromString("1676360a-c7c4-43a9-a667-90ddfe8a18e6"), 2 - ) -> actorProbe3.ref + ) -> actorProbe4.ref ) // / superior grid nodeUuid vector @@ -64,8 +63,10 @@ class ReceivedValuesStoreSpec "initialize an empty store correctly when everything is empty" in { - val nodeToAssetAgentsMap = Map.empty[UUID, Set[ActorRef]] - val inferiorSubGridGateToActorRefMap = Map.empty[SubGridGate, ActorRef] + val nodeToAssetAgentsMap = + Map.empty[UUID, Set[ActorRef[ParticipantMessage]]] + val inferiorSubGridGateToActorRefMap = + Map.empty[SubGridGate, ActorRef[GridAgentMessage]] val superiorGridNodeUuids = Vector.empty[UUID] val receivedValuesStore = @@ -98,7 +99,7 @@ class ReceivedValuesStoreSpec ) shouldBe Map(actorProbe2.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("5cd55ab5-a7d2-499f-a25f-6dbc3845c5e8") - ) shouldBe Map(actorProbe3.ref -> None) + ) shouldBe Map(actorProbe4.ref -> None) receivedValuesStore.nodeToReceivedSlackVoltage.size shouldBe 1 receivedValuesStore.nodeToReceivedSlackVoltage( @@ -120,7 +121,8 @@ class ReceivedValuesStoreSpec ) ) - val inferiorSubGridGateToActorRefMap = Map.empty[SubGridGate, ActorRef] + val inferiorSubGridGateToActorRefMap = + Map.empty[SubGridGate, ActorRef[GridAgentMessage]] val superiorGridNodeUuids = Vector.empty[UUID] val receivedValuesStore = @@ -167,14 +169,16 @@ class ReceivedValuesStoreSpec ) shouldBe Map(actorProbe2.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("5cd55ab5-a7d2-499f-a25f-6dbc3845c5e8") - ) shouldBe Map(actorProbe3.ref -> None) + ) shouldBe Map(actorProbe4.ref -> None) } "initialize an empty store correctly when only information on the superior grid slack nodes are provided" in { - val nodeToAssetAgentsMap = Map.empty[UUID, Set[ActorRef]] - val inferiorSubGridGateToActorRefMap = Map.empty[SubGridGate, ActorRef] + val nodeToAssetAgentsMap = + Map.empty[UUID, Set[ActorRef[ParticipantMessage]]] + val inferiorSubGridGateToActorRefMap = + Map.empty[SubGridGate, ActorRef[GridAgentMessage]] val superiorGridNodeUuids = Vector( UUID.fromString("baded8c4-b703-4316-b62f-75ffe09c9843"), @@ -202,7 +206,8 @@ class ReceivedValuesStoreSpec "initialize an empty store correctly when only an invalid mapping for asset agents with duplicates is provided" in { - val inferiorSubGridGateToActorRefMap = Map.empty[SubGridGate, ActorRef] + val inferiorSubGridGateToActorRefMap = + Map.empty[SubGridGate, ActorRef[GridAgentMessage]] val superiorGridNodeUuids = Vector.empty[UUID] val receivedValuesStore = diff --git a/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala index 1007da8e77..31ac506a89 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala @@ -9,7 +9,7 @@ package edu.ie3.simona.agent.participant import com.typesafe.config.ConfigFactory import edu.ie3.datamodel.models.input.system.SystemParticipantInput import edu.ie3.datamodel.models.result.system.SystemParticipantResult -import edu.ie3.simona.agent.grid.GridAgent.FinishGridSimulationTrigger +import edu.ie3.simona.agent.grid.GridAgentMessage.FinishGridSimulationTrigger import edu.ie3.simona.agent.participant.data.Data.PrimaryData.ApparentPower import edu.ie3.simona.agent.participant.statedata.ParticipantStateData.ParticipantInitializeStateData import edu.ie3.simona.config.SimonaConfig diff --git a/src/test/scala/edu/ie3/simona/event/NotifierSpec.scala b/src/test/scala/edu/ie3/simona/event/NotifierSpec.scala index a654ec289a..6db51d4b74 100644 --- a/src/test/scala/edu/ie3/simona/event/NotifierSpec.scala +++ b/src/test/scala/edu/ie3/simona/event/NotifierSpec.scala @@ -7,7 +7,13 @@ package edu.ie3.simona.event import java.util.{Calendar, Date} -import org.apache.pekko.actor.{ActorLogging, ActorRef, ActorSystem, Props} +import org.apache.pekko.actor.{ + Actor, + ActorLogging, + ActorRef, + ActorSystem, + Props +} import org.apache.pekko.testkit.ImplicitSender import org.apache.pekko.util.Timeout import com.typesafe.config.ConfigFactory @@ -40,6 +46,7 @@ class NotifierSpec // test listenerActor class NotifierActor(override val listener: Iterable[ActorRef]) extends Notifier + with Actor with ActorLogging { override def preStart(): Unit = { log.debug(s"{} started!", self) diff --git a/src/test/scala/edu/ie3/simona/sim/SimonaSimFailSpec.scala b/src/test/scala/edu/ie3/simona/sim/SimonaSimFailSpec.scala index 27c6c80fae..85049cb148 100644 --- a/src/test/scala/edu/ie3/simona/sim/SimonaSimFailSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/SimonaSimFailSpec.scala @@ -13,13 +13,15 @@ import org.apache.pekko.actor.typed.scaladsl.adapter.{ import org.apache.pekko.actor.{ Actor, ActorContext, - ActorRef, ActorSystem, - Props + Props, + ActorRef => classicRef } +import org.apache.pekko.actor.typed.ActorRef import org.apache.pekko.testkit.{TestActorRef, TestProbe} import com.typesafe.config.ConfigFactory import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.scheduler.TimeAdvancer import edu.ie3.simona.scheduler.TimeAdvancer.StartSimMessage @@ -77,10 +79,10 @@ object SimonaSimFailSpec { timeAdvancer ) ) { - val child: ActorRef = context.actorOf(Props(new Loser)) + val child: classicRef = context.actorOf(Props(new Loser)) context.watch(child) - def getChild: ActorRef = child + def getChild: classicRef = child } class Loser extends Actor { @@ -108,23 +110,23 @@ object SimonaSimFailSpec { override def systemParticipantsListener( context: ActorContext - ): Seq[ActorRef] = Seq.empty[ActorRef] + ): Seq[classicRef] = Seq.empty[classicRef] override def primaryServiceProxy( context: ActorContext, - scheduler: ActorRef - ): ActorRef = + scheduler: classicRef + ): classicRef = TestProbe("primaryService")(actorSystem).ref override def weatherService( context: ActorContext, - scheduler: ActorRef - ): ActorRef = + scheduler: classicRef + ): classicRef = TestProbe("weatherService")(actorSystem).ref override def timeAdvancer( context: ActorContext, - simulation: ActorRef, + simulation: classicRef, runtimeEventListener: org.apache.pekko.actor.typed.ActorRef[ RuntimeEvent ] @@ -136,17 +138,17 @@ object SimonaSimFailSpec { timeAdvancer: org.apache.pekko.actor.typed.ActorRef[ TimeAdvancer.Incoming ] - ): ActorRef = TestProbe("scheduler")(actorSystem).ref + ): classicRef = TestProbe("scheduler")(actorSystem).ref override def gridAgents( context: ActorContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ActorRef] - ): Iterable[ActorRef] = Iterable.empty + systemParticipantListener: Seq[classicRef] + ): Iterable[ActorRef[GridAgentMessage]] = Iterable.empty override def extSimulations( context: ActorContext, - scheduler: ActorRef + scheduler: classicRef ): ExtSimSetupData = ExtSimSetupData(Iterable.empty, Map.empty) } diff --git a/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala b/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala index 93ae23d06b..cf7ee5bdc3 100644 --- a/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala @@ -7,8 +7,7 @@ package edu.ie3.simona.sim.setup import java.util.UUID - -import org.apache.pekko.actor.ActorRef +import org.apache.pekko.actor.typed.ActorRef import org.apache.pekko.testkit.TestException import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.input.connector.{ @@ -19,16 +18,27 @@ import edu.ie3.datamodel.models.input.container.{ JointGridContainer, RawGridElements } +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.common.input.GridInputTestData +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + ScalaTestWithActorTestKit, + TestProbe +} import scala.jdk.CollectionConverters._ -class SetupHelperSpec extends UnitSpec with GridInputTestData { +class SetupHelperSpec + extends ScalaTestWithActorTestKit + with UnitSpec + with GridInputTestData { private final object SetupHelperInstance extends SetupHelper "A setup helper" should { + val actorRef: ActorRef[GridAgentMessage] = + TestProbe[GridAgentMessage]("noSender").ref + "reduce multiple SubGridGates between the same superior and inferior nodes to one unique SubGridGate" in { // build dummy grid with two transformers between the same nodes based on the basic grid input test data @@ -83,7 +93,7 @@ class SetupHelperSpec extends UnitSpec with GridInputTestData { ) val subGridToActorRefMap = - Map(1 -> ActorRef.noSender, 100 -> ActorRef.noSender) + Map(1 -> actorRef, 100 -> actorRef) // subGrid gates should be the same for this case gridModel.getSubGridTopologyGraph.edgesOf( diff --git a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala index 26b6246e42..47e16fd8a7 100644 --- a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala @@ -6,13 +6,19 @@ package edu.ie3.simona.sim.setup -import org.apache.pekko.actor.{ActorContext, ActorRef, ActorSystem} +import org.apache.pekko.actor.{ + ActorContext, + ActorRef => classicRef, + ActorSystem +} +import org.apache.pekko.actor.typed.ActorRef import edu.ie3.datamodel.exceptions.NotImplementedException import edu.ie3.datamodel.models.input.connector.{ ConnectorPort, Transformer3WInput } import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.scheduler.TimeAdvancer import edu.ie3.simona.test.common.UnitSpec @@ -29,48 +35,50 @@ class SimonaSetupSpec extends UnitSpec with SimonaSetup with SubGridGateMokka { override def runtimeEventListener( context: ActorContext - ): org.apache.pekko.actor.typed.ActorRef[RuntimeEvent] = + ): ActorRef[RuntimeEvent] = throw new NotImplementedException("This is a dummy setup") override def systemParticipantsListener( context: ActorContext - ): Seq[ActorRef] = throw new NotImplementedException("This is a dummy setup") + ): Seq[classicRef] = throw new NotImplementedException( + "This is a dummy setup" + ) override def primaryServiceProxy( context: ActorContext, - scheduler: ActorRef - ): ActorRef = + scheduler: classicRef + ): classicRef = throw new NotImplementedException("This is a dummy setup") override def weatherService( context: ActorContext, - scheduler: ActorRef - ): ActorRef = + scheduler: classicRef + ): classicRef = throw new NotImplementedException("This is a dummy setup") override def extSimulations( context: ActorContext, - scheduler: ActorRef + scheduler: classicRef ): ExtSimSetupData = throw new NotImplementedException("This is a dummy setup") override def timeAdvancer( context: ActorContext, - simulation: ActorRef, - runtimeEventListener: org.apache.pekko.actor.typed.ActorRef[RuntimeEvent] - ): org.apache.pekko.actor.typed.ActorRef[TimeAdvancer.Incoming] = + simulation: classicRef, + runtimeEventListener: ActorRef[RuntimeEvent] + ): ActorRef[TimeAdvancer.Incoming] = throw new NotImplementedException("This is a dummy setup") override def scheduler( context: ActorContext, - timeAdvancer: org.apache.pekko.actor.typed.ActorRef[TimeAdvancer.Incoming] - ): ActorRef = throw new NotImplementedException("This is a dummy setup") + timeAdvancer: ActorRef[TimeAdvancer.Incoming] + ): classicRef = throw new NotImplementedException("This is a dummy setup") override def gridAgents( context: ActorContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ActorRef] - ): Iterable[ActorRef] = + systemParticipantListener: Seq[classicRef] + ): Iterable[ActorRef[GridAgentMessage]] = throw new NotImplementedException("This is a dummy setup") "Attempting to modify a sub grid gate" should { From b00c1e12b88a3e2c73ec605153dde548f5123659 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 9 Feb 2024 09:40:43 +0100 Subject: [PATCH 064/123] convert to squants --- .../control/TransformerControlGroup.scala | 11 ++++------ .../edu/ie3/simona/model/grid/GridModel.scala | 20 +++++++------------ .../control/TransformerControlGroupSpec.scala | 13 ++++-------- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala index bf9bc582b8..4f04a31951 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala @@ -10,10 +10,9 @@ import breeze.math.Complex import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult import edu.ie3.simona.model.control.TransformerControlGroup.RegulationCriterion -import tech.units.indriya.ComparableQuantity import java.util.UUID -import javax.measure.quantity.Dimensionless +import squants.Dimensionless /** Business logic for a transformer control group. It's main purpose is to * determine, if there is any regulation need and if yes, to what extent (here: @@ -28,9 +27,7 @@ import javax.measure.quantity.Dimensionless */ final case class TransformerControlGroup( nodalRegulationCriterion: Map[UUID, RegulationCriterion], - harmonizeRegulationNeeds: Array[ - ComparableQuantity[Dimensionless] - ] => Option[ComparableQuantity[Dimensionless]] + harmonizeRegulationNeeds: Array[Dimensionless] => Option[Dimensionless] ) { /** Based on the given successful power flow result, determine the difference @@ -48,7 +45,7 @@ final case class TransformerControlGroup( def determineRegulationNeed( result: SuccessFullPowerFlowResult, uuidToIndex: Map[UUID, Int] - ): Option[ComparableQuantity[Dimensionless]] = { + ): Option[Dimensionless] = { val regulationNeeds = result.nodeData.flatMap { case StateData(resultNodeIndex, _, voltage, _) => /* Find possible matching criterion and evaluate it */ @@ -71,5 +68,5 @@ final case class TransformerControlGroup( object TransformerControlGroup { type RegulationCriterion = - Complex => Option[ComparableQuantity[Dimensionless]] + Complex => Option[Dimensionless] } diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 8dbb1a4424..ff85c720c8 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -27,21 +27,19 @@ import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseC } import edu.ie3.simona.util.CollectionUtils -import edu.ie3.util.quantities.PowerSystemUnits import org.jgrapht.Graph import org.jgrapht.alg.connectivity.ConnectivityInspector import org.jgrapht.graph.{DefaultEdge, SimpleGraph} -import tech.units.indriya.ComparableQuantity -import tech.units.indriya.quantity.Quantities import edu.ie3.simona.model.control.{ TransformerControlGroup => ControlGroupModel } import java.time.ZonedDateTime import java.util.UUID -import javax.measure.quantity.Dimensionless import scala.collection.immutable.ListSet import scala.jdk.CollectionConverters._ +import squants.Each +import squants.Dimensionless /** Representation of one physical electrical grid. It holds the references to * nodes, lines, switches and transformers and fundamental properties (like @@ -693,22 +691,18 @@ case object GridModel { val vMag = complexVoltage.abs vMag match { case mag if mag > vMax => - Some(vMax - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + Some(vMax - mag).map(Each(_)) case mag if mag < vMin => - Some(vMin - mag).map(Quantities.getQuantity(_, PowerSystemUnits.PU)) + Some(vMin - mag).map(Each(_)) case _ => None } } }.toMap val harmonizationFunction = - (regulationRequests: Array[ComparableQuantity[Dimensionless]]) => { - val negativeRequests = regulationRequests.filter( - _.isLessThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) - val positiveRequests = regulationRequests.filter( - _.isGreaterThan(Quantities.getQuantity(0d, PowerSystemUnits.PU)) - ) + (regulationRequests: Array[Dimensionless]) => { + val negativeRequests = regulationRequests.filter(_ < Each(0d)) + val positiveRequests = regulationRequests.filter(_ > Each(0d)) (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { case (true, true) => diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala index 8def596ce6..93725fe473 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala @@ -14,8 +14,7 @@ import edu.ie3.powerflow.model.enums.NodeType import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.matchers.QuantityMatchers -import edu.ie3.util.quantities.PowerSystemUnits -import tech.units.indriya.quantity.Quantities +import squants.{Dimensionless, Each} import java.util.UUID @@ -24,7 +23,7 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { val buildTransformerControlModels = PrivateMethod[TransformerControlGroup]( Symbol("buildTransformerControlModels") ) - + implicit val tolerance: Dimensionless = Each(1e-10) val dut = GridModel invokePrivate buildTransformerControlModels( Set( UUID.fromString( @@ -100,9 +99,7 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { actual match { case Some(regulationNeed) => - regulationNeed should equalWithTolerance( - Quantities.getQuantity(0.05, PowerSystemUnits.PU) - ) + regulationNeed should approximate(Each(0.05)) case None => fail("Did expect to receive a regulation need.") } } @@ -122,9 +119,7 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { actual match { case Some(regulationNeed) => - regulationNeed should equalWithTolerance( - Quantities.getQuantity(-0.05, PowerSystemUnits.PU) - ) + regulationNeed should approximate(Each(-0.05)) case None => fail("Did expect to receive a regulation need.") } } From e752b58bd9805441bd74e1d41dc8c5e043bbb971 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 9 Feb 2024 10:40:55 +0100 Subject: [PATCH 065/123] merge ConfigFailFast from #90 --- .../ie3/simona/config/ConfigFailFast.scala | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala index b4dfa1414a..d14d9a7c78 100644 --- a/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala +++ b/src/main/scala/edu/ie3/simona/config/ConfigFailFast.scala @@ -601,35 +601,46 @@ case object ConfigFailFast extends LazyLogging { * * One important check cannot be performed at this place, as input data is * not available, yet: Do the measurements belong to a region, that can be - * influenced by the transformer? + * influenced by the transformer? This is partly addressed in + * [[edu.ie3.simona.agent.grid.GridAgentFailFast]] * * @param transformerControlGroup * Transformer control group definition */ private def checkTransformerControl( transformerControlGroup: TransformerControlGroup - ): Unit = transformerControlGroup match { - case TransformerControlGroup(measurements, transformers, vMax, vMin) => - if (measurements.isEmpty) - throw new InvalidConfigParameterException( - "A transformer control group cannot have no measurements assigned." - ) - if (transformers.isEmpty) - throw new InvalidConfigParameterException( - "A transformer control group cannot have no transformers assigned." - ) - if (vMin < 0) - throw new InvalidConfigParameterException( - "The minimum permissible voltage magnitude of a transformer control group has to be positive." - ) - if (vMax < 0) - throw new InvalidConfigParameterException( - "The maximum permissible voltage magnitude of a transformer control group has to be positive." - ) - if (vMax < vMin) - throw new InvalidConfigParameterException( - "The minimum permissible voltage magnitude of a transformer control group must be smaller than the maximum permissible voltage magnitude." - ) + ): Unit = { + val lowerBoundary = 0.8 + val upperBoundary = 1.2 + transformerControlGroup match { + case TransformerControlGroup(measurements, transformers, vMax, vMin) => + if (measurements.isEmpty) + throw new InvalidConfigParameterException( + s"A transformer control group (${transformerControlGroup.toString}) cannot have no measurements assigned." + ) + if (transformers.isEmpty) + throw new InvalidConfigParameterException( + s"A transformer control group (${transformerControlGroup.toString}) cannot have no transformers assigned." + ) + if (vMin < 0) + throw new InvalidConfigParameterException( + "The minimum permissible voltage magnitude of a transformer control group has to be positive." + ) + if (vMax < vMin) + throw new InvalidConfigParameterException( + s"The minimum permissible voltage magnitude of a transformer control group (${transformerControlGroup.toString}) must be smaller than the maximum permissible voltage magnitude." + ) + if (vMin < lowerBoundary) + throw new InvalidConfigParameterException( + s"A control group (${transformerControlGroup.toString}) which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMin is lower than the lower boundary (0.8 of nominal Voltage)!" + ) + if (vMax > upperBoundary) + throw new InvalidConfigParameterException( + s"A control group (${transformerControlGroup.toString}) which control boundaries exceed the limit of +- 20% of nominal voltage! This may be caused " + + s"by invalid parametrization of one control groups where vMax is higher than the upper boundary (1.2 of nominal Voltage)!" + ) + } } /** Check the default config From eaa4affd7d56419a30231faf0175db198544e71f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 9 Feb 2024 10:53:43 +0100 Subject: [PATCH 066/123] fix imports --- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index c24633a320..75bd056b65 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -36,8 +36,7 @@ import java.time.ZonedDateTime import java.util.UUID import scala.collection.immutable.ListSet import scala.jdk.CollectionConverters._ -import squants.Each -import squants.Dimensionless + /** Representation of one physical electrical grid. It holds the references to * nodes, lines, switches and transformers and fundamental properties (like From dc30f7a6dc4faca2f64b8dce67adc6c9425cd587 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 9 Feb 2024 11:25:23 +0100 Subject: [PATCH 067/123] fmt --- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 75bd056b65..3342809985 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -37,7 +37,6 @@ import java.util.UUID import scala.collection.immutable.ListSet import scala.jdk.CollectionConverters._ - /** Representation of one physical electrical grid. It holds the references to * nodes, lines, switches and transformers and fundamental properties (like * nominal voltage etc.). From e3a41d4837610c0f748a0ef05262973627afa9cd Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 13 Feb 2024 09:04:06 +0100 Subject: [PATCH 068/123] fmt --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 2 +- .../simona/agent/grid/GridAgentFailFast.scala | 6 ++-- .../edu/ie3/simona/config/SimonaConfig.scala | 18 +++++----- .../control/TransformerControlGroup.scala | 4 +-- .../edu/ie3/simona/model/grid/GridModel.scala | 18 +++++----- .../simona/config/ConfigFailFastSpec.scala | 12 +++---- .../control/TransformerControlGroupSpec.scala | 22 ++++++------ .../edu/ie3/simona/model/grid/GridSpec.scala | 34 +++++++++---------- .../model/grid/BasicGridWithSwitches.scala | 4 +-- 9 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 22dc8eb5b6..d25f28d1bc 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -187,7 +187,7 @@ class GridAgent( .toZonedDateTime(simonaConfig.simona.time.startDateTime), TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.endDateTime - ) + ), simonaConfig.simona.control, ) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala index 27d8d216c8..4e45a97cb7 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala @@ -25,7 +25,7 @@ object GridAgentFailFast { */ def failFast( gridAgentInitData: GridAgentInitData, - simonaConfig: SimonaConfig + simonaConfig: SimonaConfig, ): Unit = { /** Check if there is InitData for superior or inferior GridGates @@ -43,7 +43,7 @@ object GridAgentFailFast { checkControlGroupsForMeasurement( gridAgentInitData.subGridContainer, - simonaConfig.simona.control + simonaConfig.simona.control, ) } @@ -58,7 +58,7 @@ object GridAgentFailFast { */ def checkControlGroupsForMeasurement( subGridContainer: SubGridContainer, - maybeControlConfig: Option[SimonaConfig.Simona.Control] + maybeControlConfig: Option[SimonaConfig.Simona.Control], ): Unit = { val measurementUnits = diff --git a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala index 79ada26af1..f5dd2fdf3b 100644 --- a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala +++ b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala @@ -756,13 +756,13 @@ object SimonaConfig { measurements: scala.List[java.lang.String], transformers: scala.List[java.lang.String], vMax: scala.Double, - vMin: scala.Double + vMin: scala.Double, ) object TransformerControlGroup { def apply( c: com.typesafe.config.Config, parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator + $tsCfgValidator: $TsCfgValidator, ): SimonaConfig.TransformerControlGroup = { SimonaConfig.TransformerControlGroup( measurements = @@ -770,14 +770,14 @@ object SimonaConfig { transformers = $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), - vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator) + vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator), ) } private def $_reqDbl( parentPath: java.lang.String, c: com.typesafe.config.Config, path: java.lang.String, - $tsCfgValidator: $TsCfgValidator + $tsCfgValidator: $TsCfgValidator, ): scala.Double = { if (c == null) 0 else @@ -953,20 +953,20 @@ object SimonaConfig { def apply( c: com.typesafe.config.Config, parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator + $tsCfgValidator: $TsCfgValidator, ): SimonaConfig.Simona.Control = { SimonaConfig.Simona.Control( transformer = $_LSimonaConfig_TransformerControlGroup( c.getList("transformer"), parentPath, - $tsCfgValidator + $tsCfgValidator, ) ) } private def $_LSimonaConfig_TransformerControlGroup( cl: com.typesafe.config.ConfigList, parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator + $tsCfgValidator: $TsCfgValidator, ): scala.List[SimonaConfig.TransformerControlGroup] = { import scala.jdk.CollectionConverters._ cl.asScala @@ -974,7 +974,7 @@ object SimonaConfig { SimonaConfig.TransformerControlGroup( cv.asInstanceOf[com.typesafe.config.ConfigObject].toConfig, parentPath, - $tsCfgValidator + $tsCfgValidator, ) ) .toList @@ -2666,7 +2666,7 @@ object SimonaConfig { SimonaConfig.Simona.Control( c.getConfig("control"), parentPath + "control.", - $tsCfgValidator + $tsCfgValidator, ) ) else None, diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala index 4f04a31951..3db869c582 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala @@ -27,7 +27,7 @@ import squants.Dimensionless */ final case class TransformerControlGroup( nodalRegulationCriterion: Map[UUID, RegulationCriterion], - harmonizeRegulationNeeds: Array[Dimensionless] => Option[Dimensionless] + harmonizeRegulationNeeds: Array[Dimensionless] => Option[Dimensionless], ) { /** Based on the given successful power flow result, determine the difference @@ -44,7 +44,7 @@ final case class TransformerControlGroup( */ def determineRegulationNeed( result: SuccessFullPowerFlowResult, - uuidToIndex: Map[UUID, Int] + uuidToIndex: Map[UUID, Int], ): Option[Dimensionless] = { val regulationNeeds = result.nodeData.flatMap { case StateData(resultNodeIndex, _, voltage, _) => diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 0b698d6647..4d20f3316f 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -74,13 +74,13 @@ case object GridModel { refSystem: RefSystem, startDate: ZonedDateTime, endDate: ZonedDateTime, - controlConfig: Option[SimonaConfig.Simona.Control] + controlConfig: Option[SimonaConfig.Simona.Control], ): GridModel = buildAndValidate( subGridContainer, refSystem, startDate, endDate, - controlConfig + controlConfig, ) /** structure that represents all grid components that are needed by a grid @@ -569,7 +569,7 @@ case object GridModel { .map { controlConfig => buildTransformerControlGroups( controlConfig.transformer, - subGridContainer.getRawGrid.getMeasurementUnits + subGridContainer.getRawGrid.getMeasurementUnits, ) } .getOrElse(Set.empty[ControlGroupModel]) @@ -582,7 +582,7 @@ case object GridModel { subGridContainer.getSubnet, refSystem, gridComponents, - gridControls + gridControls, ) // validate @@ -604,14 +604,14 @@ case object GridModel { */ private def buildTransformerControlGroups( config: List[SimonaConfig.TransformerControlGroup], - measurementUnitInput: java.util.Set[MeasurementUnitInput] + measurementUnitInput: java.util.Set[MeasurementUnitInput], ): Set[ControlGroupModel] = config.map { case TransformerControlGroup(measurements, _, vMax, vMin) => buildTransformerControlGroupModel( measurementUnitInput, measurements, vMax, - vMin + vMin, ) }.toSet @@ -635,7 +635,7 @@ case object GridModel { measurementUnitInput: java.util.Set[MeasurementUnitInput], measurementConfigs: List[String], vMax: Double, - vMin: Double + vMin: Double, ): ControlGroupModel = { val nodeUuids = determineNodeUuids(measurementUnitInput, measurementConfigs) @@ -654,7 +654,7 @@ case object GridModel { */ private def determineNodeUuids( measurementUnitInput: java.util.Set[MeasurementUnitInput], - measurementConfigs: List[String] + measurementConfigs: List[String], ): Set[UUID] = Set.from( measurementUnitInput.asScala .filter(input => @@ -679,7 +679,7 @@ case object GridModel { private def buildTransformerControlModels( nodeUuids: Set[UUID], vMax: Double, - vMin: Double + vMin: Double, ): ControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 368e570572..515bba93bc 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -15,7 +15,7 @@ import edu.ie3.simona.config.SimonaConfig.Simona.{Powerflow, Time} import edu.ie3.simona.config.SimonaConfig.{ BaseCsvParams, ResultKafkaParams, - TransformerControlGroup + TransformerControlGroup, } import edu.ie3.simona.exceptions.InvalidConfigParameterException import edu.ie3.simona.test.common.{ConfigTestData, UnitSpec} @@ -964,7 +964,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { List.empty[String], List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), 1.02, - 0.98 + 0.98, ) intercept[InvalidConfigParameterException] { @@ -977,7 +977,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { List("6888c53a-7629-4563-ac8e-840f80b03106"), List.empty[String], 1.02, - 0.98 + 0.98, ) intercept[InvalidConfigParameterException] { @@ -990,7 +990,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { List("6888c53a-7629-4563-ac8e-840f80b03106"), List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), 0.98, - 1.02 + 1.02, ) intercept[InvalidConfigParameterException] { @@ -1003,7 +1003,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { List("6888c53a-7629-4563-ac8e-840f80b03106"), List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), 1.02, - 0.79 + 0.79, ) intercept[InvalidConfigParameterException] { @@ -1017,7 +1017,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { List("6888c53a-7629-4563-ac8e-840f80b03106"), List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), 1.21, - 0.98 + 0.98, ) intercept[InvalidConfigParameterException] { diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala index 07d6515338..2d6c6adbf6 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala @@ -35,10 +35,10 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { ), UUID.fromString( "324f49e5-1c35-4c49-afb1-3cf41696bf93" - ) + ), ), 1.1, - 0.9 + 0.9, ) val uuidToIndex = Map( @@ -50,7 +50,7 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { ) -> 1, UUID.fromString( "324f49e5-1c35-4c49-afb1-3cf41696bf93" - ) -> 2 + ) -> 2, ) "return no regulation need, if everything is fine" in { @@ -59,9 +59,9 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { Array( StateData(0, NodeType.SL, Complex.one, Complex.zero), StateData(1, NodeType.PQ, Complex.one, Complex.zero), - StateData(2, NodeType.PQ, Complex.one, Complex.zero) + StateData(2, NodeType.PQ, Complex.one, Complex.zero), ), - DenseMatrix.zeros(1, 1) + DenseMatrix.zeros(1, 1), ) val actual = dut.determineRegulationNeed(result, uuidToIndex) @@ -75,9 +75,9 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { Array( StateData(0, NodeType.SL, Complex.one, Complex.zero), StateData(1, NodeType.PQ, Complex.one * 0.88, Complex.zero), - StateData(2, NodeType.PQ, Complex.one * 1.11, Complex.zero) + StateData(2, NodeType.PQ, Complex.one * 1.11, Complex.zero), ), - DenseMatrix.zeros(1, 1) + DenseMatrix.zeros(1, 1), ) val actual = dut.determineRegulationNeed(result, uuidToIndex) @@ -91,9 +91,9 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { Array( StateData(0, NodeType.SL, Complex.one, Complex.zero), StateData(1, NodeType.PQ, Complex.one * 0.85, Complex.zero), - StateData(2, NodeType.PQ, Complex.one * 0.88, Complex.zero) + StateData(2, NodeType.PQ, Complex.one * 0.88, Complex.zero), ), - DenseMatrix.zeros(1, 1) + DenseMatrix.zeros(1, 1), ) val actual = dut.determineRegulationNeed(result, uuidToIndex) @@ -111,9 +111,9 @@ class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { Array( StateData(0, NodeType.SL, Complex.one, Complex.zero), StateData(1, NodeType.PQ, Complex.one * 1.15, Complex.zero), - StateData(2, NodeType.PQ, Complex.one * 1.11, Complex.zero) + StateData(2, NodeType.PQ, Complex.one * 1.11, Complex.zero), ), - DenseMatrix.zeros(1, 1) + DenseMatrix.zeros(1, 1), ) val actual = dut.determineRegulationNeed(result, uuidToIndex) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 73c36a8470..b13da303ec 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -18,7 +18,7 @@ import edu.ie3.simona.model.control.TransformerControlGroup import edu.ie3.simona.model.grid.GridModel.{ emptyGridControls, GridComponents, - GridControls + GridControls, } import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} import edu.ie3.simona.test.common.model.grid.{ @@ -212,7 +212,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { lines, Set(transformer2wModel), Set.empty[Transformer3wModel], - switches + switches, ), GridControls(Set.empty[TransformerControlGroup]), ) @@ -241,7 +241,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { adaptedLines, Set(transformer2wModel), Set.empty[Transformer3wModel], - Set.empty[SwitchModel] + Set.empty[SwitchModel], ), GridControls(Set.empty[TransformerControlGroup]), ) @@ -287,7 +287,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { lines, Set(transformer2wModel), Set.empty[Transformer3wModel], - switches + switches, ), emptyGridControls, ) @@ -392,7 +392,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { lines, Set(transformer2wModel), Set.empty[Transformer3wModel], - switches + switches, ), GridControls(Set.empty[TransformerControlGroup]), ) @@ -444,7 +444,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { lines, Set(transformer2wModel), Set.empty[Transformer3wModel], - Set.empty[SwitchModel] + Set.empty[SwitchModel], ), GridControls(Set.empty[TransformerControlGroup]), ) @@ -480,22 +480,22 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { val node0 = TestObjectFactory.buildNodeInput( false, GermanVoltageLevelUtils.MV_10KV, - 1 + 1, ) val node1 = TestObjectFactory.buildNodeInput( false, GermanVoltageLevelUtils.MV_10KV, - 1 + 1, ) val node2 = TestObjectFactory.buildNodeInput( false, GermanVoltageLevelUtils.MV_10KV, - 1 + 1, ) val node3 = TestObjectFactory.buildNodeInput( false, GermanVoltageLevelUtils.MV_10KV, - 1 + 1, ) val measurementUnits = Set( @@ -506,7 +506,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { true, false, false, - false + false, ), new MeasurementUnitInput( UUID.fromString("ab66fbb0-ece1-44b9-9341-86a884233ec4"), @@ -515,7 +515,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { true, false, false, - false + false, ), new MeasurementUnitInput( UUID.fromString("93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d"), @@ -524,7 +524,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { true, false, false, - false + false, ), new MeasurementUnitInput( UUID.fromString("8e84eb8a-2940-4900-b0ce-0eeb6bca8bae"), @@ -533,19 +533,19 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { false, false, false, - false - ) + false, + ), ).asJava val selectedMeasurements = List( "ab66fbb0-ece1-44b9-9341-86a884233ec4", "93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d", - "8e84eb8a-2940-4900-b0ce-0eeb6bca8bae" + "8e84eb8a-2940-4900-b0ce-0eeb6bca8bae", ) val expectedUuids = Set(node1, node2).map(_.getUuid) val actual = GridModel invokePrivate determineNodeUuids( measurementUnits, - selectedMeasurements + selectedMeasurements, ) actual should contain theSameElementsAs expectedUuids } diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index 2660fffab6..5a03235762 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -9,7 +9,7 @@ package edu.ie3.simona.test.common.model.grid import edu.ie3.simona.model.grid.GridModel.{ emptyGridControls, GridComponents, - GridControls + GridControls, } import edu.ie3.simona.model.grid.{ GridModel, @@ -234,7 +234,7 @@ trait BasicGridWithSwitches extends BasicGrid { Set.empty[Transformer3wModel], gridSwitches, ), - emptyGridControls + emptyGridControls, ) } From 82922d7c43491cb620e5717434beabc4ed81af6a Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 14 Feb 2024 10:15:53 +0100 Subject: [PATCH 069/123] Minor things --- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 4d20f3316f..5c190e7f74 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -26,7 +26,6 @@ import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseC, } import edu.ie3.simona.util.CollectionUtils - import org.jgrapht.Graph import org.jgrapht.alg.connectivity.ConnectivityInspector import org.jgrapht.graph.{DefaultEdge, SimpleGraph} @@ -67,7 +66,7 @@ final case class GridModel( def nodeUuidToIndexMap: Map[UUID, Int] = _nodeUuidToIndexMap } -case object GridModel { +object GridModel { def apply( subGridContainer: SubGridContainer, From c10e0f68f9513d62b1c371b30a8a69c6f9680f4d Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 14 Feb 2024 14:21:22 +0100 Subject: [PATCH 070/123] Improving implementation. --- .../ie3/simona/actor/SimonaActorNaming.scala | 10 +- .../ie3/simona/agent/EnvironmentRefs.scala | 15 +- .../ie3/simona/agent/grid/DBFSAlgorithm.scala | 232 ++++++++++++------ .../edu/ie3/simona/agent/grid/GridAgent.scala | 138 ++++------- .../ie3/simona/agent/grid/GridAgentData.scala | 43 +++- .../simona/agent/grid/GridAgentMessage.scala | 32 +-- .../simona/agent/grid/PowerFlowSupport.scala | 2 +- .../simona/agent/grid/ReceivedValues.scala | 13 +- .../agent/grid/ReceivedValuesStore.scala | 2 +- .../grid}/VoltageMessage.scala | 10 +- .../scala/edu/ie3/simona/sim/SimonaSim.scala | 10 +- .../sim/setup/SimonaStandaloneSetup.scala | 44 ++-- .../agent/grid/DBFSAlgorithmCenGridSpec.scala | 85 ++++--- .../DBFSAlgorithmFailedPowerFlowSpec.scala | 49 ++-- .../grid/DBFSAlgorithmParticipantSpec.scala | 61 +++-- .../agent/grid/DBFSAlgorithmSupGridSpec.scala | 33 +-- .../agent/grid/DBFSMockGridAgents.scala | 48 ++-- .../agent/grid/GridAgentSetup2WSpec.scala | 59 +++-- .../agent/grid/GridAgentSetup3WSpec.scala | 63 +++-- .../agent/grid/PowerFlowSupportSpec.scala | 5 +- .../agent/grid/ReceivedValuesStoreSpec.scala | 42 ++-- .../simona/sim/setup/SimonaSetupSpec.scala | 22 +- 22 files changed, 534 insertions(+), 484 deletions(-) rename src/main/scala/edu/ie3/simona/{ontology/messages => agent/grid}/VoltageMessage.scala (88%) diff --git a/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala b/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala index 04a2dbff60..0b4686d781 100644 --- a/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala +++ b/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala @@ -7,7 +7,7 @@ package edu.ie3.simona.actor import org.apache.pekko.actor.typed.ActorRef -import org.apache.pekko.actor.{ActorRefFactory, Props, ActorRef => classicRef} +import org.apache.pekko.actor.{ActorRefFactory, Props, ActorRef => ClassicRef} import java.util.UUID @@ -16,10 +16,10 @@ object SimonaActorNaming { implicit class RichActorRefFactory(private val refFactory: ActorRefFactory) extends AnyVal { - def simonaActorOf(props: Props, actorId: String): classicRef = + def simonaActorOf(props: Props, actorId: String): ClassicRef = refFactory.actorOf(props, actorName(props, actorId)) - def simonaActorOf(props: Props): classicRef = + def simonaActorOf(props: Props): ClassicRef = refFactory.actorOf(props, actorName(props, simonaActorUuid)) } @@ -63,13 +63,13 @@ object SimonaActorNaming { def actorName(typeName: String, actorId: String): String = s"${typeName}_${cleanActorIdForPekko(actorId)}" - /** Extracts the actor name from given [[classicRef]]. Cluster singletons are + /** Extracts the actor name from given [[ClassicRef]]. Cluster singletons are * taken care of separately. * * @return * the actor name extract from the ActorRef */ - def actorName(actorRef: classicRef): String = + def actorName(actorRef: ClassicRef): String = actorRef.path.name match { case "singleton" => // singletons end in /${actorName}/singleton diff --git a/src/main/scala/edu/ie3/simona/agent/EnvironmentRefs.scala b/src/main/scala/edu/ie3/simona/agent/EnvironmentRefs.scala index 2179b90202..c9476136e4 100644 --- a/src/main/scala/edu/ie3/simona/agent/EnvironmentRefs.scala +++ b/src/main/scala/edu/ie3/simona/agent/EnvironmentRefs.scala @@ -6,7 +6,10 @@ package edu.ie3.simona.agent -import org.apache.pekko.actor.ActorRef +import edu.ie3.simona.event.RuntimeEvent +import edu.ie3.simona.scheduler.TimeAdvancer.Incoming +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.{ActorRef => ClassicRef} /** Container class, that gather together reference to relevant entities, that * represent the environment in the simulation @@ -23,9 +26,9 @@ import org.apache.pekko.actor.ActorRef * Reference to the EV data service, if existing */ final case class EnvironmentRefs( - scheduler: ActorRef, - runtimeEventListener: ActorRef, - primaryServiceProxy: ActorRef, - weather: ActorRef, - evDataService: Option[ActorRef], + scheduler: ClassicRef, + runtimeEventListener: ActorRef[RuntimeEvent], + primaryServiceProxy: ClassicRef, + weather: ClassicRef, + evDataService: Option[ClassicRef], ) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala index d214a256ad..8e203c7b11 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -17,30 +17,34 @@ import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidN import edu.ie3.powerflow.model.enums.NodeType import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentBaseData, + GridAgentValues, PowerFlowDoneData, } import edu.ie3.simona.agent.grid.GridAgentMessage._ import edu.ie3.simona.agent.grid.ReceivedValues._ +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.agent.grid.VoltageMessage.{ + ProvideSlackVoltageMessage, + RequestSlackVoltageMessage, +} import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.event.RuntimeEvent.PowerFlowFailed import edu.ie3.simona.exceptions.agent.DBFSAlgorithmException import edu.ie3.simona.model.grid.{NodeModel, RefSystem} -import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage._ import edu.ie3.simona.ontology.messages.SchedulerMessage.Completion -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage -import edu.ie3.simona.ontology.messages.VoltageMessage.{ - ProvideSlackVoltageMessage, - RequestSlackVoltageMessage, -} +import edu.ie3.simona.ontology.messages.{Activation, StopMessage} import edu.ie3.simona.util.TickUtil.TickLong import edu.ie3.util.scala.quantities.Megavars import edu.ie3.util.scala.quantities.SquantsUtils.RichElectricPotential import org.apache.pekko.actor.typed.scaladsl.AskPattern._ import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps -import org.apache.pekko.actor.typed.scaladsl.{ActorContext, Behaviors} +import org.apache.pekko.actor.typed.scaladsl.{ + ActorContext, + Behaviors, + StashBuffer, +} import org.apache.pekko.actor.typed.{ActorRef, Behavior, Scheduler} -import org.apache.pekko.actor.{ActorRef => classicRef} import org.apache.pekko.pattern.ask import org.apache.pekko.util.{Timeout => PekkoTimeout} import org.slf4j.Logger @@ -57,7 +61,51 @@ import scala.util.{Failure, Success} * the standard behaviour of a [[GridAgent]]. */ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { - this: GridAgent => + + /** Method that defines the idle [[Behavior]] of the agent. + * @param gridAgentBaseData + * state data of the actor + * @param values + * immutable [[GridAgent]] values + * @param buffer + * for [[GridAgentMessage]]s + * @return + * a [[Behavior]] + */ + protected def idle( + gridAgentBaseData: GridAgentBaseData + )(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], + ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + case (_, pm: WrappedPowerMessage) => + // needs to be set here to handle if the messages arrive too early + // before a transition to GridAgentBehaviour took place + buffer.stash(pm) + Behaviors.same + + case (_, WrappedActivation(activation: Activation)) => + values.environmentRefs.scheduler ! Completion( + values.activationAdapter, + Some(activation.tick), + ) + buffer.unstashAll(simulateGrid(gridAgentBaseData, activation.tick)) + + case (ctx, WrappedResultMessage(StopMessage(_))) => + // shutdown children + gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => + actors.foreach(a => ctx.stop(a)) + } + + // we are done + Behaviors.stopped + + case (_, StopGridAgent) => + Behaviors.stopped + + case _ => + Behaviors.unhandled + } /** Method that defines the [[Behavior]] for simulating the grid. * @param gridAgentData @@ -67,16 +115,19 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * @return * a [[Behavior]] */ - protected def simulateGrid( + private def simulateGrid( gridAgentData: GridAgentData, currentTick: Long, + )(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { (ctx, message) => (message, gridAgentData) match { // first part of the grid simulation, same for all gridAgents on all levels // we start with a forward-sweep by requesting the data from our child assets and grids (if any) case ( - ActivationAdapter(activation: Activation), + WrappedActivation(activation: Activation), gridAgentBaseData: GridAgentBaseData, ) => ctx.log.debug( @@ -116,7 +167,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // if we receive power values as response on our request, we process them here case ( - ValuesAdapter(receivedValues: ReceivedValues), + receivedValues: ReceivedValues, gridAgentBaseData: GridAgentBaseData, ) => // we just received either all provided slack voltage values or all provided power values @@ -158,24 +209,22 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { updatedGridAgentBaseData, currentTick, simulateGrid, - )(ctx) + )(ctx, values, buffer) } else { goToPowerFlowCalculationOrStay( allValuesReceived, updatedGridAgentBaseData, currentTick, simulateGrid, - )(ctx) + )(ctx, values, buffer) } // if we receive a request for slack voltages from our inferior grids we want to answer it case ( - VMAdapter( - RequestSlackVoltageMessage( - currentSweepNo, - nodeUuids, - sender: ActorRef[GridAgentMessage], - ) + RequestSlackVoltageMessage( + currentSweepNo, + nodeUuids, + sender: ActorRef[GridAgentMessage], ), gridAgentBaseData: GridAgentBaseData, ) => @@ -262,8 +311,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { } } match { case exchangeVoltages => - sender ! VMAdapter( - ProvideSlackVoltageMessage(currentSweepNo, exchangeVoltages) + sender ! ProvideSlackVoltageMessage( + currentSweepNo, + exchangeVoltages, ) Behaviors.same } @@ -272,7 +322,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // before power flow calc for this sweep we either have to stash() the message to answer it later (in current sweep) // or trigger a new run for the next sweepNo case ( - PMAdapter( + WrappedPowerMessage( RequestGridPowerMessage( requestSweepNo, nodeUuids, @@ -288,7 +338,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) buffer.stash( - PMAdapter( + WrappedPowerMessage( RequestGridPowerMessage(requestSweepNo, nodeUuids, sender) ) ) @@ -303,7 +353,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ctx.self ! PrepareNextSweepTrigger(currentTick) buffer.stash( - PMAdapter( + WrappedPowerMessage( RequestGridPowerMessage(requestSweepNo, nodeUuids, sender) ) ) @@ -316,7 +366,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // after power flow calc for this sweepNo case ( - PMAdapter(RequestGridPowerMessage(_, requestedNodeUuids, sender)), + WrappedPowerMessage( + RequestGridPowerMessage(_, requestedNodeUuids, sender) + ), powerFlowDoneData @ PowerFlowDoneData( gridAgentBaseData, powerFlowResult, @@ -408,11 +460,13 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) } - sender ! PMAdapter(ProvideGridPowerMessage(exchangePowers)) + sender ! WrappedPowerMessage( + ProvideGridPowerMessage(exchangePowers) + ) simulateGrid(updatedGridAgentBaseData, currentTick) case _: FailedNewtonRaphsonPFResult => - sender ! PMAdapter(FailedPowerFlow) + sender ! WrappedPowerMessage(FailedPowerFlow) simulateGrid(gridAgentBaseData, currentTick) } case None => @@ -421,7 +475,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { "I got a grid power request from a subgrid I don't know. Can't answer it properly." ) - sender ! PMAdapter(FailedPowerFlow) + sender ! WrappedPowerMessage(FailedPowerFlow) Behaviors.same } @@ -475,8 +529,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) createAndSendPowerFlowResults( gridAgentBaseData, - currentTick.toDateTime(simStartTime), - )(ctx.log) + currentTick.toDateTime(values.simStartTime), + )(ctx.log, values) // do my cleanup stuff ctx.log.debug("Doing my cleanup stuff") @@ -489,9 +543,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) // / inform scheduler that we are done with the whole simulation and request new trigger for next time step - environmentRefs.scheduler ! Completion( - activationAdapter, - Some(currentTick + resolution), + values.environmentRefs.scheduler ! Completion( + values.activationAdapter, + Some(currentTick + values.resolution), ) // return to Idle @@ -519,6 +573,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { private def handlePowerFlowCalculations( gridAgentData: GridAgentData, currentTick: Long, + )(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { (ctx, message) => (message, gridAgentData) match { @@ -610,7 +667,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // handler for the future provided by `askForAssetPowers` to check if there are any changes in generation/load // of assets based on updated nodal voltages case ( - ValuesAdapter(receivedPowerValues: ReceivedPowerValues), + receivedPowerValues: ReceivedPowerValues, powerFlowDoneData: PowerFlowDoneData, ) => val gridAgentBaseData = powerFlowDoneData.gridAgentBaseData @@ -658,7 +715,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { updatedGridAgentBaseData, currentTick, handlePowerFlowCalculations, - )(ctx) + )(ctx, values, buffer) } else { // no changes from assets, we want to go back to SimulateGrid and report the LF results to our parent grids if any requests @@ -673,7 +730,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // this means we requested an update of the slack voltage values, but for now don't request (and hence don't expect) // updated power values for our power flow calculations case ( - ValuesAdapter(receivedSlackValues: ReceivedSlackVoltageValues), + receivedSlackValues: ReceivedSlackVoltageValues, gridAgentBaseData: GridAgentBaseData, ) => ctx.log.debug( @@ -685,7 +742,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { val previousSweepData = gridAgentBaseData.sweepValueStores.getOrElse( gridAgentBaseData.currentSweepNo - 1, throw new DBFSAlgorithmException( - s"$actorName Unable to get results from previous sweep ${gridAgentBaseData.currentSweepNo - 1}!" + s"${gridAgentBaseData.actorName}: Unable to get results from previous sweep ${gridAgentBaseData.currentSweepNo - 1}!" ), ) @@ -792,28 +849,32 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // (only possible when first simulation triggered and this agent is faster in this state as the request // by a superior grid arrives) case ( - PMAdapter(requestGridPowerMessage: RequestGridPowerMessage), + WrappedPowerMessage( + requestGridPowerMessage: RequestGridPowerMessage + ), _: GridAgentBaseData, ) => ctx.log.debug( "Received Request for Grid Power too early. Stashing away" ) - buffer.stash(PMAdapter(requestGridPowerMessage)) + buffer.stash(WrappedPowerMessage(requestGridPowerMessage)) Behaviors.same // happens only when we received slack data and power values before we received a request to provide grid // (only possible when first simulation triggered and this agent is faster // with its power flow calculation in this state as the request by a superior grid arrives) case ( - PMAdapter(requestGridPowerMessage: RequestGridPowerMessage), + WrappedPowerMessage( + requestGridPowerMessage: RequestGridPowerMessage + ), _: PowerFlowDoneData, ) => ctx.log.debug( "Received Request for Grid Power too early. Stashing away" ) - buffer.stash(PMAdapter(requestGridPowerMessage)) + buffer.stash(WrappedPowerMessage(requestGridPowerMessage)) Behaviors.same case (StopGridAgent, _) => @@ -833,6 +894,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { */ private def checkPowerDifferences( gridAgentBaseData: GridAgentBaseData + )(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { case (ctx, CheckPowerDifferencesTrigger(currentTick)) => @@ -973,7 +1037,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { failedResult.cause, ) ctx.self ! FinishGridSimulationTrigger(currentTick) - handlePowerFlowFailure(gridAgentBaseData)(ctx) + handlePowerFlowFailure(gridAgentBaseData)(ctx, values) simulateGrid(gridAgentBaseData, currentTick) } @@ -1007,7 +1071,11 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentBaseData: GridAgentBaseData, currentTick: Long, behavior: (GridAgentData, Long) => Behavior[GridAgentMessage], - )(implicit ctx: ActorContext[GridAgentMessage]): Behavior[GridAgentMessage] = + )(implicit + ctx: ActorContext[GridAgentMessage], + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], + ): Behavior[GridAgentMessage] = if (allReceived) { ctx.log.debug( "All power values of inferior grids, assets + voltage superior grid slack voltages received." @@ -1043,8 +1111,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ctx.log.debug( "Still waiting for asset or grid power values or slack voltage information of inferior grids" ) - - buffer.unstashAll(behavior(gridAgentBaseData, currentTick)) + behavior(gridAgentBaseData, currentTick) } /** Normally only reached by the superior (dummy) agent! @@ -1076,7 +1143,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { currentTick: Long, behavior: (GridAgentData, Long) => Behavior[GridAgentMessage], )(implicit - ctx: ActorContext[GridAgentMessage] + ctx: ActorContext[GridAgentMessage], + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = { if (allReceived) { ctx.log.debug( @@ -1106,8 +1175,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ctx.log.debug( "Still waiting for asset or grid power values or slack voltage information of inferior grids" ) - - buffer.unstashAll(behavior(gridAgentBaseData, currentTick)) + behavior(gridAgentBaseData, currentTick) } } @@ -1117,8 +1185,11 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { */ private def handlePowerFlowFailure( gridAgentBaseData: GridAgentBaseData - )(implicit ctx: ActorContext[GridAgentMessage]): Unit = { - environmentRefs.runtimeEventListener ! PowerFlowFailed + )(implicit + ctx: ActorContext[GridAgentMessage], + values: GridAgentValues, + ): Unit = { + values.environmentRefs.runtimeEventListener ! PowerFlowFailed if (gridAgentBaseData.powerFlowParams.stopOnFailure) { ctx.log.error("Stopping because of failed power flow.") @@ -1143,9 +1214,12 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { private def goToSimulateGridForNextSweepWith( gridAgentBaseData: GridAgentBaseData, currentTick: Long, + )(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = { - environmentRefs.scheduler ! Completion( - activationAdapter, + values.environmentRefs.scheduler ! Completion( + values.activationAdapter, Some(currentTick), ) @@ -1161,8 +1235,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * the current sweep value store containing the current node voltage for * the assets * @param nodeToAssetAgents - * a map contains a mapping between nodes and the [[classicRef]] s located - * \@ those nodes + * a map contains a mapping between nodes and the [[ActorRef]] s located \@ + * those nodes * @param refSystem * the reference system of the [[edu.ie3.simona.model.grid.GridModel]] of * this [[GridAgent]] @@ -1177,7 +1251,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { askTimeout: Duration, )(implicit ctx: ActorContext[GridAgentMessage] - ): Option[Future[ValuesAdapter]] = { + ): Option[Future[GridAgentMessage]] = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) implicit val ec: ExecutionContext = ctx.executionContext @@ -1227,7 +1301,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { }) }.toVector ) - .map(res => ValuesAdapter(ReceivedAssetPowerValues(res))) + .map(res => ReceivedAssetPowerValues(res)) pipeToSelf(future, ctx) Some(future) @@ -1252,7 +1326,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { askTimeout: Duration, )(implicit ctx: ActorContext[GridAgentMessage] - ): Option[Future[ValuesAdapter]] = { + ): Option[Future[GridAgentMessage]] = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) implicit val ec: ExecutionContext = ctx.executionContext implicit val scheduler: Scheduler = ctx.system.scheduler @@ -1281,7 +1355,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { .map { case (inferiorGridAgentRef, inferiorGridGateNodes) => inferiorGridAgentRef .ask[GridAgentMessage](ref => - PMAdapter( + WrappedPowerMessage( RequestGridPowerMessage( currentSweepNo, inferiorGridGateNodes.distinct, @@ -1290,17 +1364,17 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) ) .map { - case PMAdapter( + case WrappedPowerMessage( provideGridPowerMessage: ProvideGridPowerMessage ) => (inferiorGridAgentRef, provideGridPowerMessage) - case PMAdapter(FailedPowerFlow) => + case WrappedPowerMessage(FailedPowerFlow) => (inferiorGridAgentRef, FailedPowerFlow) } } .toVector ) - .map(res => ValuesAdapter(ReceivedGridPowerValues(res))) + .map(res => ReceivedGridPowerValues(res)) pipeToSelf(future, ctx) future } @@ -1324,7 +1398,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { askTimeout: Duration, )(implicit ctx: ActorContext[GridAgentMessage] - ): Option[Future[ValuesAdapter]] = { + ): Option[Future[GridAgentMessage]] = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) implicit val ec: ExecutionContext = ctx.executionContext implicit val scheduler: Scheduler = ctx.system.scheduler @@ -1342,24 +1416,19 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { .map { case (superiorGridAgent, gridGates) => superiorGridAgent .ask[GridAgentMessage](ref => - VMAdapter( - RequestSlackVoltageMessage( - currentSweepNo, - gridGates.map(_.superiorNode.getUuid), - ref, - ) + RequestSlackVoltageMessage( + currentSweepNo, + gridGates.map(_.superiorNode.getUuid), + ref, ) ) - .map { - case VMAdapter( - providedSlackValues: ProvideSlackVoltageMessage - ) => - (superiorGridAgent, providedSlackValues) + .map { case providedSlackValues: ProvideSlackVoltageMessage => + (superiorGridAgent, providedSlackValues) } } .toVector ) - .map(res => ValuesAdapter(ReceivedSlackVoltageValues(res))) + .map(res => ReceivedSlackVoltageValues(res)) pipeToSelf(future, ctx) future } @@ -1380,10 +1449,13 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { private def createAndSendPowerFlowResults( gridAgentBaseData: GridAgentBaseData, currentTimestamp: ZonedDateTime, - )(implicit log: Logger): Unit = { + )(implicit + log: Logger, + values: GridAgentValues, + ): Unit = { gridAgentBaseData.sweepValueStores.lastOption.foreach { case (_, valueStore) => - notifyListener( + values.notifyListener( this.createResultModels( gridAgentBaseData.gridEnv.gridModel, valueStore, @@ -1402,12 +1474,12 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * context */ private def pipeToSelf( - future: Future[ValuesAdapter], + future: Future[GridAgentMessage], ctx: ActorContext[GridAgentMessage], ): Unit = { - ctx.pipeToSelf[ValuesAdapter](future) { + ctx.pipeToSelf[GridAgentMessage](future) { case Success(value) => value - case Failure(exception) => ValuesAdapter(ReceivedFailure(exception)) + case Failure(exception) => ReceivedFailure(exception) } } } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 17dfce12be..19de1b9649 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -11,19 +11,19 @@ import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentBaseData, GridAgentInitData, + GridAgentValues, } import edu.ie3.simona.agent.grid.GridAgentMessage._ import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.event.ResultEvent -import edu.ie3.simona.event.notifier.Notifier import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel +import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } -import edu.ie3.simona.ontology.messages.{Activation, StopMessage} import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.TimeUtil import org.apache.pekko.actor.typed.scaladsl.adapter.{ @@ -32,25 +32,24 @@ import org.apache.pekko.actor.typed.scaladsl.adapter.{ } import org.apache.pekko.actor.typed.scaladsl.{Behaviors, StashBuffer} import org.apache.pekko.actor.typed.{ActorRef, Behavior} -import org.apache.pekko.actor.{ActorRef => classicRef} +import org.apache.pekko.actor.{ActorRef => ClassicRef} import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.UUID import scala.language.postfixOps -object GridAgent { +object GridAgent extends DBFSAlgorithm { + def apply( environmentRefs: EnvironmentRefs, simonaConfig: SimonaConfig, - listener: Iterable[classicRef], + listener: Iterable[ClassicRef], ): Behavior[GridAgentMessage] = Behaviors.withStash(100) { buffer => Behaviors.setup[GridAgentMessage] { context => - context.messageAdapter(values => ValuesAdapter(values)) - context.messageAdapter(msg => PMAdapter(msg)) - context.messageAdapter(msg => VMAdapter(msg)) + context.messageAdapter(msg => WrappedPowerMessage(msg)) val activationAdapter: ActorRef[Activation] = - context.messageAdapter[Activation](msg => ActivationAdapter(msg)) + context.messageAdapter[Activation](msg => WrappedActivation(msg)) // val initialization val resolution: Long = simonaConfig.simona.powerflow.resolution.get( @@ -60,55 +59,27 @@ object GridAgent { val simStartTime: ZonedDateTime = TimeUtil.withDefaults .toZonedDateTime(simonaConfig.simona.time.startDateTime) - val gridAgentController = - new GridAgentController( - context.toClassic, - environmentRefs, - simStartTime, - TimeUtil.withDefaults - .toZonedDateTime(simonaConfig.simona.time.endDateTime), - simonaConfig.simona.runtime.participant, - simonaConfig.simona.output.participant, - resolution, - listener.map(_.toTyped[ResultEvent]), - context.log, - ) - - val agent = GridAgent( + val agentValues = GridAgentValues( environmentRefs, simonaConfig, listener, resolution, simStartTime, - gridAgentController, - buffer, activationAdapter, - SimonaActorNaming.actorName(context.self), ) - agent.uninitialized + uninitialized(agentValues, buffer) } } -} - -final case class GridAgent( - environmentRefs: EnvironmentRefs, - simonaConfig: SimonaConfig, - override val listener: Iterable[classicRef], - resolution: Long, - simStartTime: ZonedDateTime, - gridAgentController: GridAgentController, - buffer: StashBuffer[GridAgentMessage], - activationAdapter: ActorRef[Activation], - actorName: String, -) extends DBFSAlgorithm - with Notifier { - protected def uninitialized: Behavior[GridAgentMessage] = + private def uninitialized(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], + ): Behavior[GridAgentMessage] = Behaviors.receiveMessage[GridAgentMessage] { case CreateGridAgent(gridAgentInitData, unlockKey) => - environmentRefs.scheduler ! ScheduleActivation( - activationAdapter, + values.environmentRefs.scheduler ! ScheduleActivation( + values.activationAdapter, INIT_SIM_TICK, Some(unlockKey), ) @@ -122,10 +93,13 @@ final case class GridAgent( Behaviors.unhandled } - protected def initializing( + private def initializing( gridAgentInitData: GridAgentInitData + )(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { - case (ctx, ActivationAdapter(Activation(INIT_SIM_TICK))) => + case (ctx, WrappedActivation(Activation(INIT_SIM_TICK))) => // fail fast sanity checks failFast(gridAgentInitData, SimonaActorNaming.actorName(ctx.self)) @@ -156,13 +130,27 @@ final case class GridAgent( subGridContainer, refSystem, TimeUtil.withDefaults.toZonedDateTime( - simonaConfig.simona.time.startDateTime + values.simonaConfig.simona.time.startDateTime ), TimeUtil.withDefaults.toZonedDateTime( - simonaConfig.simona.time.endDateTime + values.simonaConfig.simona.time.endDateTime ), ) + val gridAgentController = + new GridAgentController( + ctx.toClassic, + values.environmentRefs, + values.simStartTime, + TimeUtil.withDefaults + .toZonedDateTime(values.simonaConfig.simona.time.endDateTime), + values.simonaConfig.simona.runtime.participant, + values.simonaConfig.simona.output.participant, + values.resolution, + values.listener.map(_.toTyped[ResultEvent]), + ctx.log, + ) + /* Reassure, that there are also calculation models for the given uuids */ val nodeToAssetAgentsMap: Map[UUID, Set[ActorRef[ParticipantMessage]]] = gridAgentController @@ -187,25 +175,23 @@ final case class GridAgent( gridAgentInitData.superiorGridNodeUuids, gridAgentInitData.inferiorGridGates, PowerFlowParams( - simonaConfig.simona.powerflow.maxSweepPowerDeviation, - simonaConfig.simona.powerflow.newtonraphson.epsilon.toVector.sorted, - simonaConfig.simona.powerflow.newtonraphson.iterations, - simonaConfig.simona.powerflow.sweepTimeout, - simonaConfig.simona.powerflow.stopOnFailure, + values.simonaConfig.simona.powerflow.maxSweepPowerDeviation, + values.simonaConfig.simona.powerflow.newtonraphson.epsilon.toVector.sorted, + values.simonaConfig.simona.powerflow.newtonraphson.iterations, + values.simonaConfig.simona.powerflow.sweepTimeout, + values.simonaConfig.simona.powerflow.stopOnFailure, ), - ctx.log, - ctx.self.toString, + SimonaActorNaming.actorName(ctx.self), ) ctx.log.debug("Je suis initialized") - environmentRefs.scheduler ! Completion( - activationAdapter, - Some(resolution), + values.environmentRefs.scheduler ! Completion( + values.activationAdapter, + Some(values.resolution), ) idle(gridAgentBaseData) - case (_, StopGridAgent) => Behaviors.stopped @@ -213,38 +199,6 @@ final case class GridAgent( Behaviors.unhandled } - protected def idle( - gridAgentBaseData: GridAgentBaseData - ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { - case (_, pm: PMAdapter) => - // needs to be set here to handle if the messages arrive too early - // before a transition to GridAgentBehaviour took place - buffer.stash(pm) - Behaviors.same - - case (_, ActivationAdapter(activation: Activation)) => - environmentRefs.scheduler ! Completion( - activationAdapter, - Some(activation.tick), - ) - buffer.unstashAll(simulateGrid(gridAgentBaseData, activation.tick)) - - case (ctx, ResultMessageAdapter(StopMessage(_))) => - // shutdown children - gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => - actors.foreach(a => ctx.stop(a)) - } - - // we are done - Behaviors.stopped - - case (_, StopGridAgent) => - Behaviors.stopped - - case _ => - Behaviors.unhandled - } - private def failFast( gridAgentInitData: GridAgentInitData, actorName: String, diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala index d4b91858df..d5a726bd0b 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala @@ -10,13 +10,17 @@ import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.datamodel.models.input.container.{SubGridContainer, ThermalGrid} import edu.ie3.powerflow.model.PowerFlowResult import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult +import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.ReceivedValues.{ ReceivedPowerValues, ReceivedSlackVoltageValues, } import edu.ie3.simona.agent.grid.ReceivedValuesStore.NodeToReceivedPower import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage +import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.event.notifier.Notifier import edu.ie3.simona.model.grid.{GridModel, RefSystem} +import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage.{ FailedPowerFlow, PowerResponseMessage, @@ -24,8 +28,10 @@ import edu.ie3.simona.ontology.messages.PowerMessage.{ ProvidePowerMessage, } import org.apache.pekko.actor.typed.ActorRef -import org.slf4j.Logger +import org.apache.pekko.actor.typed.scaladsl.StashBuffer +import org.apache.pekko.actor.{ActorRef => ClassicRef} +import java.time.ZonedDateTime import java.util.UUID sealed trait GridAgentData @@ -34,6 +40,29 @@ sealed trait GridAgentData */ object GridAgentData { + /** Class holding some [[GridAgent]] values that are immutable. + * @param environmentRefs + * environment actor refs + * @param simonaConfig + * config + * @param listener + * listeners + * @param resolution + * of the simulation + * @param simStartTime + * start time of the simulation + * @param activationAdapter + * adapter for [[Activation]] + */ + final case class GridAgentValues private ( + environmentRefs: EnvironmentRefs, + simonaConfig: SimonaConfig, + override val listener: Iterable[ClassicRef], + resolution: Long, + simStartTime: ZonedDateTime, + activationAdapter: ActorRef[Activation], + ) extends Notifier + /** Data that is send to the [[GridAgent]] directly after startup. It contains * the main information for initialization. This data should include all * [[GridAgent]] individual data, for data that is the same for all @@ -103,7 +132,6 @@ object GridAgentData { superiorGridNodeUuids: Vector[UUID], inferiorGridGates: Vector[SubGridGate], powerFlowParams: PowerFlowParams, - log: Logger, actorName: String, ): GridAgentBaseData = { @@ -126,7 +154,6 @@ object GridAgentData { superiorGridNodeUuids, ), sweepValueStores, - log, actorName, ) } @@ -191,7 +218,6 @@ object GridAgentData { currentSweepNo: Int, receivedValueStore: ReceivedValuesStore, sweepValueStores: Map[Int, SweepValueStore], - log: Logger, actorName: String, ) extends GridAgentData with GridAgentDataHelper { @@ -212,14 +238,7 @@ object GridAgentData { val slackVoltageValuesReady = receivedValueStore.nodeToReceivedSlackVoltage.values .forall(_.isDefined) - log.debug( - "slackMap: {}", - receivedValueStore.nodeToReceivedSlackVoltage, - ) - log.debug( - "powerMap: {}", - receivedValueStore.nodeToReceivedPower, - ) + assetAndGridPowerValuesReady & slackVoltageValuesReady } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala index cb8c43b95d..cc11aa44ac 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala @@ -8,11 +8,7 @@ package edu.ie3.simona.agent.grid import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage -import edu.ie3.simona.ontology.messages.{ - Activation, - PowerMessage, - VoltageMessage, -} +import edu.ie3.simona.ontology.messages.{Activation, PowerMessage} import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey import org.apache.pekko.actor.typed.ActorRef @@ -25,6 +21,11 @@ sealed trait GridAgentMessage */ object GridAgentMessage { + /** Necessary because we want to extend [[GridAgentMessage]] in other classes, + * but we do want to keep [[GridAgentMessage]] sealed. + */ + private[grid] trait GAMessage extends GridAgentMessage + /** GridAgent initialization data can only be constructed once all GridAgent * actors are created. Thus, we need an extra initialization message. * @@ -78,33 +79,18 @@ object GridAgentMessage { */ final object StopGridAgent extends GridAgentMessage - /** Wrapper for string messages. NOTICE: Only for internal use. - * @param str - * message - * @param sender - * of the message - */ - private[grid] final case class StringAdapter( - str: String, - sender: ActorRef[GridAgentMessage], - ) extends GridAgentMessage - /** Wrapper for activation values * * @param activation * the tick */ - final case class ActivationAdapter(activation: Activation) + final case class WrappedActivation(activation: Activation) extends GridAgentMessage - final case class PMAdapter(msg: PowerMessage) extends GridAgentMessage - - final case class VMAdapter(msg: VoltageMessage) extends GridAgentMessage - - final case class ValuesAdapter(values: ReceivedValues) + final case class WrappedPowerMessage(msg: PowerMessage) extends GridAgentMessage - final case class ResultMessageAdapter(msg: ResultMessage) + final case class WrappedResultMessage(msg: ResultMessage) extends GridAgentMessage } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala b/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala index 8d275188b7..5d34d06bd4 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/PowerFlowSupport.scala @@ -17,7 +17,7 @@ import edu.ie3.simona.agent.grid.ReceivedValues.ReceivedSlackVoltageValues import edu.ie3.simona.exceptions.agent.DBFSAlgorithmException import edu.ie3.simona.model.grid._ import edu.ie3.simona.ontology.messages.PowerMessage.ProvidePowerMessage -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage import edu.ie3.util.scala.quantities.Kilovars import org.slf4j.Logger import squants.electro.ElectricPotential diff --git a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala index dd1c5d5b49..eacda5e019 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala @@ -6,27 +6,26 @@ package edu.ie3.simona.agent.grid -import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.ontology.messages.PowerMessage.PowerResponseMessage -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage -import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey +import VoltageMessage.ProvideSlackVoltageMessage +import edu.ie3.simona.agent.grid.GridAgentMessage.GAMessage import org.apache.pekko.actor.typed.ActorRef /** Serves as a wrapper class that allows for matches against received values in * [[DBFSAlgorithm]] */ -sealed trait ReceivedValues +sealed trait ReceivedValues extends GAMessage object ReceivedValues { - type ParticipantPowerRequestResponse = + private type ParticipantPowerRequestResponse = ( ActorRef[_], PowerResponseMessage, ) // necessary, because participants are still classic actors - type GridPowerRequestResponse = + private type GridPowerRequestResponse = (ActorRef[GridAgentMessage], PowerResponseMessage) - type ActorSlackVoltageRequestResponse = + private type ActorSlackVoltageRequestResponse = (ActorRef[GridAgentMessage], ProvideSlackVoltageMessage) sealed trait ReceivedPowerValues extends ReceivedValues { diff --git a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala index 6e01f44620..a576045703 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValuesStore.scala @@ -16,7 +16,7 @@ import edu.ie3.simona.ontology.messages.PowerMessage.{ PowerResponseMessage, ProvidePowerMessage, } -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage import org.apache.pekko.actor.typed.ActorRef import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps import org.apache.pekko.actor.{ActorRef => classicRef} diff --git a/src/main/scala/edu/ie3/simona/ontology/messages/VoltageMessage.scala b/src/main/scala/edu/ie3/simona/agent/grid/VoltageMessage.scala similarity index 88% rename from src/main/scala/edu/ie3/simona/ontology/messages/VoltageMessage.scala rename to src/main/scala/edu/ie3/simona/agent/grid/VoltageMessage.scala index 67229c4436..bcbffdf609 100644 --- a/src/main/scala/edu/ie3/simona/ontology/messages/VoltageMessage.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/VoltageMessage.scala @@ -4,16 +4,16 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.ontology.messages +package edu.ie3.simona.agent.grid -import edu.ie3.simona.agent.grid.GridAgentMessage -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.agent.grid.GridAgentMessage.GAMessage +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage import org.apache.pekko.actor.typed.ActorRef +import squants.electro.ElectricPotential import java.util.UUID -import squants.electro.ElectricPotential -sealed trait VoltageMessage +sealed trait VoltageMessage extends GAMessage /** Message that is send between [[edu.ie3.simona.agent.grid.GridAgent]] s to * provide voltage information for nodes diff --git a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala index 930c46907a..a0b33394ed 100644 --- a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala +++ b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala @@ -6,7 +6,10 @@ package edu.ie3.simona.sim -import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps +import org.apache.pekko.actor.typed.scaladsl.adapter.{ + ClassicActorRefOps, + TypedActorRefOps, +} import org.apache.pekko.actor.SupervisorStrategy.Stop import org.apache.pekko.actor.{ Actor, @@ -24,7 +27,7 @@ import edu.ie3.simona.agent.grid.GridAgentMessage.StopGridAgent import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.StopMessage import edu.ie3.simona.scheduler.TimeAdvancer -import edu.ie3.simona.scheduler.TimeAdvancer.StartSimMessage +import edu.ie3.simona.scheduler.TimeAdvancer.{Incoming, StartSimMessage} import edu.ie3.simona.sim.SimMessage.{ InitSim, SimulationFailure, @@ -37,6 +40,7 @@ import edu.ie3.simona.sim.SimonaSim.{ } import edu.ie3.simona.sim.setup.{ExtSimSetupData, SimonaSetup} import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.ActorContext import scala.concurrent.duration.DurationInt import scala.language.postfixOps @@ -102,7 +106,7 @@ class SimonaSim(simonaSetup: SimonaSetup) context, EnvironmentRefs( scheduler, - runtimeEventListener.toClassic, + runtimeEventListener, primaryServiceProxy, weatherService, extSimulationData.evDataService, diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala index 2235f90327..4ab3199f6c 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala @@ -45,8 +45,8 @@ import org.apache.pekko.actor.typed.scaladsl.adapter.{ } import org.apache.pekko.actor.{ ActorSystem, - ActorContext => classicContext, - ActorRef => classicRef, + ActorContext, + ActorRef => ClassicRef, } import java.util.concurrent.LinkedBlockingQueue @@ -67,9 +67,9 @@ class SimonaStandaloneSetup( ) extends SimonaSetup { override def gridAgents( - context: classicContext, + context: ActorContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[classicRef], + systemParticipantListener: Seq[ClassicRef], ): Iterable[ActorRef[GridAgentMessage]] = { /* get the grid */ @@ -142,9 +142,9 @@ class SimonaStandaloneSetup( } override def primaryServiceProxy( - context: classicContext, - scheduler: classicRef, - ): classicRef = { + context: ActorContext, + scheduler: ClassicRef, + ): ClassicRef = { val simulationStart = TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.startDateTime ) @@ -164,9 +164,9 @@ class SimonaStandaloneSetup( } override def weatherService( - context: classicContext, - scheduler: classicRef, - ): classicRef = { + context: ActorContext, + scheduler: ClassicRef, + ): ClassicRef = { val weatherService = context.simonaActorOf( WeatherService.props( scheduler, @@ -187,8 +187,8 @@ class SimonaStandaloneSetup( } override def extSimulations( - context: classicContext, - scheduler: classicRef, + context: ActorContext, + scheduler: ClassicRef, ): ExtSimSetupData = { val jars = ExtSimLoader.scanInputFolder() @@ -212,7 +212,7 @@ class SimonaStandaloneSetup( // setup data services that belong to this external simulation val (extData, extDataInit): ( Iterable[ExtData], - Iterable[(Class[_ <: SimonaService[_]], classicRef)], + Iterable[(Class[_ <: SimonaService[_]], ClassicRef)], ) = extLink.getExtDataSimulations.asScala.zipWithIndex.map { case (_: ExtEvSimulation, dIndex) => @@ -250,8 +250,8 @@ class SimonaStandaloneSetup( } override def timeAdvancer( - context: classicContext, - simulation: classicRef, + context: ActorContext, + simulation: ClassicRef, runtimeEventListener: ActorRef[RuntimeEvent], ): ActorRef[TimeAdvancer.Incoming] = { val startDateTime = TimeUtil.withDefaults.toZonedDateTime( @@ -273,9 +273,9 @@ class SimonaStandaloneSetup( } override def scheduler( - context: classicContext, + context: ActorContext, timeAdvancer: ActorRef[TimeAdvancer.Incoming], - ): classicRef = + ): ClassicRef = context .spawn( Scheduler( @@ -286,7 +286,7 @@ class SimonaStandaloneSetup( .toClassic override def runtimeEventListener( - context: classicContext + context: ActorContext ): ActorRef[RuntimeEvent] = context .spawn( @@ -299,8 +299,8 @@ class SimonaStandaloneSetup( ) override def systemParticipantsListener( - context: classicContext - ): Seq[classicRef] = { + context: ActorContext + ): Seq[ClassicRef] = { // append ResultEventListener as well to write raw output files ArgsParser .parseListenerConfigOption(simonaConfig.simona.event.listener) @@ -323,9 +323,9 @@ class SimonaStandaloneSetup( def buildSubGridToActorRefMap( subGridTopologyGraph: SubGridTopologyGraph, - context: classicContext, + context: ActorContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[classicRef], + systemParticipantListener: Seq[ClassicRef], ): Map[Int, ActorRef[GridAgentMessage]] = { subGridTopologyGraph .vertexSet() diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala index c938ad0054..ea7ca31c72 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala @@ -19,8 +19,9 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import VoltageMessage.ProvideSlackVoltageMessage +import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGrid @@ -54,7 +55,7 @@ class DBFSAlgorithmCenGridSpec private val scheduler: TestProbe[SchedulerMessage] = TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe("runtimeEvents") + private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") private val primaryService = TestProbe("primaryService") private val weatherService = TestProbe("weatherService") @@ -76,7 +77,7 @@ class DBFSAlgorithmCenGridSpec private val environmentRefs = EnvironmentRefs( scheduler = scheduler.ref.toClassic, - runtimeEventListener = runtimeEvents.ref.toClassic, + runtimeEventListener = runtimeEvents.ref, primaryServiceProxy = primaryService.ref.toClassic, weather = weatherService.ref.toClassic, evDataService = None, @@ -132,14 +133,14 @@ class DBFSAlgorithmCenGridSpec val msg = scheduler.expectMessageType[ScheduleActivation] msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) - centerGridAgent ! ActivationAdapter(Activation(INIT_SIM_TICK)) + centerGridAgent ! WrappedActivation(Activation(INIT_SIM_TICK)) val completionMessage = scheduler.expectMessageType[Completion] - completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) + completionMessage shouldBe Completion(msg.actor, Some(3600)) } s"go to SimulateGrid when it receives an activity start trigger" in { - centerGridAgent ! ActivationAdapter(Activation(3600)) + centerGridAgent ! WrappedActivation(Activation(3600)) val msg = scheduler.expectMessageType[Completion] msg shouldBe Completion(msg.actor, Some(3600)) @@ -150,7 +151,7 @@ class DBFSAlgorithmCenGridSpec val firstSweepNo = 0 // send the start grid simulation trigger - centerGridAgent ! ActivationAdapter(Activation(3600)) + centerGridAgent ! WrappedActivation(Activation(3600)) /* We expect one grid power request message per inferior grid */ @@ -217,7 +218,7 @@ class DBFSAlgorithmCenGridSpec // we now answer the request of our centerGridAgent // with three fake grid power messages and one fake slack voltage message - firstPowerRequestSender11 ! PMAdapter( + firstPowerRequestSender11 ! WrappedPowerMessage( ProvideGridPowerMessage( inferiorGrid11.nodeUuids.map(nodeUuid => ExchangePower( @@ -229,7 +230,7 @@ class DBFSAlgorithmCenGridSpec ) ) - firstPowerRequestSender12 ! PMAdapter( + firstPowerRequestSender12 ! WrappedPowerMessage( ProvideGridPowerMessage( inferiorGrid12.nodeUuids.map(nodeUuid => ExchangePower( @@ -241,7 +242,7 @@ class DBFSAlgorithmCenGridSpec ) ) - firstPowerRequestSender13 ! PMAdapter( + firstPowerRequestSender13 ! WrappedPowerMessage( ProvideGridPowerMessage( inferiorGrid13.nodeUuids.map(nodeUuid => ExchangePower( @@ -253,22 +254,20 @@ class DBFSAlgorithmCenGridSpec ) ) - firstSlackVoltageRequestSender ! VMAdapter( - ProvideSlackVoltageMessage( - firstSweepNo, - Seq( - ExchangeVoltage( - supNodeA.getUuid, - Kilovolts(380d), - Kilovolts(0d), - ), - ExchangeVoltage( - supNodeB.getUuid, - Kilovolts(380d), - Kilovolts(0d), - ), + firstSlackVoltageRequestSender ! ProvideSlackVoltageMessage( + firstSweepNo, + Seq( + ExchangeVoltage( + supNodeA.getUuid, + Kilovolts(380d), + Kilovolts(0d), ), - ) + ExchangeVoltage( + supNodeB.getUuid, + Kilovolts(380d), + Kilovolts(0d), + ), + ), ) // power flow calculation should run now. After it's done, @@ -301,22 +300,20 @@ class DBFSAlgorithmCenGridSpec superiorGridAgent.expectSlackVoltageRequest(secondSweepNo) // the superior grid would answer with updated slack voltage values - secondSlackAskSender ! VMAdapter( - ProvideSlackVoltageMessage( - secondSweepNo, - Seq( - ExchangeVoltage( - supNodeB.getUuid, - Kilovolts(374.22694614463d), // 380 kV @ 10° - Kilovolts(65.9863075134335d), // 380 kV @ 10° - ), - ExchangeVoltage( // this one should currently be ignored anyways - supNodeA.getUuid, - Kilovolts(380d), - Kilovolts(0d), - ), + secondSlackAskSender ! ProvideSlackVoltageMessage( + secondSweepNo, + Seq( + ExchangeVoltage( + supNodeB.getUuid, + Kilovolts(374.22694614463d), // 380 kV @ 10° + Kilovolts(65.9863075134335d), // 380 kV @ 10° ), - ) + ExchangeVoltage( // this one should currently be ignored anyways + supNodeA.getUuid, + Kilovolts(380d), + Kilovolts(0d), + ), + ), ) // After the intermediate power flow calculation, we expect one grid power @@ -385,7 +382,7 @@ class DBFSAlgorithmCenGridSpec // we now answer the requests of our centerGridAgent // with three fake grid power message - secondPowerRequestSender11 ! PMAdapter( + secondPowerRequestSender11 ! WrappedPowerMessage( ProvideGridPowerMessage( inferiorGrid11.nodeUuids.map(nodeUuid => ExchangePower( @@ -397,7 +394,7 @@ class DBFSAlgorithmCenGridSpec ) ) - secondPowerRequestSender12 ! PMAdapter( + secondPowerRequestSender12 ! WrappedPowerMessage( ProvideGridPowerMessage( inferiorGrid12.nodeUuids.map(nodeUuid => ExchangePower( @@ -409,7 +406,7 @@ class DBFSAlgorithmCenGridSpec ) ) - secondPowerRequestSender13 ! PMAdapter( + secondPowerRequestSender13 ! WrappedPowerMessage( ProvideGridPowerMessage( inferiorGrid13.nodeUuids.map(nodeUuid => ExchangePower( diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala index 5586c8e5d4..eebcce4a0c 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala @@ -21,8 +21,9 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import VoltageMessage.ProvideSlackVoltageMessage +import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGrid @@ -49,7 +50,7 @@ class DBFSAlgorithmFailedPowerFlowSpec private val scheduler: TestProbe[SchedulerMessage] = TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe("runtimeEvents") + private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") private val primaryService = TestProbe("primaryService") private val weatherService = TestProbe("weatherService") @@ -63,7 +64,7 @@ class DBFSAlgorithmFailedPowerFlowSpec private val environmentRefs = EnvironmentRefs( scheduler = scheduler.ref.toClassic, - runtimeEventListener = runtimeEvents.ref.toClassic, + runtimeEventListener = runtimeEvents.ref, primaryServiceProxy = primaryService.ref.toClassic, weather = weatherService.ref.toClassic, evDataService = None, @@ -112,21 +113,17 @@ class DBFSAlgorithmFailedPowerFlowSpec key, ) - val message = scheduler.expectMessageType[ScheduleActivation] - message shouldBe ScheduleActivation( - message.actor, - INIT_SIM_TICK, - Some(key), - ) + val msg = scheduler.expectMessageType[ScheduleActivation] + msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) - centerGridAgent ! ActivationAdapter(Activation(INIT_SIM_TICK)) - scheduler.expectMessage(Completion(message.actor, Some(3600))) + centerGridAgent ! WrappedActivation(Activation(INIT_SIM_TICK)) + scheduler.expectMessage(Completion(msg.actor, Some(3600))) } s"go to SimulateGrid when it receives an activation" in { // send init data to agent - centerGridAgent ! ActivationAdapter(Activation(3600)) + centerGridAgent ! WrappedActivation(Activation(3600)) // we expect a completion message val message = scheduler.expectMessageType[Completion] @@ -137,7 +134,7 @@ class DBFSAlgorithmFailedPowerFlowSpec val sweepNo = 0 // send the start grid simulation trigger - centerGridAgent ! ActivationAdapter(Activation(3600)) + centerGridAgent ! WrappedActivation(Activation(3600)) // we expect a request for grid power values here for sweepNo $sweepNo val powerRequestSender = inferiorGridAgent.expectGridPowerRequest() @@ -166,7 +163,7 @@ class DBFSAlgorithmFailedPowerFlowSpec // we now answer the request of our centerGridAgent // with a fake grid power message and one fake slack voltage message - powerRequestSender ! PMAdapter( + powerRequestSender ! WrappedPowerMessage( ProvideGridPowerMessage( inferiorGridAgent.nodeUuids.map(nodeUuid => ExchangePower( @@ -178,17 +175,15 @@ class DBFSAlgorithmFailedPowerFlowSpec ) ) - slackVoltageRequestSender ! VMAdapter( - ProvideSlackVoltageMessage( - sweepNo, - Seq( - ExchangeVoltage( - supNodeA.getUuid, - Kilovolts(380d), - Kilovolts(0d), - ) - ), - ) + slackVoltageRequestSender ! ProvideSlackVoltageMessage( + sweepNo, + Seq( + ExchangeVoltage( + supNodeA.getUuid, + Kilovolts(380d), + Kilovolts(0d), + ) + ), ) // power flow calculation should run now. After it's done, @@ -201,7 +196,7 @@ class DBFSAlgorithmFailedPowerFlowSpec // wait 30 seconds max for power flow to finish superiorGridAgent.gaProbe.expectMessage( 30 seconds, - PMAdapter(FailedPowerFlow), + WrappedPowerMessage(FailedPowerFlow), ) // normally the slack node would send a FinishGridSimulationTrigger to all diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala index 0f2fa775b1..034b41cc2b 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala @@ -10,10 +10,9 @@ import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.agent.grid.GridAgentMessage.{ - ActivationAdapter, - VMAdapter, CreateGridAgent, FinishGridSimulationTrigger, + WrappedActivation, } import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage import edu.ie3.simona.model.grid.RefSystem @@ -22,8 +21,9 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import VoltageMessage.ProvideSlackVoltageMessage +import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.services.ServiceMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.PrimaryServiceRegistrationMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.RegistrationResponseMessage.RegistrationFailedMessage @@ -53,14 +53,14 @@ class DBFSAlgorithmParticipantSpec private val scheduler: TestProbe[SchedulerMessage] = TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe("runtimeEvents") + private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") private val primaryService: TestProbe[ServiceMessage] = TestProbe[ServiceMessage]("primaryService") private val weatherService = TestProbe("weatherService") private val environmentRefs = EnvironmentRefs( scheduler = scheduler.ref.toClassic, - runtimeEventListener = runtimeEvents.ref.toClassic, + runtimeEventListener = runtimeEvents.ref, primaryServiceProxy = primaryService.ref.toClassic, weather = weatherService.ref.toClassic, evDataService = None, @@ -109,7 +109,7 @@ class DBFSAlgorithmParticipantSpec msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) // send init data to agent and expect a CompletionMessage - gridAgentWithParticipants ! ActivationAdapter(Activation(INIT_SIM_TICK)) + gridAgentWithParticipants ! WrappedActivation(Activation(INIT_SIM_TICK)) val message = scheduler.expectMessageType[ScheduleActivation] @@ -120,6 +120,9 @@ class DBFSAlgorithmParticipantSpec _, ) => loadAgent + + case other => + fail(s"$other was not expected") } val completionMessage = scheduler.expectMessageType[Completion] @@ -148,7 +151,7 @@ class DBFSAlgorithmParticipantSpec s"go to SimulateGrid when it receives an activity start trigger" in { // send init data to agent - gridAgentWithParticipants ! ActivationAdapter(Activation(3600)) + gridAgentWithParticipants ! WrappedActivation(Activation(3600)) // we expect a completion message val message = scheduler.expectMessageType[Completion] @@ -161,7 +164,7 @@ class DBFSAlgorithmParticipantSpec // send the start grid simulation trigger // the gird agent should send a RequestAssetPowerMessage to the load agent - gridAgentWithParticipants ! ActivationAdapter(Activation(3600)) + gridAgentWithParticipants ! WrappedActivation(Activation(3600)) // we expect a request for voltage values of our slack node // (voltages are requested by our agent under test from the superior grid) @@ -170,17 +173,15 @@ class DBFSAlgorithmParticipantSpec // we now answer the request of our gridAgentsWithParticipants // with a fake slack voltage message - firstSlackVoltageRequestSender ! VMAdapter( - ProvideSlackVoltageMessage( - firstSweepNo, - Seq( - ExchangeVoltage( - supNodeA.getUuid, - Kilovolts(380d), - Kilovolts(0d), - ) - ), - ) + firstSlackVoltageRequestSender ! ProvideSlackVoltageMessage( + firstSweepNo, + Seq( + ExchangeVoltage( + supNodeA.getUuid, + Kilovolts(380d), + Kilovolts(0d), + ) + ), ) // power flow calculation should run now. After it's done, @@ -217,17 +218,15 @@ class DBFSAlgorithmParticipantSpec superiorGridAgent.expectSlackVoltageRequest(secondSweepNo) // the superior grid would answer with updated slack voltage values - secondSlackAskSender ! VMAdapter( - ProvideSlackVoltageMessage( - secondSweepNo, - Seq( - ExchangeVoltage( - supNodeA.getUuid, - Kilovolts(374.2269461446d), - Kilovolts(65.9863075134d), - ) - ), - ) + secondSlackAskSender ! ProvideSlackVoltageMessage( + secondSweepNo, + Seq( + ExchangeVoltage( + supNodeA.getUuid, + Kilovolts(374.2269461446d), + Kilovolts(65.9863075134d), + ) + ), ) // here the gridAgentWithParticipants has received a second AssetPowerUnchangedMessage diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala index 5d023f1017..19f68dc84b 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala @@ -11,12 +11,13 @@ import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.agent.grid.GridAgentMessage.{ - ActivationAdapter, CreateGridAgent, FinishGridSimulationTrigger, - PMAdapter, + WrappedActivation, + WrappedPowerMessage, } import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower @@ -61,7 +62,7 @@ class DBFSAlgorithmSupGridSpec private val scheduler: TestProbe[SchedulerMessage] = TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe("runtimeEvents") + private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") private val primaryService: TestProbe[ServiceMessage] = TestProbe[ServiceMessage]("primaryService") private val weatherService = TestProbe("weatherService") @@ -70,7 +71,7 @@ class DBFSAlgorithmSupGridSpec private val environmentRefs = EnvironmentRefs( scheduler = scheduler.ref.toClassic, - runtimeEventListener = runtimeEvents.ref.toClassic, + runtimeEventListener = runtimeEvents.ref, primaryServiceProxy = primaryService.ref.toClassic, weather = weatherService.ref.toClassic, evDataService = None, @@ -110,7 +111,7 @@ class DBFSAlgorithmSupGridSpec val am = scheduler.expectMessageType[ScheduleActivation] am shouldBe ScheduleActivation(am.actor, INIT_SIM_TICK, Some(key)) - superiorGridAgentFSM ! ActivationAdapter(Activation(INIT_SIM_TICK)) + superiorGridAgentFSM ! WrappedActivation(Activation(INIT_SIM_TICK)) val cm = scheduler.expectMessageType[Completion] cm shouldBe Completion(cm.actor, Some(3600)) @@ -118,7 +119,7 @@ class DBFSAlgorithmSupGridSpec s"go to SimulateGrid when it receives an activity start trigger" in { // send init data to agent - superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) + superiorGridAgentFSM ! WrappedActivation(Activation(3600)) // we expect a completion message val message = scheduler.expectMessageType[Completion] @@ -134,13 +135,15 @@ class DBFSAlgorithmSupGridSpec Vector(UUID.fromString("9fe5fa33-6d3b-4153-a829-a16f4347bc4e")) // send the start grid simulation trigger - superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) + superiorGridAgentFSM ! WrappedActivation(Activation(3600)) // we expect a request for grid power values here for sweepNo $sweepNo - val message = hvGrid.expectMessageType[PMAdapter] + val message = hvGrid.expectMessageType[WrappedPowerMessage] val lastSender = message match { - case PMAdapter(requestGridPowerMessage: RequestGridPowerMessage) => + case WrappedPowerMessage( + requestGridPowerMessage: RequestGridPowerMessage + ) => requestGridPowerMessage.currentSweepNo shouldBe sweepNo requestGridPowerMessage.nodeUuids should contain allElementsOf requestedConnectionNodeUuids @@ -154,7 +157,7 @@ class DBFSAlgorithmSupGridSpec // we return with a fake grid power message // / as we are using the ask pattern, we cannot send it to the grid agent directly but have to send it to the // / ask sender - lastSender ! PMAdapter( + lastSender ! WrappedPowerMessage( ProvideGridPowerMessage( requestedConnectionNodeUuids.map { uuid => ExchangePower( @@ -245,7 +248,7 @@ class DBFSAlgorithmSupGridSpec ) // bring agent in simulate grid state - superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) + superiorGridAgentFSM ! WrappedActivation(Activation(3600)) // we expect a completion message val message = scheduler.expectMessageType[Completion] @@ -258,13 +261,15 @@ class DBFSAlgorithmSupGridSpec Vector(UUID.fromString("9fe5fa33-6d3b-4153-a829-a16f4347bc4e")) // send the start grid simulation trigger - superiorGridAgentFSM ! ActivationAdapter(Activation(3600)) + superiorGridAgentFSM ! WrappedActivation(Activation(3600)) // we expect a request for grid power values here for sweepNo $sweepNo val message = hvGrid.expectMessageType[GridAgentMessage] val lastSender = message match { - case PMAdapter(requestGridPowerMessage: RequestGridPowerMessage) => + case WrappedPowerMessage( + requestGridPowerMessage: RequestGridPowerMessage + ) => requestGridPowerMessage.currentSweepNo shouldBe sweepNo requestGridPowerMessage.nodeUuids should contain allElementsOf requestedConnectionNodeUuids @@ -278,7 +283,7 @@ class DBFSAlgorithmSupGridSpec // we return with a fake grid power message // / as we are using the ask pattern, we cannot send it to the grid agent directly but have to send it to the // / ask sender - lastSender ! PMAdapter( + lastSender ! WrappedPowerMessage( ProvideGridPowerMessage( requestedConnectionNodeUuids.map { uuid => ExchangePower( diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala index fe35899c69..27c542611c 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSMockGridAgents.scala @@ -6,21 +6,21 @@ package edu.ie3.simona.agent.grid -import edu.ie3.simona.agent.grid.GridAgentMessage.{PMAdapter, VMAdapter} -import org.apache.pekko.actor.typed.ActorRef +import edu.ie3.simona.agent.grid.GridAgentMessage.WrappedPowerMessage +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.agent.grid.VoltageMessage.{ + ProvideSlackVoltageMessage, + RequestSlackVoltageMessage, +} import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ ProvideGridPowerMessage, RequestGridPowerMessage, } -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage -import edu.ie3.simona.ontology.messages.VoltageMessage.{ - ProvideSlackVoltageMessage, - RequestSlackVoltageMessage, -} import edu.ie3.simona.test.common.UnitSpec import edu.ie3.util.scala.quantities.{Megavars, ReactivePower} import org.apache.pekko.actor.testkit.typed.scaladsl.TestProbe +import org.apache.pekko.actor.typed.ActorRef import squants.Power import squants.electro.Volts import squants.energy.Megawatts @@ -53,10 +53,10 @@ trait DBFSMockGridAgents extends UnitSpec { ) extends GAActorAndModel { def expectGridPowerRequest(): ActorRef[GridAgentMessage] = { - val message = gaProbe.expectMessageType[GridAgentMessage] - - message match { - case PMAdapter(requestGridPowerMessage: RequestGridPowerMessage) => + gaProbe.expectMessageType[GridAgentMessage] match { + case WrappedPowerMessage( + requestGridPowerMessage: RequestGridPowerMessage + ) => requestGridPowerMessage.nodeUuids should contain allElementsOf nodeUuids requestGridPowerMessage.sender @@ -67,10 +67,8 @@ trait DBFSMockGridAgents extends UnitSpec { expectedSweepNo: Int, expectedExchangedVoltages: Seq[ExchangeVoltage], ): Unit = { - val message = gaProbe.expectMessageType[GridAgentMessage] - - message match { - case VMAdapter(msg: ProvideSlackVoltageMessage) => + gaProbe.expectMessageType[GridAgentMessage] match { + case msg: ProvideSlackVoltageMessage => msg.currentSweepNo shouldBe expectedSweepNo msg.nodalSlackVoltages.size shouldBe expectedExchangedVoltages.size @@ -95,9 +93,7 @@ trait DBFSMockGridAgents extends UnitSpec { receiver: ActorRef[GridAgentMessage], sweepNo: Int, ): Unit = - receiver ! VMAdapter( - RequestSlackVoltageMessage(sweepNo, nodeUuids, gaProbe.ref) - ) + receiver ! RequestSlackVoltageMessage(sweepNo, nodeUuids, gaProbe.ref) } final case class SuperiorGA( @@ -108,12 +104,8 @@ trait DBFSMockGridAgents extends UnitSpec { def expectSlackVoltageRequest( expectedSweepNo: Int ): ActorRef[GridAgentMessage] = { - val message = gaProbe.expectMessageType[GridAgentMessage] - - message match { - case VMAdapter( - requestSlackVoltageMessage: RequestSlackVoltageMessage - ) => + gaProbe.expectMessageType[GridAgentMessage] match { + case requestSlackVoltageMessage: RequestSlackVoltageMessage => requestSlackVoltageMessage.currentSweepNo shouldBe expectedSweepNo requestSlackVoltageMessage.nodeUuids should have size nodeUuids.size requestSlackVoltageMessage.nodeUuids should contain allElementsOf nodeUuids @@ -126,10 +118,8 @@ trait DBFSMockGridAgents extends UnitSpec { expectedExchangedPowers: Seq[ExchangePower], maxDuration: FiniteDuration = 30 seconds, ): Unit = { - val message = gaProbe.expectMessageType[GridAgentMessage](maxDuration) - - message match { - case PMAdapter(msg: ProvideGridPowerMessage) => + gaProbe.expectMessageType[GridAgentMessage](maxDuration) match { + case WrappedPowerMessage(msg: ProvideGridPowerMessage) => msg.nodalResidualPower should have size expectedExchangedPowers.size expectedExchangedPowers.foreach { expectedPower => @@ -153,7 +143,7 @@ trait DBFSMockGridAgents extends UnitSpec { receiver: ActorRef[GridAgentMessage], sweepNo: Int, ): Unit = { - receiver ! PMAdapter( + receiver ! WrappedPowerMessage( RequestGridPowerMessage(sweepNo, nodeUuids, gaProbe.ref) ) } diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala index 243167c216..19120cbe35 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala @@ -9,14 +9,23 @@ package edu.ie3.simona.agent.grid import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgentMessage.StringAdapter +import edu.ie3.simona.agent.grid.GridAgentMessage.{ + FinishGridSimulationTrigger, + PrepareNextSweepTrigger, +} +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.io.result.ResultSinkType import edu.ie3.simona.sim.setup.SimonaStandaloneSetup import edu.ie3.simona.test.common.ConfigTestData import edu.ie3.simona.test.common.input.TransformerInputTestData import edu.ie3.simona.util.ResultFileHierarchy import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig -import org.apache.pekko.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + BehaviorTestKit, + ScalaTestWithActorTestKit, + TestProbe, +} +import org.apache.pekko.actor.typed.{ActorRef, Scheduler} import org.apache.pekko.actor.typed.receptionist.Receptionist.{ Listing, Register, @@ -29,9 +38,12 @@ import org.apache.pekko.actor.typed.scaladsl.adapter.{ TypedActorContextOps, TypedActorRefOps, } -import org.apache.pekko.actor.typed.{ActorRef, Scheduler} -import org.apache.pekko.actor.{ActorRef => classicRef} +import org.apache.pekko.actor.{ + ActorContext => ClassicContext, + ActorRef => ClassicRef, +} import org.apache.pekko.util.Timeout +import org.mockito.Mock import org.scalatest.wordspec.AnyWordSpecLike import java.util.concurrent.TimeUnit @@ -46,6 +58,19 @@ class GridAgentSetup2WSpec with LazyLogging { "The setup of grid agents" must { + + val scheduler = TestProbe("scheduler") + val runtimeEventListener = TestProbe[RuntimeEvent]("listener") + val primaryServiceProxy = TestProbe("primaryServiceProxy") + + val environmentRefs = EnvironmentRefs( + scheduler.ref.toClassic, + runtimeEventListener.ref, + primaryServiceProxy = primaryServiceProxy.ref.toClassic, + weather = ClassicRef.noSender, + evDataService = None, + ) + "provide two grid agents on presence of a two winding transformer" in { implicit val timeout: Timeout = Timeout(1, TimeUnit.SECONDS) @@ -58,19 +83,7 @@ class GridAgentSetup2WSpec ctx.system.receptionist ! Register(serviceKey, ctx.self) Behaviors.receive[GridAgentMessage] { - case (ctx, StringAdapter("ping", sender)) => - // replying to ping signal - sender ! StringAdapter("pong", ctx.self) - Behaviors.same - case (ctx, StringAdapter("setup", _)) => - val environmentRefs = EnvironmentRefs( - scheduler = ctx.self.toClassic, - runtimeEventListener = ctx.self.toClassic, - primaryServiceProxy = ctx.self.toClassic, - weather = classicRef.noSender, - evDataService = None, - ) - + case (ctx, PrepareNextSweepTrigger(tick)) => SimonaStandaloneSetup( typesafeConfig, ResultFileHierarchy( @@ -88,19 +101,23 @@ class GridAgentSetup2WSpec gridContainer.getSubGridTopologyGraph, ctx.toClassic, environmentRefs, - Seq.empty[classicRef], + Seq.empty[ClassicRef], ) - ctx.self ! StringAdapter("done", ctx.self) + + ctx.self ! FinishGridSimulationTrigger(tick) Behaviors.same + + case other => + fail(s"$other was not expected") } }) Await.ready( - actor.ask[GridAgentMessage](ref => StringAdapter("setup", ref)), + actor.ask[GridAgentMessage](_ => PrepareNextSweepTrigger(0)), Duration(10, TimeUnit.SECONDS), ) - testKit.spawn(Behaviors.setup[Listing] { ctx => + BehaviorTestKit(Behaviors.setup[Listing] { ctx => logger.debug("Subscribing to the actors.") ctx.system.receptionist ! Subscribe(serviceKey, ctx.self) diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala index 988e941400..e269e9c0e9 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala @@ -9,13 +9,22 @@ package edu.ie3.simona.agent.grid import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgentMessage.StringAdapter +import edu.ie3.simona.agent.grid.GridAgentMessage.{ + FinishGridSimulationTrigger, + PrepareNextSweepTrigger, +} +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.io.result.ResultSinkType import edu.ie3.simona.sim.setup.SimonaStandaloneSetup import edu.ie3.simona.test.common.{ConfigTestData, ThreeWindingTestData} import edu.ie3.simona.util.ResultFileHierarchy import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig -import org.apache.pekko.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit +import org.apache.pekko.actor.testkit.typed.scaladsl.{ + BehaviorTestKit, + ScalaTestWithActorTestKit, + TestProbe, +} +import org.apache.pekko.actor.typed.{ActorRef, Scheduler} import org.apache.pekko.actor.typed.receptionist.Receptionist.{ Listing, Register, @@ -24,12 +33,11 @@ import org.apache.pekko.actor.typed.receptionist.Receptionist.{ import org.apache.pekko.actor.typed.receptionist.ServiceKey import org.apache.pekko.actor.typed.scaladsl.AskPattern.Askable import org.apache.pekko.actor.typed.scaladsl.Behaviors -import org.apache.pekko.actor.typed.scaladsl.adapter.{ - TypedActorContextOps, - TypedActorRefOps, +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps +import org.apache.pekko.actor.{ + ActorContext => ClassicContext, + ActorRef => ClassicRef, } -import org.apache.pekko.actor.typed.{ActorRef, Scheduler} -import org.apache.pekko.actor.{ActorRef => classicRef} import org.apache.pekko.util.Timeout import org.scalatest.wordspec.AnyWordSpecLike @@ -45,6 +53,19 @@ class GridAgentSetup3WSpec with LazyLogging { "The setup of grid agents" must { + + val scheduler = TestProbe("scheduler") + val runtimeEventListener = TestProbe[RuntimeEvent]("listener") + val primaryServiceProxy = TestProbe("primaryServiceProxy") + + val environmentRefs = EnvironmentRefs( + scheduler.ref.toClassic, + runtimeEventListener.ref, + primaryServiceProxy = primaryServiceProxy.ref.toClassic, + weather = ClassicRef.noSender, + evDataService = None, + ) + "provide three grid agents on presence of a three winding transformer" in { implicit val timeout: Timeout = Timeout(1, TimeUnit.SECONDS) implicit val scheduler: Scheduler = system.scheduler @@ -56,20 +77,7 @@ class GridAgentSetup3WSpec ctx.system.receptionist ! Register(serviceKey, ctx.self) Behaviors.receive[GridAgentMessage] { - case (ctx, StringAdapter("ping", sender)) => - // replying to ping signal - sender ! StringAdapter("pong", ctx.self) - Behaviors.same - - case (ctx, StringAdapter("setup", _)) => - val environmentRefs = EnvironmentRefs( - scheduler = ctx.self.toClassic, - runtimeEventListener = ctx.self.toClassic, - primaryServiceProxy = ctx.self.toClassic, - weather = classicRef.noSender, - evDataService = None, - ) - + case (ctx, PrepareNextSweepTrigger(tick)) => SimonaStandaloneSetup( typesafeConfig, ResultFileHierarchy( @@ -85,21 +93,24 @@ class GridAgentSetup3WSpec ), ).buildSubGridToActorRefMap( threeWindingTestGrid.getSubGridTopologyGraph, - ctx.toClassic, + ctx.asInstanceOf[ClassicContext], environmentRefs, - Seq.empty[classicRef], + Seq.empty[ClassicRef], ) - ctx.self ! StringAdapter("done", ctx.self) + ctx.self ! FinishGridSimulationTrigger(tick) Behaviors.same + + case other => + fail(s"$other was not expected") } }) Await.ready( - actor.ask[GridAgentMessage](ref => StringAdapter("setup", ref)), + actor.ask[GridAgentMessage](_ => PrepareNextSweepTrigger(0)), Duration(10, TimeUnit.SECONDS), ) - testKit.spawn(Behaviors.setup[Listing] { ctx => + BehaviorTestKit(Behaviors.setup[Listing] { ctx => logger.debug("Subscribing to the actors.") ctx.system.receptionist ! Subscribe(serviceKey, ctx.self) diff --git a/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala index 53e17242e7..070e771241 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala @@ -9,7 +9,7 @@ package edu.ie3.simona.agent.grid import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower -import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.common.model.grid.BasicGridWithSwitches import edu.ie3.util.quantities.QuantityUtils.RichQuantityDouble @@ -41,8 +41,7 @@ class PowerFlowSupportSpec with PowerFlowSupport with GridResultsSupport { - implicit val log: Logger = - LoggerFactory.getLogger(PowerFlowSupportSpec.super.getClass) + implicit val log: Logger = LoggerFactory.getLogger(this.getClass) val actorRef: ActorRef[GridAgentMessage] = TestProbe[GridAgentMessage]("noSender").ref diff --git a/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala index 3d24cdd038..378c08c1ef 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/ReceivedValuesStoreSpec.scala @@ -24,22 +24,22 @@ class ReceivedValuesStoreSpec with SubGridGateMokka { // test actorRefs - val actorProbe1: TestProbe[ParticipantMessage] = + val participant1: TestProbe[ParticipantMessage] = TestProbe[ParticipantMessage]() - val actorProbe2: TestProbe[ParticipantMessage] = + val participant2: TestProbe[ParticipantMessage] = TestProbe[ParticipantMessage]() - val actorProbe3: TestProbe[ParticipantMessage] = + val participant3: TestProbe[ParticipantMessage] = TestProbe[ParticipantMessage]() - val actorProbe4: TestProbe[GridAgentMessage] = TestProbe[GridAgentMessage]() + val gridAgent: TestProbe[GridAgentMessage] = TestProbe[GridAgentMessage]() // test data used by almost all tests // / node to asset agents mapping val nodeToAssetAgentsMap: Map[UUID, Set[ActorRef[ParticipantMessage]]] = Map( UUID.fromString("dd9a5b54-94bb-4201-9108-2b1b7d689546") -> Set( - actorProbe1.ref + participant1.ref ), UUID.fromString("34e807f1-c62b-4968-b0f6-980ce500ff97") -> Set( - actorProbe2.ref + participant2.ref ), ) @@ -51,7 +51,7 @@ class ReceivedValuesStoreSpec 1, UUID.fromString("1676360a-c7c4-43a9-a667-90ddfe8a18e6"), 2, - ) -> actorProbe4.ref + ) -> gridAgent.ref ) // / superior grid nodeUuid vector @@ -93,13 +93,13 @@ class ReceivedValuesStoreSpec receivedValuesStore.nodeToReceivedPower.size shouldBe 3 receivedValuesStore.nodeToReceivedPower( UUID.fromString("dd9a5b54-94bb-4201-9108-2b1b7d689546") - ) shouldBe Map(actorProbe1.ref -> None) + ) shouldBe Map(participant1.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("34e807f1-c62b-4968-b0f6-980ce500ff97") - ) shouldBe Map(actorProbe2.ref -> None) + ) shouldBe Map(participant2.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("5cd55ab5-a7d2-499f-a25f-6dbc3845c5e8") - ) shouldBe Map(actorProbe4.ref -> None) + ) shouldBe Map(gridAgent.ref -> None) receivedValuesStore.nodeToReceivedSlackVoltage.size shouldBe 1 receivedValuesStore.nodeToReceivedSlackVoltage( @@ -113,11 +113,11 @@ class ReceivedValuesStoreSpec val nodeToAssetAgentsMap = Map( UUID.fromString("dd9a5b54-94bb-4201-9108-2b1b7d689546") -> Set( - actorProbe1.ref + participant1.ref ), UUID.fromString("34e807f1-c62b-4968-b0f6-980ce500ff97") -> Set( - actorProbe2.ref, - actorProbe3.ref, + participant2.ref, + participant3.ref, ), ) @@ -137,12 +137,12 @@ class ReceivedValuesStoreSpec receivedValuesStore.nodeToReceivedPower.size shouldBe 2 receivedValuesStore.nodeToReceivedPower( UUID.fromString("dd9a5b54-94bb-4201-9108-2b1b7d689546") - ) shouldBe Map(actorProbe1.ref -> None) + ) shouldBe Map(participant1.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("34e807f1-c62b-4968-b0f6-980ce500ff97") ) shouldBe Map( - actorProbe2.ref -> None, - actorProbe3.ref -> None, + participant2.ref -> None, + participant3.ref -> None, ) } @@ -163,13 +163,13 @@ class ReceivedValuesStoreSpec receivedValuesStore.nodeToReceivedPower.size shouldBe 3 receivedValuesStore.nodeToReceivedPower( UUID.fromString("dd9a5b54-94bb-4201-9108-2b1b7d689546") - ) shouldBe Map(actorProbe1.ref -> None) + ) shouldBe Map(participant1.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("34e807f1-c62b-4968-b0f6-980ce500ff97") - ) shouldBe Map(actorProbe2.ref -> None) + ) shouldBe Map(participant2.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("5cd55ab5-a7d2-499f-a25f-6dbc3845c5e8") - ) shouldBe Map(actorProbe4.ref -> None) + ) shouldBe Map(gridAgent.ref -> None) } @@ -222,10 +222,10 @@ class ReceivedValuesStoreSpec receivedValuesStore.nodeToReceivedPower.size shouldBe 2 receivedValuesStore.nodeToReceivedPower( UUID.fromString("dd9a5b54-94bb-4201-9108-2b1b7d689546") - ) shouldBe Map(actorProbe1.ref -> None) + ) shouldBe Map(participant1.ref -> None) receivedValuesStore.nodeToReceivedPower( UUID.fromString("34e807f1-c62b-4968-b0f6-980ce500ff97") - ) shouldBe Map(actorProbe2.ref -> None) + ) shouldBe Map(participant2.ref -> None) } diff --git a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala index f3811556c3..7ce21d9cdd 100644 --- a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala @@ -7,9 +7,9 @@ package edu.ie3.simona.sim.setup import org.apache.pekko.actor.{ - ActorContext, - ActorRef => classicRef, ActorSystem, + ActorContext, + ActorRef => ClassicRef, } import org.apache.pekko.actor.typed.ActorRef import edu.ie3.datamodel.exceptions.NotImplementedException @@ -40,31 +40,31 @@ class SimonaSetupSpec extends UnitSpec with SimonaSetup with SubGridGateMokka { override def systemParticipantsListener( context: ActorContext - ): Seq[classicRef] = throw new NotImplementedException( + ): Seq[ClassicRef] = throw new NotImplementedException( "This is a dummy setup" ) override def primaryServiceProxy( context: ActorContext, - scheduler: classicRef, - ): classicRef = + scheduler: ClassicRef, + ): ClassicRef = throw new NotImplementedException("This is a dummy setup") override def weatherService( context: ActorContext, - scheduler: classicRef, - ): classicRef = + scheduler: ClassicRef, + ): ClassicRef = throw new NotImplementedException("This is a dummy setup") override def extSimulations( context: ActorContext, - scheduler: classicRef, + scheduler: ClassicRef, ): ExtSimSetupData = throw new NotImplementedException("This is a dummy setup") override def timeAdvancer( context: ActorContext, - simulation: classicRef, + simulation: ClassicRef, runtimeEventListener: ActorRef[RuntimeEvent], ): ActorRef[TimeAdvancer.Incoming] = throw new NotImplementedException("This is a dummy setup") @@ -72,12 +72,12 @@ class SimonaSetupSpec extends UnitSpec with SimonaSetup with SubGridGateMokka { override def scheduler( context: ActorContext, timeAdvancer: ActorRef[TimeAdvancer.Incoming], - ): classicRef = throw new NotImplementedException("This is a dummy setup") + ): ClassicRef = throw new NotImplementedException("This is a dummy setup") override def gridAgents( context: ActorContext, environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[classicRef], + systemParticipantListener: Seq[ClassicRef], ): Iterable[ActorRef[GridAgentMessage]] = throw new NotImplementedException("This is a dummy setup") From a806229639483b96bc96cb4aa839c9792024f73e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 14 Feb 2024 17:55:21 +0100 Subject: [PATCH 071/123] remove wrong entry in changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e36f22096d..ea7a458337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,7 +54,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Relevant scientific papers have been added to the documentation [#139](https://github.com/ie3-institute/simona/issues/139) - Add troubleshooting section to Users guide [#160](https://github.com/ie3-institute/simona/issues/160) - Added Kafka sink for results [#24](https://github.com/ie3-institute/simona/issues/24) -- Config possibility for transformer control groups [#90](https://github.com/ie3-institute/simona/issues/90) - Added Kafka sink for runtime events, re-implemented RuntimeEventListener in akka typed [#242](https://github.com/ie3-institute/simona/issues/242) - Added listeners to DBFS tests to check the result output and check the handling of failed power flows [#269](https://github.com/ie3-institute/simona/issues/269) - Added DBFS test with participant load and added testing for FinishGridSimulationTrigger [#281](https://github.com/ie3-institute/simona/issues/281) From e629b7a92036d3369a6d5855af296531e17b4b8a Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 09:34:11 +0100 Subject: [PATCH 072/123] measurementsConfigs as Set --- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 5c190e7f74..624f7783aa 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -608,7 +608,7 @@ object GridModel { case TransformerControlGroup(measurements, _, vMax, vMin) => buildTransformerControlGroupModel( measurementUnitInput, - measurements, + measurements.toSet, vMax, vMin, ) @@ -632,7 +632,7 @@ object GridModel { */ private def buildTransformerControlGroupModel( measurementUnitInput: java.util.Set[MeasurementUnitInput], - measurementConfigs: List[String], + measurementConfigs: Set[String], vMax: Double, vMin: Double, ): ControlGroupModel = { @@ -653,7 +653,7 @@ object GridModel { */ private def determineNodeUuids( measurementUnitInput: java.util.Set[MeasurementUnitInput], - measurementConfigs: List[String], + measurementConfigs: Set[String], ): Set[UUID] = Set.from( measurementUnitInput.asScala .filter(input => From 70934be3ae0090f8b0aa23c9c24a8e9a779a5abc Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 09:37:45 +0100 Subject: [PATCH 073/123] renaming config-template --- gradle/scripts/tscfg.gradle | 2 +- ...fig-template.conf => config-template.conf} | 0 .../edu/ie3/simona/config/SimonaConfig.scala | 78 +++++++++---------- 3 files changed, 40 insertions(+), 40 deletions(-) rename src/main/resources/config/{simona-config-template.conf => config-template.conf} (100%) diff --git a/gradle/scripts/tscfg.gradle b/gradle/scripts/tscfg.gradle index d9ee8bca7b..0f94fba657 100644 --- a/gradle/scripts/tscfg.gradle +++ b/gradle/scripts/tscfg.gradle @@ -15,7 +15,7 @@ task genConfigClass { args = [ "build/tscfg-${tscfgVersion}.jar", "--spec", - "src/main/resources/config/simona-config-template.conf", + "src/main/resources/config/config-template.conf", "--scala", "--durations", "--pn", diff --git a/src/main/resources/config/simona-config-template.conf b/src/main/resources/config/config-template.conf similarity index 100% rename from src/main/resources/config/simona-config-template.conf rename to src/main/resources/config/config-template.conf diff --git a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala index f5dd2fdf3b..f122d05d39 100644 --- a/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala +++ b/src/main/scala/edu/ie3/simona/config/SimonaConfig.scala @@ -752,45 +752,6 @@ object SimonaConfig { } - final case class TransformerControlGroup( - measurements: scala.List[java.lang.String], - transformers: scala.List[java.lang.String], - vMax: scala.Double, - vMin: scala.Double, - ) - object TransformerControlGroup { - def apply( - c: com.typesafe.config.Config, - parentPath: java.lang.String, - $tsCfgValidator: $TsCfgValidator, - ): SimonaConfig.TransformerControlGroup = { - SimonaConfig.TransformerControlGroup( - measurements = - $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), - transformers = - $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), - vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), - vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator), - ) - } - private def $_reqDbl( - parentPath: java.lang.String, - c: com.typesafe.config.Config, - path: java.lang.String, - $tsCfgValidator: $TsCfgValidator, - ): scala.Double = { - if (c == null) 0 - else - try c.getDouble(path) - catch { - case e: com.typesafe.config.ConfigException => - $tsCfgValidator.addBadPath(parentPath + path, e) - 0 - } - } - - } - final case class SimpleOutputConfig( override val notifier: java.lang.String, override val simulationResult: scala.Boolean, @@ -841,6 +802,45 @@ object SimonaConfig { } + final case class TransformerControlGroup( + measurements: scala.List[java.lang.String], + transformers: scala.List[java.lang.String], + vMax: scala.Double, + vMin: scala.Double, + ) + object TransformerControlGroup { + def apply( + c: com.typesafe.config.Config, + parentPath: java.lang.String, + $tsCfgValidator: $TsCfgValidator, + ): SimonaConfig.TransformerControlGroup = { + SimonaConfig.TransformerControlGroup( + measurements = + $_L$_str(c.getList("measurements"), parentPath, $tsCfgValidator), + transformers = + $_L$_str(c.getList("transformers"), parentPath, $tsCfgValidator), + vMax = $_reqDbl(parentPath, c, "vMax", $tsCfgValidator), + vMin = $_reqDbl(parentPath, c, "vMin", $tsCfgValidator), + ) + } + private def $_reqDbl( + parentPath: java.lang.String, + c: com.typesafe.config.Config, + path: java.lang.String, + $tsCfgValidator: $TsCfgValidator, + ): scala.Double = { + if (c == null) 0 + else + try c.getDouble(path) + catch { + case e: com.typesafe.config.ConfigException => + $tsCfgValidator.addBadPath(parentPath + path, e) + 0 + } + } + + } + final case class VoltLvlConfig( id: java.lang.String, vNom: java.lang.String, From 628908bcb0baa5057d9234dd4abaabf5320403c5 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 09:50:51 +0100 Subject: [PATCH 074/123] renaming TransformerControlGroup to TransformerControlGroupModel --- ...ala => TransformerControlGroupModel.scala} | 6 ++--- .../edu/ie3/simona/model/grid/GridModel.scala | 27 ++++++++++--------- ...=> TransformerControlGroupModelSpec.scala} | 9 ++++--- .../edu/ie3/simona/model/grid/GridSpec.scala | 10 +++---- 4 files changed, 27 insertions(+), 25 deletions(-) rename src/main/scala/edu/ie3/simona/model/control/{TransformerControlGroup.scala => TransformerControlGroupModel.scala} (92%) rename src/test/scala/edu/ie3/simona/model/control/{TransformerControlGroupSpec.scala => TransformerControlGroupModelSpec.scala} (94%) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala similarity index 92% rename from src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala rename to src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index 3db869c582..ada32e4fb0 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroup.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -9,7 +9,7 @@ package edu.ie3.simona.model.control import breeze.math.Complex import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult -import edu.ie3.simona.model.control.TransformerControlGroup.RegulationCriterion +import edu.ie3.simona.model.control.TransformerControlGroupModel.RegulationCriterion import java.util.UUID import squants.Dimensionless @@ -25,7 +25,7 @@ import squants.Dimensionless * Partial function to harmonize different, possible contradictory regulation * needs */ -final case class TransformerControlGroup( +final case class TransformerControlGroupModel( nodalRegulationCriterion: Map[UUID, RegulationCriterion], harmonizeRegulationNeeds: Array[Dimensionless] => Option[Dimensionless], ) { @@ -66,7 +66,7 @@ final case class TransformerControlGroup( } } -object TransformerControlGroup { +object TransformerControlGroupModel { type RegulationCriterion = Complex => Option[Dimensionless] } diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 624f7783aa..15c0bda9a7 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -16,9 +16,7 @@ import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.SystemComponent -import edu.ie3.simona.model.control.{ - TransformerControlGroup => ControlGroupModel -} +import edu.ie3.simona.model.control.TransformerControlGroupModel import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseA, @@ -99,13 +97,13 @@ object GridModel { * Transformer control groups */ final case class GridControls( - transformerControlGroups: Set[ControlGroupModel] + transformerControlGroups: Set[TransformerControlGroupModel] ) - /** Represents an empty Transformer control groups + /** Represents an empty Transformer control group */ val emptyGridControls: GridControls = GridControls( - Set.empty[ControlGroupModel] + Set.empty[TransformerControlGroupModel] ) /** Checks the availability of node calculation models, that are connected by @@ -571,7 +569,7 @@ object GridModel { subGridContainer.getRawGrid.getMeasurementUnits, ) } - .getOrElse(Set.empty[ControlGroupModel]) + .getOrElse(Set.empty[TransformerControlGroupModel]) /* Build grid related control strategies */ val gridControls = GridControls(transformerControlGroups) @@ -604,7 +602,7 @@ object GridModel { private def buildTransformerControlGroups( config: List[SimonaConfig.TransformerControlGroup], measurementUnitInput: java.util.Set[MeasurementUnitInput], - ): Set[ControlGroupModel] = config.map { + ): Set[TransformerControlGroupModel] = config.map { case TransformerControlGroup(measurements, _, vMax, vMin) => buildTransformerControlGroupModel( measurementUnitInput, @@ -628,14 +626,14 @@ object GridModel { * @param vMin * Lower permissible voltage magnitude * @return - * A [[ControlGroupModel]] + * A [[TransformerControlGroupModel]] */ private def buildTransformerControlGroupModel( measurementUnitInput: java.util.Set[MeasurementUnitInput], measurementConfigs: Set[String], vMax: Double, vMin: Double, - ): ControlGroupModel = { + ): TransformerControlGroupModel = { val nodeUuids = determineNodeUuids(measurementUnitInput, measurementConfigs) buildTransformerControlModels(nodeUuids, vMax, vMin) @@ -673,13 +671,13 @@ object GridModel { * @param vMin * Lower permissible voltage magnitude * @return - * A [[ControlGroupModel]] + * A [[TransformerControlGroupModel]] */ private def buildTransformerControlModels( nodeUuids: Set[UUID], vMax: Double, vMin: Double, - ): ControlGroupModel = { + ): TransformerControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => uuid -> { (complexVoltage: Complex) => @@ -715,7 +713,10 @@ object GridModel { } - ControlGroupModel(nodeUuidToRegulationCriterion, harmonizationFunction) + TransformerControlGroupModel( + nodeUuidToRegulationCriterion, + harmonizationFunction, + ) } /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala similarity index 94% rename from src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala rename to src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala index 2d6c6adbf6..2ea7876057 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala @@ -18,12 +18,13 @@ import squants.{Dimensionless, Each} import java.util.UUID -class TransformerControlGroupSpec extends UnitSpec with QuantityMatchers { +class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { implicit val tolerance: Dimensionless = Each(1e-10) "Checking the function of transformer control groups" should { - val buildTransformerControlModels = PrivateMethod[TransformerControlGroup]( - Symbol("buildTransformerControlModels") - ) + val buildTransformerControlModels = + PrivateMethod[TransformerControlGroupModel]( + Symbol("buildTransformerControlModels") + ) implicit val tolerance: Dimensionless = Each(1e-10) val dut = GridModel invokePrivate buildTransformerControlModels( Set( diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index b13da303ec..b0280a2534 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -14,7 +14,7 @@ import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException -import edu.ie3.simona.model.control.TransformerControlGroup +import edu.ie3.simona.model.control.TransformerControlGroupModel import edu.ie3.simona.model.grid.GridModel.{ emptyGridControls, GridComponents, @@ -214,7 +214,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], switches, ), - GridControls(Set.empty[TransformerControlGroup]), + GridControls(Set.empty[TransformerControlGroupModel]), ) // get the private method for validation val validateConnectivity: PrivateMethod[Unit] = @@ -243,7 +243,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], Set.empty[SwitchModel], ), - GridControls(Set.empty[TransformerControlGroup]), + GridControls(Set.empty[TransformerControlGroupModel]), ) // get the private method for validation @@ -394,7 +394,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], switches, ), - GridControls(Set.empty[TransformerControlGroup]), + GridControls(Set.empty[TransformerControlGroupModel]), ) // update the uuidToIndexMap @@ -446,7 +446,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { Set.empty[Transformer3wModel], Set.empty[SwitchModel], ), - GridControls(Set.empty[TransformerControlGroup]), + GridControls(Set.empty[TransformerControlGroupModel]), ) // update the uuidToIndexMap From 48966357fc99212f56b5bdc9bbb8adbb93685e88 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 09:54:18 +0100 Subject: [PATCH 075/123] emptyGridControls as def --- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 15c0bda9a7..f9c902f8b0 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -102,7 +102,7 @@ object GridModel { /** Represents an empty Transformer control group */ - val emptyGridControls: GridControls = GridControls( + def emptyGridControls: GridControls = GridControls( Set.empty[TransformerControlGroupModel] ) From bc37db363296d0f354c65b2863decc279f9896a5 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 10:42:41 +0100 Subject: [PATCH 076/123] fix GridSpec --- src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index b0280a2534..f1dd5c4460 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -536,7 +536,7 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { false, ), ).asJava - val selectedMeasurements = List( + val selectedMeasurements = Set( "ab66fbb0-ece1-44b9-9341-86a884233ec4", "93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d", "8e84eb8a-2940-4900-b0ce-0eeb6bca8bae", From c4f3c735120cef4780d3f15f406eff90c0201b75 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 17:35:38 +0100 Subject: [PATCH 077/123] refactor GA FailFast and move into GridModel validation --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 6 +- .../simona/agent/grid/GridAgentFailFast.scala | 106 ------------------ .../edu/ie3/simona/model/grid/GridModel.scala | 94 +++++++++++++++- .../edu/ie3/simona/model/grid/GridSpec.scala | 30 ++++- 4 files changed, 120 insertions(+), 116 deletions(-) delete mode 100644 src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index d25f28d1bc..5a7d265835 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -154,9 +154,6 @@ class GridAgent( Activation(INIT_SIM_TICK), gridAgentInitData: GridAgentInitData, ) => - // fail fast sanity checks - GridAgentFailFast.failFast(gridAgentInitData, simonaConfig) - log.debug( s"Inferior Subnets: {}; Inferior Subnet Nodes: {}", gridAgentInitData.inferiorGridIds, @@ -188,7 +185,8 @@ class GridAgent( TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.endDateTime ), - simonaConfig.simona.control, + gridAgentInitData, + simonaConfig, ) /* Reassure, that there are also calculation models for the given uuids */ diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala deleted file mode 100644 index 4e45a97cb7..0000000000 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentFailFast.scala +++ /dev/null @@ -1,106 +0,0 @@ -/* - * © 2022. TU Dortmund University, - * Institute of Energy Systems, Energy Efficiency and Energy Economics, - * Research group Distribution grid planning and operation - */ - -package edu.ie3.simona.agent.grid - -import edu.ie3.datamodel.models.input.container.SubGridContainer -import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.config.SimonaConfig -import edu.ie3.simona.exceptions.agent.GridAgentInitializationException - -import java.util.UUID -import scala.jdk.CollectionConverters._ - -object GridAgentFailFast { - - /** FailFast Check of GridAgent at Initialisation - * @param gridAgentInitData - * Data that is send to the [[GridAgent]] directly after startup. It - * contains the main information for initialization. - * @param simonaConfig - * the config that should be checked - */ - def failFast( - gridAgentInitData: GridAgentInitData, - simonaConfig: SimonaConfig, - ): Unit = { - - /** Check if there is InitData for superior or inferior GridGates - */ - if ( - gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty - ) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + - s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" - ) - - /** Check if there exits voltage measurements for transformerControlGroups - */ - - checkControlGroupsForMeasurement( - gridAgentInitData.subGridContainer, - simonaConfig.simona.control, - ) - } - - /** Checks all ControlGroups if a) Transformer of ControlGroup and Measurement - * belongs to the same sub grid. b) Measurements are measure voltage - * magnitude. - * - * @param subGridContainer - * Container of all models for this sub grid - * @param maybeControlConfig - * Config of ControlGroup - */ - def checkControlGroupsForMeasurement( - subGridContainer: SubGridContainer, - maybeControlConfig: Option[SimonaConfig.Simona.Control], - ): Unit = { - - val measurementUnits = - subGridContainer.getRawGrid.getMeasurementUnits.asScala - - val transformerUnits2W = - subGridContainer.getRawGrid.getTransformer2Ws.asScala - - val transformerUnits3W = - subGridContainer.getRawGrid.getTransformer3Ws.asScala - - maybeControlConfig.foreach(control => - control.transformer.foreach(controlGroup => - controlGroup.transformers.map(UUID.fromString).foreach { transformer => - val transformerUnit2W = transformerUnits2W - .find(_.getUuid == transformer) - val transformerUnit3W = transformerUnits3W - .find(_.getUuid == transformer) - - /** In order to check that the measurements are located in the subgrid - * of this GridAgent, it is first checked if the transformer belongs - * to this GridAgent and is therefore part of this subgrid. - */ - if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { - controlGroup.measurements - .map(UUID.fromString) - .foreach { measurement => - val measurementUnit = measurementUnits - .find(_.getUuid == measurement) - .getOrElse( - throw new GridAgentInitializationException( - s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exists in this subnet." - ) - ) - if (!measurementUnit.getVMag) - throw new GridAgentInitializationException( - s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." - ) - } - } - } - ) - ) - } -} diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index f9c902f8b0..0c05990f13 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -12,9 +12,11 @@ import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.input.connector._ import edu.ie3.datamodel.models.input.container.SubGridContainer +import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException +import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.SystemComponent import edu.ie3.simona.model.control.TransformerControlGroupModel import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} @@ -71,13 +73,15 @@ object GridModel { refSystem: RefSystem, startDate: ZonedDateTime, endDate: ZonedDateTime, - controlConfig: Option[SimonaConfig.Simona.Control], + gridAgentInitData: GridAgentInitData, + simonaConfig: SimonaConfig, ): GridModel = buildAndValidate( subGridContainer, refSystem, startDate, endDate, - controlConfig, + gridAgentInitData, + simonaConfig, ) /** structure that represents all grid components that are needed by a grid @@ -472,12 +476,79 @@ object GridModel { } + private def checkForGridGates(gridAgentInitData: GridAgentInitData): Unit = { + if ( + gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty + ) + throw new GridAgentInitializationException( + s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + + s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" + ) + } + + /** Checks all ControlGroups if a) Transformer of ControlGroup and Measurement + * belongs to the same sub grid. b) Measurements are measure voltage + * magnitude. + * + * @param subGridContainer + * Container of all models for this sub grid + * @param maybeControlConfig + * Config of ControlGroup + */ + private def checkControlGroupsForMeasurement( + subGridContainer: SubGridContainer, + maybeControlConfig: Option[SimonaConfig.Simona.Control], + ): Unit = { + + val measurementUnits = + subGridContainer.getRawGrid.getMeasurementUnits.asScala + .map(measurement => measurement.getUuid -> measurement) + .toMap + + val transformerUnits2W = + subGridContainer.getRawGrid.getTransformer2Ws.asScala + .map(transformer2w => transformer2w.getUuid -> transformer2w) + .toMap + + val transformerUnits3W = + subGridContainer.getRawGrid.getTransformer3Ws.asScala + .map(transformer3w => transformer3w.getUuid -> transformer3w) + .toMap + + maybeControlConfig.foreach(control => + control.transformer.foreach(controlGroup => + controlGroup.transformers.map(UUID.fromString).foreach { transformer => + val transformerUnit2W = transformerUnits2W.get(transformer) + val transformerUnit3W = transformerUnits3W.get(transformer) + + if (transformerUnit2W.isDefined || transformerUnit3W.isDefined) { + controlGroup.measurements + .map(UUID.fromString) + .foreach { measurement => + val measurementUnit = measurementUnits.getOrElse( + measurement, + throw new GridAgentInitializationException( + s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exist in this subnet." + ), + ) + if (!measurementUnit.getVMag) + throw new GridAgentInitializationException( + s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." + ) + } + } + } + ) + ) + } + private def buildAndValidate( subGridContainer: SubGridContainer, refSystem: RefSystem, startDate: ZonedDateTime, endDate: ZonedDateTime, - maybeControlConfig: Option[SimonaConfig.Simona.Control], + gridAgentInitData: GridAgentInitData, + simonaConfig: SimonaConfig, ): GridModel = { // build @@ -562,6 +633,12 @@ object GridModel { ) /* Build transformer control groups */ + val maybeControlConfig: Option[SimonaConfig.Simona.Control] = + simonaConfig.simona.control match { + case Some(control) => simonaConfig.simona.control + case None => None + } + val transformerControlGroups = maybeControlConfig .map { controlConfig => buildTransformerControlGroups( @@ -582,9 +659,20 @@ object GridModel { gridControls, ) + /** Check and validates the grid. Especially the consistency of the grid + * model the connectivity of the grid model if there is InitData for + * superior or inferior GridGates if there exits voltage measurements for + * transformerControlGroups + */ + // validate validateConsistency(gridModel) validateConnectivity(gridModel) + checkForGridGates(gridAgentInitData) + checkControlGroupsForMeasurement( + gridAgentInitData.subGridContainer, + simonaConfig.simona.control, + ) // return gridModel diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index f1dd5c4460..be089f18f1 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -13,6 +13,8 @@ import breeze.numerics.abs import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils +import edu.ie3.simona.agent.grid.DBFSMockGridAgents +import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.TransformerControlGroupModel import edu.ie3.simona.model.grid.GridModel.{ @@ -28,10 +30,20 @@ import edu.ie3.simona.test.common.model.grid.{ } import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} import testutils.TestObjectFactory - +import edu.ie3.simona.test.common.model.grid.DbfsTestGrid +import org.apache.pekko.testkit.TestProbe +import edu.ie3.simona.test.common.ConfigTestData +import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import scala.jdk.CollectionConverters.SetHasAsJava +import edu.ie3.datamodel.models.input.container.ThermalGrid -class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { +class GridSpec + extends UnitSpec + with LineInputTestData + with DefaultTestData + with DbfsTestGrid + with DBFSMockGridAgents + with ConfigTestData { private val _printAdmittanceMatrixOnMismatch : (DenseMatrix[Complex], DenseMatrix[Complex]) => Unit = { @@ -552,12 +564,24 @@ class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData { } "process a valid GridInputModel without an Exception" in new GridInputTestData { + val simonaConfig: SimonaConfig = SimonaConfig(typesafeConfig) + private val superiorGridAgent = SuperiorGA( + TestProbe("superiorGridAgent_1000"), + Seq(supNodeA.getUuid), + ) + GridModel( validTestGridInputModel, gridInputModelTestDataRefSystem, defaultSimulationStart, defaultSimulationEnd, - controlConfig = None, + GridAgentInitData( + hvGridContainer, + Seq.empty[ThermalGrid], + superiorGridAgent.ref, + RefSystem("2000 MVA", "110 kV"), + ), + simonaConfig, ) } } From b8028cf1111a8344136118475d694b4c8d68cd41 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 18:04:14 +0100 Subject: [PATCH 078/123] add transformer control group config parameters to config.md --- docs/readthedocs/config.md | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/readthedocs/config.md b/docs/readthedocs/config.md index 91a6d952a5..52b2caef92 100644 --- a/docs/readthedocs/config.md +++ b/docs/readthedocs/config.md @@ -236,3 +236,42 @@ Secondary convergence criterion for the power flow calculation is the number of Resolution of the power flow calculation: `simona.powerflow.resolution = "3600s"` + +## Transformer Control Group configuration + +It's possible to add a voltage control function to a transformer or group of transformers. This requires measurements within the network to be under voltage control and at least one corresponding transformer. +The voltage control will attempt to adjust the voltage by changing the tap position of the corresponding transformer. If changing the tap position would cause a voltage limit to be exceeded, the initial voltage deviation cannot be reduced by the voltage control system. + +Transformer control groups must contain at least one transformer and one measurement. And can be configured as shown in this example for two transformer control groups: +``` +simona.control.transformer = [ +{ +transformers = ["31a2b9bf-e785-4475-aa44-1c34646e8c79"], +measurements = ["923f2d69-3093-4198-86e4-13d2d1c220f8"], +vMin = 0.98, +vMax = 1.02 +} +, { +transformers = ["1132dbf4-e8a1-44ae-8415-f42d4497aa1d"], +measurements = ["7686b818-a0ba-465c-8e4e-f7d3c4e171fc"], +vMin = 0.98, +vMax = 1.02 +} +] +``` + +UUID of transformer in control group: + +`transformers = ["31a2b9bf-e785-4475-aa44-1c34646e8c79"]` + +UUID of measurement in control group: + +`measurements = ["923f2d69-3093-4198-86e4-13d2d1c220f8"]` + +Minimum Voltage Limit in p.u.: + +`vMin = 0.98` + +Maximum Voltage Limit in p.u.: + +`vMin = 1.02` \ No newline at end of file From ff70c4c8b1f4b89873d7206759b809ae76d7b1b7 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 15 Feb 2024 18:06:31 +0100 Subject: [PATCH 079/123] add transformer control group config parameters to config.md --- docs/readthedocs/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readthedocs/config.md b/docs/readthedocs/config.md index 52b2caef92..f1db2fc5b6 100644 --- a/docs/readthedocs/config.md +++ b/docs/readthedocs/config.md @@ -274,4 +274,4 @@ Minimum Voltage Limit in p.u.: Maximum Voltage Limit in p.u.: -`vMin = 1.02` \ No newline at end of file +`vMax = 1.02` \ No newline at end of file From 19301f3466a6b046f56a06064feca86d9acb891e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 16 Feb 2024 08:56:01 +0100 Subject: [PATCH 080/123] move measurement_control.md --- docs/readthedocs/models.md | 2 +- docs/readthedocs/{ => models}/measurement_control.md | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/readthedocs/{ => models}/measurement_control.md (100%) diff --git a/docs/readthedocs/models.md b/docs/readthedocs/models.md index 18b2c330a5..e32ee67098 100644 --- a/docs/readthedocs/models.md +++ b/docs/readthedocs/models.md @@ -39,5 +39,5 @@ models/wec_model --- maxdepth: 1 --- -measurement_control +models/measurement_control ``` diff --git a/docs/readthedocs/measurement_control.md b/docs/readthedocs/models/measurement_control.md similarity index 100% rename from docs/readthedocs/measurement_control.md rename to docs/readthedocs/models/measurement_control.md From 2f7e963ee2e8f9f6f8abc818f1f0a8b5802106be Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 17 Feb 2024 08:50:20 +0100 Subject: [PATCH 081/123] remove todo in config-template --- src/main/resources/config/config-template.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/config/config-template.conf b/src/main/resources/config/config-template.conf index e46f34d520..b006cafd6b 100644 --- a/src/main/resources/config/config-template.conf +++ b/src/main/resources/config/config-template.conf @@ -130,7 +130,6 @@ GridOutputConfig { TransformerControlGroup { measurements: [string] transformers: [string] - # TODO: Currently, only limit prevention is configurable. Should be an interface, when it is allowed by tscfg vMax: Double vMin: Double } From d353b2ea8d01c65b59b0061e3e7b0a4eb0c1648e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 17 Feb 2024 08:54:08 +0100 Subject: [PATCH 082/123] rename buildControlGroups --- docs/readthedocs/config.md | 2 +- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/readthedocs/config.md b/docs/readthedocs/config.md index f1db2fc5b6..64a9dfc1b7 100644 --- a/docs/readthedocs/config.md +++ b/docs/readthedocs/config.md @@ -274,4 +274,4 @@ Minimum Voltage Limit in p.u.: Maximum Voltage Limit in p.u.: -`vMax = 1.02` \ No newline at end of file +`vMax = 1.02` diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 0c05990f13..48a51e400c 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -641,7 +641,7 @@ object GridModel { val transformerControlGroups = maybeControlConfig .map { controlConfig => - buildTransformerControlGroups( + buildControlGroups( controlConfig.transformer, subGridContainer.getRawGrid.getMeasurementUnits, ) @@ -678,7 +678,7 @@ object GridModel { gridModel } - /** Build business models for transformer control groups + /** Build business models for control groups * * @param config * List of configs for control groups @@ -687,7 +687,7 @@ object GridModel { * @return * A set of control group business models */ - private def buildTransformerControlGroups( + private def buildControlGroups( config: List[SimonaConfig.TransformerControlGroup], measurementUnitInput: java.util.Set[MeasurementUnitInput], ): Set[TransformerControlGroupModel] = config.map { From 508522d89bee6619ce0feae5a8d5e1aa7be4af8f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 20 Feb 2024 10:04:58 +0100 Subject: [PATCH 083/123] fmt --- docs/readthedocs/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readthedocs/config.md b/docs/readthedocs/config.md index f1db2fc5b6..64a9dfc1b7 100644 --- a/docs/readthedocs/config.md +++ b/docs/readthedocs/config.md @@ -274,4 +274,4 @@ Minimum Voltage Limit in p.u.: Maximum Voltage Limit in p.u.: -`vMax = 1.02` \ No newline at end of file +`vMax = 1.02` From ecef9c4f60577c137d8082b45d0236efcb91f63b Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 09:01:06 +0100 Subject: [PATCH 084/123] move GridControls in own method --- .../simona/model/control/GridControls.scala | 25 +++++++++++++++++++ .../edu/ie3/simona/model/grid/GridModel.scala | 16 +----------- 2 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 src/main/scala/edu/ie3/simona/model/control/GridControls.scala diff --git a/src/main/scala/edu/ie3/simona/model/control/GridControls.scala b/src/main/scala/edu/ie3/simona/model/control/GridControls.scala new file mode 100644 index 0000000000..2afa0f283d --- /dev/null +++ b/src/main/scala/edu/ie3/simona/model/control/GridControls.scala @@ -0,0 +1,25 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.model.control + +/** Collection of grid-related control strategies + * + * @param transformerControlGroups + * Transformer control groups + */ +final case class GridControls( + transformerControlGroups: Set[TransformerControlGroupModel] +) + +object GridControls { + + /** Represents an empty GridControls group + */ + def emptyGridControls: GridControls = GridControls( + Set.empty[TransformerControlGroupModel] + ) +} diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 48a51e400c..531060b842 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -20,6 +20,7 @@ import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.SystemComponent import edu.ie3.simona.model.control.TransformerControlGroupModel import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} +import edu.ie3.simona.model.control.{GridControls, TransformerControlGroupModel} import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseA, PowerFlowCaseB, @@ -95,21 +96,6 @@ object GridModel { switches: Set[SwitchModel], ) - /** Collection of grid-related control strategies - * - * @param transformerControlGroups - * Transformer control groups - */ - final case class GridControls( - transformerControlGroups: Set[TransformerControlGroupModel] - ) - - /** Represents an empty Transformer control group - */ - def emptyGridControls: GridControls = GridControls( - Set.empty[TransformerControlGroupModel] - ) - /** Checks the availability of node calculation models, that are connected by * the given [[ConnectorInput]]. If not both models can be found, * [[InvalidGridException]] s are thrown From 9b0259c4f0db988ddf48143c196df036e9c3c3ed Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 09:02:19 +0100 Subject: [PATCH 085/123] move transformer control groups into model method --- .../edu/ie3/simona/model/grid/GridModel.scala | 137 +----------------- 1 file changed, 2 insertions(+), 135 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 531060b842..69739a005c 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -9,18 +9,15 @@ package edu.ie3.simona.model.grid import breeze.linalg.DenseMatrix import breeze.math.Complex import edu.ie3.datamodel.exceptions.InvalidGridException -import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.input.connector._ import edu.ie3.datamodel.models.input.container.SubGridContainer import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.config.SimonaConfig -import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.SystemComponent -import edu.ie3.simona.model.control.TransformerControlGroupModel -import edu.ie3.simona.model.grid.GridModel.{GridComponents, GridControls} import edu.ie3.simona.model.control.{GridControls, TransformerControlGroupModel} +import edu.ie3.simona.model.grid.GridModel.GridComponents import edu.ie3.simona.model.grid.Transformer3wPowerFlowCase.{ PowerFlowCaseA, PowerFlowCaseB, @@ -30,7 +27,6 @@ import edu.ie3.simona.util.CollectionUtils import org.jgrapht.Graph import org.jgrapht.alg.connectivity.ConnectivityInspector import org.jgrapht.graph.{DefaultEdge, SimpleGraph} -import squants.{Dimensionless, Each} import java.time.ZonedDateTime import java.util.UUID @@ -627,7 +623,7 @@ object GridModel { val transformerControlGroups = maybeControlConfig .map { controlConfig => - buildControlGroups( + TransformerControlGroupModel.buildControlGroups( controlConfig.transformer, subGridContainer.getRawGrid.getMeasurementUnits, ) @@ -664,135 +660,6 @@ object GridModel { gridModel } - /** Build business models for control groups - * - * @param config - * List of configs for control groups - * @param measurementUnitInput - * Set of [[MeasurementUnitInput]] s - * @return - * A set of control group business models - */ - private def buildControlGroups( - config: List[SimonaConfig.TransformerControlGroup], - measurementUnitInput: java.util.Set[MeasurementUnitInput], - ): Set[TransformerControlGroupModel] = config.map { - case TransformerControlGroup(measurements, _, vMax, vMin) => - buildTransformerControlGroupModel( - measurementUnitInput, - measurements.toSet, - vMax, - vMin, - ) - }.toSet - - /** Build a single control group model. Currently, only limit violation - * prevention logic is captured: The nodal regulation need is equal to the - * voltage change needed to comply with the given thresholds - * - * @param measurementUnitInput - * Collection of all known [[MeasurementUnitInput]] s - * @param measurementConfigs - * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] - * s does belong to this control group - * @param vMax - * Upper permissible voltage magnitude - * @param vMin - * Lower permissible voltage magnitude - * @return - * A [[TransformerControlGroupModel]] - */ - private def buildTransformerControlGroupModel( - measurementUnitInput: java.util.Set[MeasurementUnitInput], - measurementConfigs: Set[String], - vMax: Double, - vMin: Double, - ): TransformerControlGroupModel = { - val nodeUuids = - determineNodeUuids(measurementUnitInput, measurementConfigs) - buildTransformerControlModels(nodeUuids, vMax, vMin) - } - - /** Determine the uuids of the nodes to control - * - * @param measurementUnitInput - * Collection of all known [[MeasurementUnitInput]] s - * @param measurementConfigs - * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] - * s does belong to this control group - * @return - * A set of relevant nodal uuids - */ - private def determineNodeUuids( - measurementUnitInput: java.util.Set[MeasurementUnitInput], - measurementConfigs: Set[String], - ): Set[UUID] = Set.from( - measurementUnitInput.asScala - .filter(input => - measurementConfigs.contains(input.getUuid.toString) && input.getVMag - ) - .map(_.getNode.getUuid) - ) - - /** Build a single control group model. Currently, only limit violation - * prevention logic is captured: The nodal regulation need is equal to the - * voltage change needed to comply with the given thresholds - * - * @param nodeUuids - * Collection of all relevant node uuids - * @param vMax - * Upper permissible voltage magnitude - * @param vMin - * Lower permissible voltage magnitude - * @return - * A [[TransformerControlGroupModel]] - */ - private def buildTransformerControlModels( - nodeUuids: Set[UUID], - vMax: Double, - vMin: Double, - ): TransformerControlGroupModel = { - /* Determine the voltage regulation criterion for each of the available nodes */ - val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> { (complexVoltage: Complex) => - val vMag = complexVoltage.abs - vMag match { - case mag if mag > vMax => - Some(vMax - mag).map(Each(_)) - case mag if mag < vMin => - Some(vMin - mag).map(Each(_)) - case _ => None - } - } - }.toMap - - val harmonizationFunction = - (regulationRequests: Array[Dimensionless]) => { - val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) - val positiveRequests = regulationRequests.filter(_ > Each(0d)) - - (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { - case (true, true) => - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - case (true, false) => - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - case (false, true) => - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption - case _ => - None - } - - } - - TransformerControlGroupModel( - nodeUuidToRegulationCriterion, - harmonizationFunction, - ) - } - /** Updates the internal state of the [[GridModel.nodeUuidToIndexMap]] to * account for changes on switches (open / close) It is highly recommended (= * mandatory) to call this method every time a node admittance matrix is From 0ecf22da799d38690d412de29b0857f4f8c51c0c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 09:02:55 +0100 Subject: [PATCH 086/123] move transformer control groups into model method --- .../TransformerControlGroupModel.scala | 136 +++++++++++++++++- .../edu/ie3/simona/model/grid/GridSpec.scala | 13 +- 2 files changed, 140 insertions(+), 9 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index ada32e4fb0..dc37243d3c 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -7,12 +7,16 @@ package edu.ie3.simona.model.control import breeze.math.Complex +import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult +import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.model.control.TransformerControlGroupModel.RegulationCriterion +import squants.{Dimensionless, Each} import java.util.UUID -import squants.Dimensionless +import scala.jdk.CollectionConverters._ /** Business logic for a transformer control group. It's main purpose is to * determine, if there is any regulation need and if yes, to what extent (here: @@ -69,4 +73,134 @@ final case class TransformerControlGroupModel( object TransformerControlGroupModel { type RegulationCriterion = Complex => Option[Dimensionless] + + /** Build business models for control groups + * + * @param config + * List of configs for control groups + * @param measurementUnitInput + * Set of [[MeasurementUnitInput]] s + * @return + * A set of control group business models + */ + def buildControlGroups( + config: List[SimonaConfig.TransformerControlGroup], + measurementUnitInput: java.util.Set[MeasurementUnitInput], + ): Set[TransformerControlGroupModel] = config.map { + case TransformerControlGroup(measurements, _, vMax, vMin) => + buildTransformerControlGroupModel( + measurementUnitInput, + measurements.toSet, + vMax, + vMin, + ) + }.toSet + + /** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param measurementUnitInput + * Collection of all known [[MeasurementUnitInput]] s + * @param measurementConfigs + * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] + * s does belong to this control group + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[TransformerControlGroupModel]] + */ + private def buildTransformerControlGroupModel( + measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementConfigs: Set[String], + vMax: Double, + vMin: Double, + ): TransformerControlGroupModel = { + val nodeUuids = + determineNodeUuids(measurementUnitInput, measurementConfigs) + buildTransformerControlModels(nodeUuids, vMax, vMin) + } + + /** Determine the uuids of the nodes to control + * + * @param measurementUnitInput + * Collection of all known [[MeasurementUnitInput]] s + * @param measurementConfigs + * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] + * s does belong to this control group + * @return + * A set of relevant nodal uuids + */ + private def determineNodeUuids( + measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementConfigs: Set[String], + ): Set[UUID] = Set.from( + measurementUnitInput.asScala + .filter(input => + measurementConfigs.contains(input.getUuid.toString) && input.getVMag + ) + .map(_.getNode.getUuid) + ) + + /** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param nodeUuids + * Collection of all relevant node uuids + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[TransformerControlGroupModel]] + */ + private def buildTransformerControlModels( + nodeUuids: Set[UUID], + vMax: Double, + vMin: Double, + ): TransformerControlGroupModel = { + /* Determine the voltage regulation criterion for each of the available nodes */ + + val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => + uuid -> { (complexVoltage: Complex) => + val vMag = complexVoltage.abs + vMag match { + case mag if mag > vMax => + Some(vMax - mag).map(Each(_)) + case mag if mag < vMin => + Some(vMin - mag).map(Each(_)) + case _ => None + } + } + }.toMap + + val harmonizationFunction = + (regulationRequests: Array[Dimensionless]) => { + val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) + val positiveRequests = regulationRequests.filter(_ > Each(0d)) + + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None + } + + } + + TransformerControlGroupModel( + nodeUuidToRegulationCriterion, + harmonizationFunction, + ) + } } diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index be089f18f1..c874a19d00 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -16,12 +16,7 @@ import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.agent.grid.DBFSMockGridAgents import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.GridInconsistencyException -import edu.ie3.simona.model.control.TransformerControlGroupModel -import edu.ie3.simona.model.grid.GridModel.{ - emptyGridControls, - GridComponents, - GridControls, -} +import edu.ie3.simona.model.control.{GridControls, TransformerControlGroupModel} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} import edu.ie3.simona.test.common.model.grid.{ BasicGrid, @@ -33,9 +28,11 @@ import testutils.TestObjectFactory import edu.ie3.simona.test.common.model.grid.DbfsTestGrid import org.apache.pekko.testkit.TestProbe import edu.ie3.simona.test.common.ConfigTestData -import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData + import scala.jdk.CollectionConverters.SetHasAsJava import edu.ie3.datamodel.models.input.container.ThermalGrid +import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData +import edu.ie3.simona.model.grid.GridModel.GridComponents class GridSpec extends UnitSpec @@ -301,7 +298,7 @@ class GridSpec Set.empty[Transformer3wModel], switches, ), - emptyGridControls, + GridControls.emptyGridControls, ) // get the private method for validation From c2dbd939b2b58eb3e08ebdab0a9e3fc4edea6150 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 09:03:05 +0100 Subject: [PATCH 087/123] fmt --- src/main/scala/edu/ie3/simona/main/RunSimona.scala | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/main/RunSimona.scala b/src/main/scala/edu/ie3/simona/main/RunSimona.scala index df011e6614..fda5a23031 100644 --- a/src/main/scala/edu/ie3/simona/main/RunSimona.scala +++ b/src/main/scala/edu/ie3/simona/main/RunSimona.scala @@ -6,15 +6,14 @@ package edu.ie3.simona.main -import java.util.Locale - -import org.apache.pekko.actor.{ActorRef, ActorSystem} -import org.apache.pekko.pattern.gracefulStop -import org.apache.pekko.util.Timeout import com.typesafe.scalalogging.LazyLogging import edu.ie3.simona.sim.setup.SimonaSetup import edu.ie3.util.scala.quantities.QuantityUtil +import org.apache.pekko.actor.ActorRef +import org.apache.pekko.pattern.gracefulStop +import org.apache.pekko.util.Timeout +import java.util.Locale import scala.concurrent.Future import scala.concurrent.duration.FiniteDuration import scala.util.Random From 465d2ef49d6ecf3351fa62c1710aa21c68796708 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 09:14:17 +0100 Subject: [PATCH 088/123] fix BasicGridWithSwitches --- .../model/grid/BasicGridWithSwitches.scala | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index 5a03235762..7d0f70f3f1 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -6,18 +6,9 @@ package edu.ie3.simona.test.common.model.grid -import edu.ie3.simona.model.grid.GridModel.{ - emptyGridControls, - GridComponents, - GridControls, -} -import edu.ie3.simona.model.grid.{ - GridModel, - LineModel, - NodeModel, - SwitchModel, - Transformer3wModel, -} +import edu.ie3.simona.model.control.GridControls +import edu.ie3.simona.model.grid.GridModel.GridComponents +import edu.ie3.simona.model.grid.{GridModel, LineModel, NodeModel, SwitchModel, Transformer3wModel} import edu.ie3.util.quantities.PowerSystemUnits._ import tech.units.indriya.quantity.Quantities @@ -234,7 +225,7 @@ trait BasicGridWithSwitches extends BasicGrid { Set.empty[Transformer3wModel], gridSwitches, ), - emptyGridControls, + GridControls.emptyGridControls, ) } From b165f20ee9de810e7a23678cc6d74e0d9fdc0672 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 10:12:11 +0100 Subject: [PATCH 089/123] refactor regulationFunction and harmonizationFunction --- .../TransformerControlGroupModel.scala | 68 ++++++++++--------- .../model/grid/BasicGridWithSwitches.scala | 8 ++- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index dc37243d3c..0a1363ef13 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -144,6 +144,41 @@ object TransformerControlGroupModel { .map(_.getNode.getUuid) ) + private def regulationFunction(complexVoltage: Complex, vMax:Double, vMin: Double): Option[Dimensionless] = { + val vMag = complexVoltage.abs + vMag match { + case mag if mag > vMax => + Some(vMax - mag).map(Each(_)) + case mag if mag < vMin => + Some(vMin - mag).map(Each(_)) + case _ => None + } + } + } + + + private def harmonizationFunction: Array[Dimensionless] => Option[Dimensionless] = + (regulationRequests: Array[Dimensionless]) => { + val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) + val positiveRequests = regulationRequests.filter(_ > Each(0d)) + + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None + } + + } + + /** Build a single control group model. Currently, only limit violation * prevention logic is captured: The nodal regulation need is equal to the * voltage change needed to comply with the given thresholds @@ -163,40 +198,11 @@ object TransformerControlGroupModel { vMin: Double, ): TransformerControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ - + val voltage = Each(1.0) val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> { (complexVoltage: Complex) => - val vMag = complexVoltage.abs - vMag match { - case mag if mag > vMax => - Some(vMax - mag).map(Each(_)) - case mag if mag < vMin => - Some(vMin - mag).map(Each(_)) - case _ => None - } - } + uuid -> regulationFunction(voltage, vMax, vMin) }.toMap - val harmonizationFunction = - (regulationRequests: Array[Dimensionless]) => { - val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) - val positiveRequests = regulationRequests.filter(_ > Each(0d)) - - (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { - case (true, true) => - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - case (true, false) => - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - case (false, true) => - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption - case _ => - None - } - - } TransformerControlGroupModel( nodeUuidToRegulationCriterion, diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index 7d0f70f3f1..d57d902bc1 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -8,7 +8,13 @@ package edu.ie3.simona.test.common.model.grid import edu.ie3.simona.model.control.GridControls import edu.ie3.simona.model.grid.GridModel.GridComponents -import edu.ie3.simona.model.grid.{GridModel, LineModel, NodeModel, SwitchModel, Transformer3wModel} +import edu.ie3.simona.model.grid.{ + GridModel, + LineModel, + NodeModel, + SwitchModel, + Transformer3wModel, +} import edu.ie3.util.quantities.PowerSystemUnits._ import tech.units.indriya.quantity.Quantities From b70dae490fa589db7af05014da5808459bb53487 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 10:13:09 +0100 Subject: [PATCH 090/123] fmt --- .../TransformerControlGroupModel.scala | 119 +++++++++--------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index 0a1363ef13..d45888ec0c 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -144,69 +144,70 @@ object TransformerControlGroupModel { .map(_.getNode.getUuid) ) - private def regulationFunction(complexVoltage: Complex, vMax:Double, vMin: Double): Option[Dimensionless] = { - val vMag = complexVoltage.abs - vMag match { - case mag if mag > vMax => - Some(vMax - mag).map(Each(_)) - case mag if mag < vMin => - Some(vMin - mag).map(Each(_)) - case _ => None - } + private def regulationFunction( + complexVoltage: Complex, + vMax: Double, + vMin: Double, + ): Option[Dimensionless] = { + val vMag = complexVoltage.abs + vMag match { + case mag if mag > vMax => + Some(vMax - mag).map(Each(_)) + case mag if mag < vMin => + Some(vMin - mag).map(Each(_)) + case _ => None } } +} - - private def harmonizationFunction: Array[Dimensionless] => Option[Dimensionless] = - (regulationRequests: Array[Dimensionless]) => { - val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) - val positiveRequests = regulationRequests.filter(_ > Each(0d)) - - (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { - case (true, true) => - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - case (true, false) => - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - case (false, true) => - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption - case _ => - None - } - +private def harmonizationFunction + : Array[Dimensionless] => Option[Dimensionless] = + (regulationRequests: Array[Dimensionless]) => { + val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) + val positiveRequests = regulationRequests.filter(_ > Each(0d)) + + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None } - - /** Build a single control group model. Currently, only limit violation - * prevention logic is captured: The nodal regulation need is equal to the - * voltage change needed to comply with the given thresholds - * - * @param nodeUuids - * Collection of all relevant node uuids - * @param vMax - * Upper permissible voltage magnitude - * @param vMin - * Lower permissible voltage magnitude - * @return - * A [[TransformerControlGroupModel]] - */ - private def buildTransformerControlModels( - nodeUuids: Set[UUID], - vMax: Double, - vMin: Double, - ): TransformerControlGroupModel = { - /* Determine the voltage regulation criterion for each of the available nodes */ - val voltage = Each(1.0) - val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> regulationFunction(voltage, vMax, vMin) - }.toMap - - - TransformerControlGroupModel( - nodeUuidToRegulationCriterion, - harmonizationFunction, - ) } + +/** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param nodeUuids + * Collection of all relevant node uuids + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[TransformerControlGroupModel]] + */ +private def buildTransformerControlModels( + nodeUuids: Set[UUID], + vMax: Double, + vMin: Double, +): TransformerControlGroupModel = { + /* Determine the voltage regulation criterion for each of the available nodes */ + val voltage = Each(1.0) + val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => + uuid -> regulationFunction(voltage, vMax, vMin) + }.toMap + + TransformerControlGroupModel( + nodeUuidToRegulationCriterion, + harmonizationFunction, + ) } From 1964ee03d82822b352bef60faea37f9095839dd6 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 15:56:34 +0100 Subject: [PATCH 091/123] move failFast of superiorGridGates back to GridAgent --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 20 +++++++++-- .../edu/ie3/simona/model/grid/GridModel.scala | 16 +-------- .../edu/ie3/simona/model/grid/GridSpec.scala | 34 ++++--------------- 3 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 5a7d265835..fd4f7934bc 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -12,11 +12,13 @@ import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentInitData, GridAgentUninitializedData, } +import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.{Initializing, SimulateGrid} import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} import edu.ie3.simona.config.SimonaConfig -import edu.ie3.simona.model.grid.GridModel +import edu.ie3.simona.exceptions.agent.GridAgentInitializationException + import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, @@ -93,6 +95,7 @@ object GridAgent { */ final case class FinishGridSimulationTrigger(tick: Long) } + class GridAgent( val environmentRefs: EnvironmentRefs, simonaConfig: SimonaConfig, @@ -154,6 +157,9 @@ class GridAgent( Activation(INIT_SIM_TICK), gridAgentInitData: GridAgentInitData, ) => + // fail fast sanity checks + failFast(gridAgentInitData) + log.debug( s"Inferior Subnets: {}; Inferior Subnet Nodes: {}", gridAgentInitData.inferiorGridIds, @@ -185,8 +191,7 @@ class GridAgent( TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.endDateTime ), - gridAgentInitData, - simonaConfig, + simonaConfig ) /* Reassure, that there are also calculation models for the given uuids */ @@ -267,4 +272,13 @@ class GridAgent( // everything else whenUnhandled(myUnhandled()) + private def failFast(gridAgentInitData: GridAgentInitData): Unit = { + if ( + gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty + ) + throw new GridAgentInitializationException( + s"$actorName has neither superior nor inferior grids! This can either " + + s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" + ) + } } diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 69739a005c..94ad793968 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -70,14 +70,12 @@ object GridModel { refSystem: RefSystem, startDate: ZonedDateTime, endDate: ZonedDateTime, - gridAgentInitData: GridAgentInitData, simonaConfig: SimonaConfig, ): GridModel = buildAndValidate( subGridContainer, refSystem, startDate, endDate, - gridAgentInitData, simonaConfig, ) @@ -458,15 +456,6 @@ object GridModel { } - private def checkForGridGates(gridAgentInitData: GridAgentInitData): Unit = { - if ( - gridAgentInitData.superiorGridGates.isEmpty && gridAgentInitData.inferiorGridGates.isEmpty - ) - throw new GridAgentInitializationException( - s"${gridAgentInitData.subGridContainer.getGridName} has neither superior nor inferior grids! This can either " + - s"be cause by wrong subnetGate information or invalid parametrization of the simulation!" - ) - } /** Checks all ControlGroups if a) Transformer of ControlGroup and Measurement * belongs to the same sub grid. b) Measurements are measure voltage @@ -529,7 +518,6 @@ object GridModel { refSystem: RefSystem, startDate: ZonedDateTime, endDate: ZonedDateTime, - gridAgentInitData: GridAgentInitData, simonaConfig: SimonaConfig, ): GridModel = { @@ -650,9 +638,7 @@ object GridModel { // validate validateConsistency(gridModel) validateConnectivity(gridModel) - checkForGridGates(gridAgentInitData) - checkControlGroupsForMeasurement( - gridAgentInitData.subGridContainer, + checkControlGroupsForMeasurement(subGridContainer, simonaConfig.simona.control, ) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index c874a19d00..862a7175fc 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -10,36 +10,28 @@ import java.util.UUID import breeze.linalg.DenseMatrix import breeze.math.Complex import breeze.numerics.abs + import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils -import edu.ie3.simona.agent.grid.DBFSMockGridAgents -import edu.ie3.simona.config.SimonaConfig + import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.{GridControls, TransformerControlGroupModel} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} -import edu.ie3.simona.test.common.model.grid.{ - BasicGrid, - BasicGridWithSwitches, - FiveLinesWithNodes, -} -import edu.ie3.simona.test.common.{DefaultTestData, UnitSpec} +import edu.ie3.simona.test.common.model.grid.{BasicGrid, BasicGridWithSwitches, FiveLinesWithNodes} +import edu.ie3.simona.test.common.{ConfigTestData, DefaultTestData, , UnitSpec} import testutils.TestObjectFactory -import edu.ie3.simona.test.common.model.grid.DbfsTestGrid -import org.apache.pekko.testkit.TestProbe -import edu.ie3.simona.test.common.ConfigTestData + import scala.jdk.CollectionConverters.SetHasAsJava -import edu.ie3.datamodel.models.input.container.ThermalGrid -import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData + import edu.ie3.simona.model.grid.GridModel.GridComponents + class GridSpec extends UnitSpec with LineInputTestData with DefaultTestData - with DbfsTestGrid - with DBFSMockGridAgents with ConfigTestData { private val _printAdmittanceMatrixOnMismatch @@ -561,23 +553,11 @@ class GridSpec } "process a valid GridInputModel without an Exception" in new GridInputTestData { - val simonaConfig: SimonaConfig = SimonaConfig(typesafeConfig) - private val superiorGridAgent = SuperiorGA( - TestProbe("superiorGridAgent_1000"), - Seq(supNodeA.getUuid), - ) - GridModel( validTestGridInputModel, gridInputModelTestDataRefSystem, defaultSimulationStart, defaultSimulationEnd, - GridAgentInitData( - hvGridContainer, - Seq.empty[ThermalGrid], - superiorGridAgent.ref, - RefSystem("2000 MVA", "110 kV"), - ), simonaConfig, ) } From a4edc1d1849b30a130ea8a943a9c8a829147b7ba Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 15:57:57 +0100 Subject: [PATCH 092/123] fmt --- .../scala/edu/ie3/simona/agent/grid/GridAgent.scala | 2 +- .../scala/edu/ie3/simona/model/grid/GridModel.scala | 4 ++-- .../scala/edu/ie3/simona/model/grid/GridSpec.scala | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index fd4f7934bc..e4dcca569f 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -191,7 +191,7 @@ class GridAgent( TimeUtil.withDefaults.toZonedDateTime( simonaConfig.simona.time.endDateTime ), - simonaConfig + simonaConfig, ) /* Reassure, that there are also calculation models for the given uuids */ diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 94ad793968..da108c62e9 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -456,7 +456,6 @@ object GridModel { } - /** Checks all ControlGroups if a) Transformer of ControlGroup and Measurement * belongs to the same sub grid. b) Measurements are measure voltage * magnitude. @@ -638,7 +637,8 @@ object GridModel { // validate validateConsistency(gridModel) validateConnectivity(gridModel) - checkControlGroupsForMeasurement(subGridContainer, + checkControlGroupsForMeasurement( + subGridContainer, simonaConfig.simona.control, ) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 862a7175fc..49ada4cf9e 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -18,16 +18,18 @@ import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.model.control.{GridControls, TransformerControlGroupModel} import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} -import edu.ie3.simona.test.common.model.grid.{BasicGrid, BasicGridWithSwitches, FiveLinesWithNodes} -import edu.ie3.simona.test.common.{ConfigTestData, DefaultTestData, , UnitSpec} +import edu.ie3.simona.test.common.model.grid.{ + BasicGrid, + BasicGridWithSwitches, + FiveLinesWithNodes, +} +import edu.ie3.simona.test.common.{ConfigTestData, DefaultTestData, UnitSpec} import testutils.TestObjectFactory - import scala.jdk.CollectionConverters.SetHasAsJava import edu.ie3.simona.model.grid.GridModel.GridComponents - class GridSpec extends UnitSpec with LineInputTestData From 11bdb7f2a3c1de9ba0281062c372eaaddd97f89e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 21 Feb 2024 15:58:15 +0100 Subject: [PATCH 093/123] fmt --- .../TransformerControlGroupModel.scala | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index d45888ec0c..737ea0217f 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -158,56 +158,56 @@ object TransformerControlGroupModel { case _ => None } } -} -private def harmonizationFunction - : Array[Dimensionless] => Option[Dimensionless] = - (regulationRequests: Array[Dimensionless]) => { - val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) - val positiveRequests = regulationRequests.filter(_ > Each(0d)) + private def harmonizationFunction + : Array[Dimensionless] => Option[Dimensionless] = + (regulationRequests: Array[Dimensionless]) => { + val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) + val positiveRequests = regulationRequests.filter(_ > Each(0d)) - (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { - case (true, true) => - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - case (true, false) => - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - case (false, true) => - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption - case _ => - None - } + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None + } - } + } -/** Build a single control group model. Currently, only limit violation - * prevention logic is captured: The nodal regulation need is equal to the - * voltage change needed to comply with the given thresholds - * - * @param nodeUuids - * Collection of all relevant node uuids - * @param vMax - * Upper permissible voltage magnitude - * @param vMin - * Lower permissible voltage magnitude - * @return - * A [[TransformerControlGroupModel]] - */ -private def buildTransformerControlModels( - nodeUuids: Set[UUID], - vMax: Double, - vMin: Double, -): TransformerControlGroupModel = { - /* Determine the voltage regulation criterion for each of the available nodes */ - val voltage = Each(1.0) - val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> regulationFunction(voltage, vMax, vMin) - }.toMap + /** Build a single control group model. Currently, only limit violation + * prevention logic is captured: The nodal regulation need is equal to the + * voltage change needed to comply with the given thresholds + * + * @param nodeUuids + * Collection of all relevant node uuids + * @param vMax + * Upper permissible voltage magnitude + * @param vMin + * Lower permissible voltage magnitude + * @return + * A [[TransformerControlGroupModel]] + */ + private def buildTransformerControlModels( + nodeUuids: Set[UUID], + vMax: Double, + vMin: Double, + ): TransformerControlGroupModel = { + /* Determine the voltage regulation criterion for each of the available nodes */ + val voltage = Complex(1.0, 0.0) + val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => + uuid -> regulationFunction(voltage, vMax, vMin) + }.toMap - TransformerControlGroupModel( - nodeUuidToRegulationCriterion, - harmonizationFunction, - ) + TransformerControlGroupModel( + nodeUuidToRegulationCriterion, + harmonizationFunction, + ) + } } From cf4fd39261267ae1a228a9e5e960359fc922d32e Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Thu, 22 Feb 2024 11:22:42 +0100 Subject: [PATCH 094/123] Reverting unnecessary changes --- gradle/scripts/tscfg.gradle | 2 +- src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gradle/scripts/tscfg.gradle b/gradle/scripts/tscfg.gradle index 0f94fba657..e81ad99320 100644 --- a/gradle/scripts/tscfg.gradle +++ b/gradle/scripts/tscfg.gradle @@ -47,7 +47,7 @@ task genConfigSample { args = [ "build/tscfg-${tscfgVersion}.jar", "--spec", - "src/main/resources/config/simona-config-template.conf", + "src/main/resources/config/config-template.conf", "--tpl", "input/samples/configSample.conf" ] diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index e4dcca569f..78a30ea294 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -12,13 +12,12 @@ import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentInitData, GridAgentUninitializedData, } -import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.{Initializing, SimulateGrid} import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException - +import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, @@ -28,8 +27,8 @@ import edu.ie3.simona.ontology.messages.{Activation, StopMessage} import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.TimeUtil -import org.apache.pekko.actor.{ActorRef, Props, Stash} import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps +import org.apache.pekko.actor.{ActorRef, Props, Stash} import java.time.ZonedDateTime import java.time.temporal.ChronoUnit From a34064a12a719e1615833e461dc91290e91c8c79 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 22 Feb 2024 12:21:09 +0100 Subject: [PATCH 095/123] Some minor internal changes to the `GridAgent`. --- .../ie3/simona/agent/grid/DBFSAlgorithm.scala | 48 +------------------ .../edu/ie3/simona/agent/grid/GridAgent.scala | 43 +++++++++++++++++ .../simona/agent/grid/GridAgentMessage.scala | 7 +-- .../simona/agent/grid/ReceivedValues.scala | 4 +- .../simona/agent/grid/VoltageMessage.scala | 4 +- 5 files changed, 50 insertions(+), 56 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala index 8e203c7b11..10987efa0d 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -15,6 +15,7 @@ import edu.ie3.powerflow.model.PowerFlowResult import edu.ie3.powerflow.model.PowerFlowResult.FailedPowerFlowResult.FailedNewtonRaphsonPFResult import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult import edu.ie3.powerflow.model.enums.NodeType +import edu.ie3.simona.agent.grid.GridAgent.idle import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentBaseData, GridAgentValues, @@ -62,51 +63,6 @@ import scala.util.{Failure, Success} */ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { - /** Method that defines the idle [[Behavior]] of the agent. - * @param gridAgentBaseData - * state data of the actor - * @param values - * immutable [[GridAgent]] values - * @param buffer - * for [[GridAgentMessage]]s - * @return - * a [[Behavior]] - */ - protected def idle( - gridAgentBaseData: GridAgentBaseData - )(implicit - values: GridAgentValues, - buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { - case (_, pm: WrappedPowerMessage) => - // needs to be set here to handle if the messages arrive too early - // before a transition to GridAgentBehaviour took place - buffer.stash(pm) - Behaviors.same - - case (_, WrappedActivation(activation: Activation)) => - values.environmentRefs.scheduler ! Completion( - values.activationAdapter, - Some(activation.tick), - ) - buffer.unstashAll(simulateGrid(gridAgentBaseData, activation.tick)) - - case (ctx, WrappedResultMessage(StopMessage(_))) => - // shutdown children - gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => - actors.foreach(a => ctx.stop(a)) - } - - // we are done - Behaviors.stopped - - case (_, StopGridAgent) => - Behaviors.stopped - - case _ => - Behaviors.unhandled - } - /** Method that defines the [[Behavior]] for simulating the grid. * @param gridAgentData * state data of the actor @@ -115,7 +71,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * @return * a [[Behavior]] */ - private def simulateGrid( + private[grid] def simulateGrid( gridAgentData: GridAgentData, currentTick: Long, )(implicit diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 19de1b9649..4c6670fbf3 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -199,6 +199,49 @@ object GridAgent extends DBFSAlgorithm { Behaviors.unhandled } + /** Method that defines the idle [[Behavior]] of the agent. + * + * @param gridAgentBaseData + * state data of the actor + * @param values + * immutable [[GridAgent]] values + * @param buffer + * for [[GridAgentMessage]]s + * @return + * a [[Behavior]] + */ + private[grid] def idle( + gridAgentBaseData: GridAgentBaseData + )(implicit + values: GridAgentValues, + buffer: StashBuffer[GridAgentMessage], + ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + case (_, pm: WrappedPowerMessage) => + // needs to be set here to handle if the messages arrive too early + // before a transition to GridAgentBehaviour took place + buffer.stash(pm) + Behaviors.same + + case (_, WrappedActivation(activation: Activation)) => + values.environmentRefs.scheduler ! Completion( + values.activationAdapter, + Some(activation.tick), + ) + buffer.unstashAll(simulateGrid(gridAgentBaseData, activation.tick)) + + case (ctx, StopGridAgent) => + // shutdown children + gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => + actors.foreach(a => ctx.stop(a)) + } + + // we are done + Behaviors.stopped + + case _ => + Behaviors.unhandled + } + private def failFast( gridAgentInitData: GridAgentInitData, actorName: String, diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala index cc11aa44ac..4a2b4dbe1c 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala @@ -7,10 +7,8 @@ package edu.ie3.simona.agent.grid import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage import edu.ie3.simona.ontology.messages.{Activation, PowerMessage} import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey -import org.apache.pekko.actor.typed.ActorRef /** Trait for [[GridAgent]] messages. */ @@ -24,7 +22,7 @@ object GridAgentMessage { /** Necessary because we want to extend [[GridAgentMessage]] in other classes, * but we do want to keep [[GridAgentMessage]] sealed. */ - private[grid] trait GAMessage extends GridAgentMessage + private[grid] trait InternalMessage extends GridAgentMessage /** GridAgent initialization data can only be constructed once all GridAgent * actors are created. Thus, we need an extra initialization message. @@ -90,7 +88,4 @@ object GridAgentMessage { final case class WrappedPowerMessage(msg: PowerMessage) extends GridAgentMessage - final case class WrappedResultMessage(msg: ResultMessage) - extends GridAgentMessage - } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala index eacda5e019..c1accbb471 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/ReceivedValues.scala @@ -8,13 +8,13 @@ package edu.ie3.simona.agent.grid import edu.ie3.simona.ontology.messages.PowerMessage.PowerResponseMessage import VoltageMessage.ProvideSlackVoltageMessage -import edu.ie3.simona.agent.grid.GridAgentMessage.GAMessage +import edu.ie3.simona.agent.grid.GridAgentMessage.InternalMessage import org.apache.pekko.actor.typed.ActorRef /** Serves as a wrapper class that allows for matches against received values in * [[DBFSAlgorithm]] */ -sealed trait ReceivedValues extends GAMessage +sealed trait ReceivedValues extends InternalMessage object ReceivedValues { diff --git a/src/main/scala/edu/ie3/simona/agent/grid/VoltageMessage.scala b/src/main/scala/edu/ie3/simona/agent/grid/VoltageMessage.scala index bcbffdf609..41c311f61d 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/VoltageMessage.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/VoltageMessage.scala @@ -6,14 +6,14 @@ package edu.ie3.simona.agent.grid -import edu.ie3.simona.agent.grid.GridAgentMessage.GAMessage +import edu.ie3.simona.agent.grid.GridAgentMessage.InternalMessage import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage import org.apache.pekko.actor.typed.ActorRef import squants.electro.ElectricPotential import java.util.UUID -sealed trait VoltageMessage extends GAMessage +sealed trait VoltageMessage extends InternalMessage /** Message that is send between [[edu.ie3.simona.agent.grid.GridAgent]] s to * provide voltage information for nodes From 3b51ed3d12f823add6a303c27cce48095271eaab Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 23 Feb 2024 14:48:01 +0100 Subject: [PATCH 096/123] Adapting to recent changes in `dev` branch. --- .../ie3/simona/agent/grid/DBFSAlgorithm.scala | 2 +- .../scala/edu/ie3/simona/sim/SimonaSim.scala | 34 +---- .../ie3/simona/sim/setup/SimonaSetup.scala | 10 +- .../sim/setup/SimonaStandaloneSetup.scala | 24 +--- .../agent/grid/DBFSAlgorithmCenGridSpec.scala | 7 +- .../DBFSAlgorithmFailedPowerFlowSpec.scala | 5 +- .../grid/DBFSAlgorithmParticipantSpec.scala | 6 +- .../agent/grid/DBFSAlgorithmSupGridSpec.scala | 9 +- .../agent/grid/GridAgentSetup2WSpec.scala | 129 ++++++------------ .../agent/grid/GridAgentSetup3WSpec.scala | 121 ++++++---------- .../ie3/simona/sim/SimonaSimFailSpec.scala | 0 .../edu/ie3/simona/sim/SimonaSimSpec.scala | 8 +- .../simona/sim/setup/SimonaSetupSpec.scala | 54 ++++---- 13 files changed, 132 insertions(+), 277 deletions(-) delete mode 100644 src/test/scala/edu/ie3/simona/sim/SimonaSimFailSpec.scala diff --git a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala index 10987efa0d..c9bb5ddc71 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -32,9 +32,9 @@ import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.event.RuntimeEvent.PowerFlowFailed import edu.ie3.simona.exceptions.agent.DBFSAlgorithmException import edu.ie3.simona.model.grid.{NodeModel, RefSystem} +import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage._ import edu.ie3.simona.ontology.messages.SchedulerMessage.Completion -import edu.ie3.simona.ontology.messages.{Activation, StopMessage} import edu.ie3.simona.util.TickUtil.TickLong import edu.ie3.util.scala.quantities.Megavars import edu.ie3.util.scala.quantities.SquantsUtils.RichElectricPotential diff --git a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala index 4887f96516..f62dc5e45a 100644 --- a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala +++ b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala @@ -6,48 +6,18 @@ package edu.ie3.simona.sim -import org.apache.pekko.actor.typed.scaladsl.adapter.{ - ClassicActorRefOps, - TypedActorRefOps, -} -import org.apache.pekko.actor.SupervisorStrategy.Stop -import org.apache.pekko.actor.{ - Actor, - AllForOneStrategy, - Props, - Stash, - SupervisorStrategy, - Terminated, - ActorRef => classicRef, -} -import com.typesafe.scalalogging.LazyLogging import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgentMessage -import edu.ie3.simona.agent.grid.GridAgentMessage.StopGridAgent import edu.ie3.simona.api.ExtSimAdapter import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{DelayedStopHelper, RuntimeEventListener} import edu.ie3.simona.main.RunSimona.SimonaEnded import edu.ie3.simona.scheduler.TimeAdvancer -import edu.ie3.simona.scheduler.TimeAdvancer.{Incoming, StartSimMessage} -import edu.ie3.simona.sim.SimMessage.{ - InitSim, - SimulationFailure, - SimulationSuccessful, - StartSimulation, -} -import edu.ie3.simona.sim.SimonaSim.{ - EmergencyShutdownInitiated, - SimonaSimStateData, -} import edu.ie3.simona.sim.setup.{ExtSimSetupData, SimonaSetup} import edu.ie3.util.scala.Scope import org.apache.pekko.actor.typed.scaladsl.adapter._ import org.apache.pekko.actor.typed.scaladsl.{ActorContext, Behaviors} import org.apache.pekko.actor.typed.{ActorRef, Behavior, PostStop, Terminated} import org.apache.pekko.actor.{ActorRef => ClassicRef} -import org.apache.pekko.actor.typed.ActorRef -import org.apache.pekko.actor.typed.scaladsl.ActorContext /** Main entrance point to a simona simulation as the guardian actor. This actor * starts the initialization of all actors and waits for the simulation to end. @@ -146,7 +116,7 @@ object SimonaSim { extSimulationData.extDataServices.values .map(_.toTyped) .foreach(ctx.watch) - gridAgents.foreach(ref => ctx.watch(ref.toTyped)) + gridAgents.foreach(ref => ctx.watch(ref)) // Start simulation timeAdvancer ! TimeAdvancer.Start() @@ -157,7 +127,7 @@ object SimonaSim { primaryServiceProxy.toTyped, weatherService.toTyped, ) ++ - gridAgents.map(_.toTyped) ++ + gridAgents ++ extSimulationData.extDataServices.values.map(_.toTyped) idle( diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala b/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala index 98e39cca49..ee850a092d 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala @@ -6,22 +6,14 @@ package edu.ie3.simona.sim.setup -import org.apache.pekko.actor.{ - ActorSystem, - ActorContext => classicContext, - ActorRef => classicRef, -} import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.datamodel.models.input.connector.Transformer3WInput import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{ResultEventListener, RuntimeEventListener} -import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.scheduler.TimeAdvancer -import org.apache.pekko.actor.typed.ActorRef -import org.apache.pekko.actor.typed.scaladsl.ActorContext import edu.ie3.simona.sim.SimonaSim import org.apache.pekko.actor.typed.ActorRef import org.apache.pekko.actor.typed.scaladsl.ActorContext @@ -157,7 +149,7 @@ trait SimonaSetup { def gridAgents( context: ActorContext[_], environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[classicRef], + resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], ): Iterable[ActorRef[GridAgentMessage]] /** SIMONA links sub grids connected by a three winding transformer a bit diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala index 4c48b75495..d43c2ec4ba 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala @@ -11,7 +11,7 @@ import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.graph.SubGridTopologyGraph import edu.ie3.datamodel.models.input.container.{GridContainer, ThermalGrid} import edu.ie3.datamodel.models.input.thermal.ThermalBusInput -import edu.ie3.simona.actor.SimonaActorNaming._ +import edu.ie3.simona.actor.SimonaActorNaming.RichActorRefFactory import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentMessage.CreateGridAgent import edu.ie3.simona.agent.grid.{GridAgent, GridAgentMessage} @@ -20,8 +20,8 @@ import edu.ie3.simona.api.data.ExtData import edu.ie3.simona.api.data.ev.{ExtEvData, ExtEvSimulation} import edu.ie3.simona.api.simulation.ExtSimAdapterData import edu.ie3.simona.config.{ArgsParser, RefSystemParser, SimonaConfig} +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{ResultEventListener, RuntimeEventListener} -import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.io.grid.GridProvider import edu.ie3.simona.ontology.messages.SchedulerMessage @@ -40,23 +40,13 @@ import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.simona.util.TickUtil.RichZonedDateTime import edu.ie3.util.TimeUtil import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.ActorContext import org.apache.pekko.actor.typed.scaladsl.adapter.{ - ClassicActorContextOps, ClassicActorRefOps, + TypedActorContextOps, TypedActorRefOps, } -import org.apache.pekko.actor.{ - ActorSystem, - ActorContext, - ActorRef => ClassicRef, -} -import org.apache.pekko.actor.typed.ActorRef -import org.apache.pekko.actor.typed.scaladsl.ActorContext -import org.apache.pekko.actor.typed.scaladsl.adapter._ -import org.apache.pekko.actor.{ - ActorContext => ClassicContext, - ActorRef => ClassicRef, -} +import org.apache.pekko.actor.{ActorRef => ClassicRef} import java.util.concurrent.LinkedBlockingQueue import scala.jdk.CollectionConverters._ @@ -78,7 +68,7 @@ class SimonaStandaloneSetup( override def gridAgents( context: ActorContext[_], environmentRefs: EnvironmentRefs, - resultEventListeners: Seq[ActorRef[ResultEvent]], + resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], ): Iterable[ActorRef[GridAgentMessage]] = { /* get the grid */ @@ -330,7 +320,7 @@ class SimonaStandaloneSetup( def buildSubGridToActorRefMap( subGridTopologyGraph: SubGridTopologyGraph, - context: ActorContext, + context: ActorContext[_], environmentRefs: EnvironmentRefs, systemParticipantListener: Seq[ClassicRef], ): Map[Int, ActorRef[GridAgentMessage]] = { diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala index 9af89c60f1..56af76d286 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala @@ -11,7 +11,7 @@ import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.agent.grid.GridAgentMessage._ import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent -import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage +import edu.ie3.simona.event.listener.ResultEventListener.Request import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower @@ -83,8 +83,7 @@ class DBFSAlgorithmCenGridSpec evDataService = None, ) - val resultListener: TestProbe[ResultMessage] = - TestProbe[ResultMessage]("resultListener") + val resultListener: TestProbe[Request] = TestProbe[Request]("resultListener") "A GridAgent actor in center position with async test" should { @@ -451,7 +450,7 @@ class DBFSAlgorithmCenGridSpec val cm = scheduler.expectMessageType[Completion] cm shouldBe Completion(cm.actor, Some(7200)) - val resultMessage = resultListener.expectMessageType[ResultMessage] + val resultMessage = resultListener.expectMessageType[Request] resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => // we expect results for 4 nodes, 5 lines and 2 transformer2ws diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala index 75fa5fe7f8..672e5342c3 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala @@ -10,7 +10,7 @@ import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.agent.grid.GridAgentMessage._ -import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage +import edu.ie3.simona.event.listener.ResultEventListener.Request import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ @@ -70,8 +70,7 @@ class DBFSAlgorithmFailedPowerFlowSpec evDataService = None, ) - val resultListener: TestProbe[ResultMessage] = - TestProbe[ResultMessage]("resultListener") + val resultListener: TestProbe[Request] = TestProbe[Request]("resultListener") "A GridAgent actor in center position with async test" should { diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala index 16cdebb266..eb4946d119 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala @@ -14,7 +14,7 @@ import edu.ie3.simona.agent.grid.GridAgentMessage.{ FinishGridSimulationTrigger, WrappedActivation, } -import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage +import edu.ie3.simona.event.listener.ResultEventListener.Request import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.SchedulerMessage.{ @@ -66,8 +66,8 @@ class DBFSAlgorithmParticipantSpec evDataService = None, ) - protected val resultListener: TestProbe[ResultMessage] = - TestProbe[ResultMessage]("resultListener") + protected val resultListener: TestProbe[Request] = + TestProbe[Request]("resultListener") private val superiorGridAgent = SuperiorGA( TestProbe("superiorGridAgent_1000"), diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala index 69d062491c..f4f43b5757 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala @@ -18,7 +18,7 @@ import edu.ie3.simona.agent.grid.GridAgentMessage.{ } import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent import edu.ie3.simona.event.RuntimeEvent -import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage +import edu.ie3.simona.event.listener.ResultEventListener.Request import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ @@ -77,8 +77,7 @@ class DBFSAlgorithmSupGridSpec evDataService = None, ) - val resultListener: TestProbe[ResultMessage] = - TestProbe[ResultMessage]("resultListener") + val resultListener: TestProbe[Request] = TestProbe[Request]("resultListener") "A GridAgent actor in superior position with async test" should { val superiorGridAgentFSM: ActorRef[GridAgentMessage] = testKit.spawn( @@ -181,7 +180,7 @@ class DBFSAlgorithmSupGridSpec case Completion(_, Some(7200)) => // agent should be in Idle again and listener should contain power flow result data val resultMessage = - resultListener.expectMessageType[ResultMessage] + resultListener.expectMessageType[Request] resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => @@ -310,7 +309,7 @@ class DBFSAlgorithmSupGridSpec case Completion(_, Some(7200)) => // after doing cleanup stuff, our agent should go back to idle again and listener should contain power flow result data val resultMessage = - resultListener.expectMessageType[ResultMessage] + resultListener.expectMessageType[Request] resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala index 2a1cc430b7..da08685dba 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala @@ -6,7 +6,6 @@ package edu.ie3.simona.agent.grid -import com.typesafe.config.ConfigFactory import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.simona.agent.EnvironmentRefs @@ -16,41 +15,23 @@ import edu.ie3.simona.agent.grid.GridAgentMessage.{ } import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.io.result.ResultSinkType +import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.sim.setup.SimonaStandaloneSetup import edu.ie3.simona.test.common.ConfigTestData import edu.ie3.simona.test.common.input.TransformerInputTestData import edu.ie3.simona.util.ResultFileHierarchy import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig +import org.apache.pekko.actor.testkit.typed.Effect.Spawned import org.apache.pekko.actor.testkit.typed.scaladsl.{ BehaviorTestKit, ScalaTestWithActorTestKit, TestProbe, } -import org.apache.pekko.actor.typed.{ActorRef, Scheduler} -import org.apache.pekko.actor.typed.receptionist.Receptionist.{ - Listing, - Register, - Subscribe, -} -import org.apache.pekko.actor.typed.receptionist.ServiceKey -import org.apache.pekko.actor.typed.scaladsl.AskPattern.Askable import org.apache.pekko.actor.typed.scaladsl.Behaviors -import org.apache.pekko.actor.typed.scaladsl.adapter.{ - TypedActorContextOps, - TypedActorRefOps, -} -import org.apache.pekko.actor.{ - ActorContext => ClassicContext, - ActorRef => ClassicRef, -} -import org.apache.pekko.util.Timeout -import org.mockito.Mock +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps +import org.apache.pekko.actor.{ActorRef => ClassicRef} import org.scalatest.wordspec.AnyWordSpecLike -import java.util.concurrent.TimeUnit -import scala.concurrent.Await -import scala.concurrent.duration.Duration - class GridAgentSetup2WSpec extends ScalaTestWithActorTestKit with AnyWordSpecLike @@ -60,12 +41,13 @@ class GridAgentSetup2WSpec "The setup of grid agents" must { - val scheduler = TestProbe("scheduler") + val scheduler: TestProbe[SchedulerMessage] = + TestProbe[SchedulerMessage]("scheduler") val runtimeEventListener = TestProbe[RuntimeEvent]("listener") val primaryServiceProxy = TestProbe("primaryServiceProxy") val environmentRefs = EnvironmentRefs( - scheduler.ref.toClassic, + scheduler.ref, runtimeEventListener.ref, primaryServiceProxy = primaryServiceProxy.ref.toClassic, weather = ClassicRef.noSender, @@ -73,76 +55,45 @@ class GridAgentSetup2WSpec ) "provide two grid agents on presence of a two winding transformer" in { - - implicit val timeout: Timeout = Timeout(1, TimeUnit.SECONDS) - implicit val scheduler: Scheduler = system.scheduler - - // in order to get an actor system we need a tmp actor that calls the corresponding method - val serviceKey = ServiceKey[GridAgentMessage]("gridAgent") - - val actor = testKit.spawn(Behaviors.setup[GridAgentMessage] { ctx => - ctx.system.receptionist ! Register(serviceKey, ctx.self) - - Behaviors.receive[GridAgentMessage] { - case (ctx, PrepareNextSweepTrigger(tick)) => - SimonaStandaloneSetup( - typesafeConfig, - ResultFileHierarchy( - "test/tmp", - "GridAgentSetup2WSpec", - ResultEntityPathConfig( - Set.empty[Class[_ <: ResultEntity]], - ResultSinkType( - simonaConfig.simona.output.sink, - simonaConfig.simona.simulationName, - ), + val testKit = BehaviorTestKit(Behaviors.receive[GridAgentMessage] { + case (ctx, PrepareNextSweepTrigger(tick)) => + SimonaStandaloneSetup( + typesafeConfig, + ResultFileHierarchy( + "test/tmp", + "GridAgentSetup2WSpec", + ResultEntityPathConfig( + Set.empty[Class[_ <: ResultEntity]], + ResultSinkType( + simonaConfig.simona.output.sink, + simonaConfig.simona.simulationName, ), ), - ).buildSubGridToActorRefMap( - gridContainer.getSubGridTopologyGraph, - ctx.toClassic, - environmentRefs, - Seq.empty[ClassicRef], - ) - - ctx.self ! FinishGridSimulationTrigger(tick) - Behaviors.same - - case other => - fail(s"$other was not expected") - } + ), + ).buildSubGridToActorRefMap( + gridContainer.getSubGridTopologyGraph, + ctx, + environmentRefs, + Seq.empty[ClassicRef], + ) + + ctx.self ! FinishGridSimulationTrigger(tick) + Behaviors.same + + case other => + fail(s"$other was not expected") }) - Await.ready( - actor.ask[GridAgentMessage](_ => PrepareNextSweepTrigger(0)), - Duration(10, TimeUnit.SECONDS), - ) - - BehaviorTestKit(Behaviors.setup[Listing] { ctx => - logger.debug("Subscribing to the actors.") - ctx.system.receptionist ! Subscribe(serviceKey, ctx.self) - - Behaviors.receiveMessagePartial[Listing] { - case serviceKey.Listing(listings) => - logger.debug("All responses received. Evaluating...") + testKit.run(PrepareNextSweepTrigger(0)) - listings.size should be(2) + // two actor should be spawned + testKit.expectEffectPF { case Spawned(_, str, _) => + str shouldBe "1" + } - val regex = """GridAgent_\d*""".r - val expectedSenders = Vector("GridAgent_1", "GridAgent_2") - val actualSenders = listings - .collect { case actorId: ActorRef[GridAgentMessage] => - val actorRefString = actorId.toString - regex.findFirstIn(actorRefString) - } - .flatten - .toVector - - actualSenders should be(expectedSenders) - - Behaviors.same - } - }) + testKit.expectEffectPF { case Spawned(_, str, _) => + str shouldBe "2" + } } } } diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala index 3ea296387e..6e19a2185c 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala @@ -6,7 +6,6 @@ package edu.ie3.simona.agent.grid -import com.typesafe.config.ConfigFactory import com.typesafe.scalalogging.LazyLogging import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.simona.agent.EnvironmentRefs @@ -16,36 +15,22 @@ import edu.ie3.simona.agent.grid.GridAgentMessage.{ } import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.io.result.ResultSinkType +import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.sim.setup.SimonaStandaloneSetup import edu.ie3.simona.test.common.{ConfigTestData, ThreeWindingTestData} import edu.ie3.simona.util.ResultFileHierarchy import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig +import org.apache.pekko.actor.testkit.typed.Effect.Spawned import org.apache.pekko.actor.testkit.typed.scaladsl.{ BehaviorTestKit, ScalaTestWithActorTestKit, TestProbe, } -import org.apache.pekko.actor.typed.{ActorRef, Scheduler} -import org.apache.pekko.actor.typed.receptionist.Receptionist.{ - Listing, - Register, - Subscribe, -} -import org.apache.pekko.actor.typed.receptionist.ServiceKey -import org.apache.pekko.actor.typed.scaladsl.AskPattern.Askable import org.apache.pekko.actor.typed.scaladsl.Behaviors import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps -import org.apache.pekko.actor.{ - ActorContext => ClassicContext, - ActorRef => ClassicRef, -} -import org.apache.pekko.util.Timeout +import org.apache.pekko.actor.{ActorRef => ClassicRef} import org.scalatest.wordspec.AnyWordSpecLike -import java.util.concurrent.TimeUnit -import scala.concurrent.Await -import scala.concurrent.duration.Duration - class GridAgentSetup3WSpec extends ScalaTestWithActorTestKit with AnyWordSpecLike @@ -55,12 +40,13 @@ class GridAgentSetup3WSpec "The setup of grid agents" must { - val scheduler = TestProbe("scheduler") + val scheduler: TestProbe[SchedulerMessage] = + TestProbe[SchedulerMessage]("scheduler") val runtimeEventListener = TestProbe[RuntimeEvent]("listener") val primaryServiceProxy = TestProbe("primaryServiceProxy") val environmentRefs = EnvironmentRefs( - scheduler.ref.toClassic, + scheduler.ref, runtimeEventListener.ref, primaryServiceProxy = primaryServiceProxy.ref.toClassic, weather = ClassicRef.noSender, @@ -68,74 +54,49 @@ class GridAgentSetup3WSpec ) "provide three grid agents on presence of a three winding transformer" in { - implicit val timeout: Timeout = Timeout(1, TimeUnit.SECONDS) - implicit val scheduler: Scheduler = system.scheduler - - // in order to get an actor system we need a tmp actor that calls the corresponding method - val serviceKey = ServiceKey[GridAgentMessage]("gridAgent") - - val actor = testKit.spawn(Behaviors.setup[GridAgentMessage] { ctx => - ctx.system.receptionist ! Register(serviceKey, ctx.self) - Behaviors.receive[GridAgentMessage] { - case (ctx, PrepareNextSweepTrigger(tick)) => - SimonaStandaloneSetup( - typesafeConfig, - ResultFileHierarchy( - "test/tmp", - "GridAgentSetup3WSpec", - ResultEntityPathConfig( - Set.empty[Class[_ <: ResultEntity]], - ResultSinkType( - simonaConfig.simona.output.sink, - simonaConfig.simona.simulationName, - ), + val testKit = BehaviorTestKit(Behaviors.receive[GridAgentMessage] { + case (ctx, PrepareNextSweepTrigger(tick)) => + SimonaStandaloneSetup( + typesafeConfig, + ResultFileHierarchy( + "test/tmp", + "GridAgentSetup3WSpec", + ResultEntityPathConfig( + Set.empty[Class[_ <: ResultEntity]], + ResultSinkType( + simonaConfig.simona.output.sink, + simonaConfig.simona.simulationName, ), ), - ).buildSubGridToActorRefMap( - threeWindingTestGrid.getSubGridTopologyGraph, - ctx.asInstanceOf[ClassicContext], - environmentRefs, - Seq.empty[ClassicRef], - ) - ctx.self ! FinishGridSimulationTrigger(tick) - Behaviors.same - - case other => - fail(s"$other was not expected") - } + ), + ).buildSubGridToActorRefMap( + threeWindingTestGrid.getSubGridTopologyGraph, + ctx, + environmentRefs, + Seq.empty[ClassicRef], + ) + ctx.self ! FinishGridSimulationTrigger(tick) + Behaviors.same + + case other => + fail(s"$other was not expected") }) - Await.ready( - actor.ask[GridAgentMessage](_ => PrepareNextSweepTrigger(0)), - Duration(10, TimeUnit.SECONDS), - ) - - BehaviorTestKit(Behaviors.setup[Listing] { ctx => - logger.debug("Subscribing to the actors.") - ctx.system.receptionist ! Subscribe(serviceKey, ctx.self) + testKit.run(PrepareNextSweepTrigger(0)) - Behaviors.receiveMessagePartial[Listing] { - case serviceKey.Listing(listings) => - logger.debug("All responses received. Evaluating...") + // three actor should be spawned + testKit.expectEffectPF { case Spawned(_, str, _) => + str shouldBe "1" + } - listings.size should be(3) - val regex = """GridAgent_\d*""".r - val expectedSenders = - Vector("GridAgent_1", "GridAgent_2", "GridAgent_3") - val actualSenders = listings - .collect { case actorId: ActorRef[GridAgentMessage] => - val actorRefString = actorId.toString - regex.findFirstIn(actorRefString) - } - .flatten - .toVector + testKit.expectEffectPF { case Spawned(_, str, _) => + str shouldBe "2" + } - actualSenders should be(expectedSenders) - - Behaviors.same - } - }) + testKit.expectEffectPF { case Spawned(_, str, _) => + str shouldBe "3" + } } } diff --git a/src/test/scala/edu/ie3/simona/sim/SimonaSimFailSpec.scala b/src/test/scala/edu/ie3/simona/sim/SimonaSimFailSpec.scala deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala b/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala index fc2308c9f0..b179ffe60c 100644 --- a/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala @@ -7,13 +7,14 @@ package edu.ie3.simona.sim import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.api.ExtSimAdapter +import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{ DelayedStopHelper, ResultEventListener, RuntimeEventListener, } -import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.main.RunSimona.SimonaEnded import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.Completion @@ -23,7 +24,6 @@ import edu.ie3.simona.sim.SimonaSimSpec._ import edu.ie3.simona.sim.setup.{ExtSimSetupData, SimonaSetup} import edu.ie3.simona.test.common.UnitSpec import org.apache.pekko.actor.testkit.typed.scaladsl.{ - LogCapturing, ScalaTestWithActorTestKit, TestProbe, } @@ -441,8 +441,8 @@ object SimonaSimSpec { override def gridAgents( context: ActorContext[_], environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ActorRef[ResultEvent]], - ): Iterable[ClassicRef] = Iterable.empty + resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], + ): Iterable[ActorRef[GridAgentMessage]] = Iterable.empty override def extSimulations( context: ActorContext[_], diff --git a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala index 4bf91a8168..190501f8d3 100644 --- a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala @@ -6,12 +6,6 @@ package edu.ie3.simona.sim.setup -import org.apache.pekko.actor.{ - ActorSystem, - ActorContext, - ActorRef => ClassicRef, -} -import org.apache.pekko.actor.typed.ActorRef import edu.ie3.datamodel.exceptions.NotImplementedException import edu.ie3.datamodel.models.input.connector.{ ConnectorPort, @@ -21,14 +15,14 @@ import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{ResultEventListener, RuntimeEventListener} -import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.scheduler.TimeAdvancer import edu.ie3.simona.sim.SimonaSim import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.common.model.grid.SubGridGateMokka -import org.apache.pekko.actor.typed.scaladsl -import org.apache.pekko.actor.{ActorRef, typed} +import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.ActorContext +import org.apache.pekko.actor.{ActorRef => ClassicRef} import java.util.UUID @@ -37,53 +31,53 @@ class SimonaSetupSpec extends UnitSpec with SimonaSetup with SubGridGateMokka { override val args: Array[String] = Array.empty[String] override def runtimeEventListener( - context: scaladsl.ActorContext[_] - ): typed.ActorRef[RuntimeEventListener.Request] = // todo typed + context: ActorContext[_] + ): ActorRef[RuntimeEventListener.Request] = throw new NotImplementedException( "This is a dummy setup" ) override def resultEventListener( - context: scaladsl.ActorContext[_] - ): Seq[typed.ActorRef[ResultEventListener.Request]] = + context: ActorContext[_] + ): Seq[ActorRef[ResultEventListener.Request]] = throw new NotImplementedException("This is a dummy setup") override def primaryServiceProxy( - context: scaladsl.ActorContext[_], - scheduler: typed.ActorRef[SchedulerMessage], - ): ActorRef = throw new NotImplementedException("This is a dummy setup") + context: ActorContext[_], + scheduler: ActorRef[SchedulerMessage], + ): ClassicRef = throw new NotImplementedException("This is a dummy setup") override def weatherService( - context: scaladsl.ActorContext[_], - scheduler: typed.ActorRef[SchedulerMessage], - ): ActorRef = throw new NotImplementedException("This is a dummy setup") + context: ActorContext[_], + scheduler: ActorRef[SchedulerMessage], + ): ClassicRef = throw new NotImplementedException("This is a dummy setup") override def extSimulations( - context: scaladsl.ActorContext[_], - scheduler: typed.ActorRef[SchedulerMessage], + context: ActorContext[_], + scheduler: ActorRef[SchedulerMessage], ): ExtSimSetupData = throw new NotImplementedException( "This is a dummy setup" ) override def timeAdvancer( - context: scaladsl.ActorContext[_], - simulation: typed.ActorRef[SimonaSim.SimulationEnded.type], - runtimeEventListener: typed.ActorRef[RuntimeEvent], - ): typed.ActorRef[TimeAdvancer.Request] = throw new NotImplementedException( + context: ActorContext[_], + simulation: ActorRef[SimonaSim.SimulationEnded.type], + runtimeEventListener: ActorRef[RuntimeEvent], + ): ActorRef[TimeAdvancer.Request] = throw new NotImplementedException( "This is a dummy setup" ) override def scheduler( - context: scaladsl.ActorContext[_], - timeAdvancer: typed.ActorRef[TimeAdvancer.Request], - ): typed.ActorRef[SchedulerMessage] = throw new NotImplementedException( + context: ActorContext[_], + timeAdvancer: ActorRef[TimeAdvancer.Request], + ): ActorRef[SchedulerMessage] = throw new NotImplementedException( "This is a dummy setup" ) override def gridAgents( - context: scaladsl.ActorContext[_], + context: ActorContext[_], environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ClassicRef], + resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], ): Iterable[ActorRef[GridAgentMessage]] = throw new NotImplementedException("This is a dummy setup") From 46cdb8841052a2b3bff55f7a677b23f4916b3fad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:43:57 +0000 Subject: [PATCH 097/123] Bump com.sksamuel.scapegoat:scalac-scapegoat-plugin_2.13.12 (#752) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 84c534b02e..8b36a3241e 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ ext { jtsVersion = '1.19.0' confluentKafkaVersion = '7.4.0' tscfgVersion = '1.0.0' - scapegoatVersion = '2.1.3' + scapegoatVersion = '2.1.4' testContainerVersion = '0.41.3' From 73af727da83cc911638d69d6b7c7bd4c6a68fe8a Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Mon, 26 Feb 2024 12:28:22 +0100 Subject: [PATCH 098/123] Simplifying and unifying GridAgent setup tests --- .../agent/grid/GridAgentSetup2WSpec.scala | 99 ----------------- .../agent/grid/GridAgentSetup3WSpec.scala | 103 ------------------ .../agent/grid/GridAgentSetupSpec.scala | 88 +++++++++++++++ 3 files changed, 88 insertions(+), 202 deletions(-) delete mode 100644 src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala delete mode 100644 src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala create mode 100644 src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetupSpec.scala diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala deleted file mode 100644 index da08685dba..0000000000 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup2WSpec.scala +++ /dev/null @@ -1,99 +0,0 @@ -/* - * © 2020. TU Dortmund University, - * Institute of Energy Systems, Energy Efficiency and Energy Economics, - * Research group Distribution grid planning and operation - */ - -package edu.ie3.simona.agent.grid - -import com.typesafe.scalalogging.LazyLogging -import edu.ie3.datamodel.models.result.ResultEntity -import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgentMessage.{ - FinishGridSimulationTrigger, - PrepareNextSweepTrigger, -} -import edu.ie3.simona.event.RuntimeEvent -import edu.ie3.simona.io.result.ResultSinkType -import edu.ie3.simona.ontology.messages.SchedulerMessage -import edu.ie3.simona.sim.setup.SimonaStandaloneSetup -import edu.ie3.simona.test.common.ConfigTestData -import edu.ie3.simona.test.common.input.TransformerInputTestData -import edu.ie3.simona.util.ResultFileHierarchy -import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig -import org.apache.pekko.actor.testkit.typed.Effect.Spawned -import org.apache.pekko.actor.testkit.typed.scaladsl.{ - BehaviorTestKit, - ScalaTestWithActorTestKit, - TestProbe, -} -import org.apache.pekko.actor.typed.scaladsl.Behaviors -import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps -import org.apache.pekko.actor.{ActorRef => ClassicRef} -import org.scalatest.wordspec.AnyWordSpecLike - -class GridAgentSetup2WSpec - extends ScalaTestWithActorTestKit - with AnyWordSpecLike - with TransformerInputTestData - with ConfigTestData - with LazyLogging { - - "The setup of grid agents" must { - - val scheduler: TestProbe[SchedulerMessage] = - TestProbe[SchedulerMessage]("scheduler") - val runtimeEventListener = TestProbe[RuntimeEvent]("listener") - val primaryServiceProxy = TestProbe("primaryServiceProxy") - - val environmentRefs = EnvironmentRefs( - scheduler.ref, - runtimeEventListener.ref, - primaryServiceProxy = primaryServiceProxy.ref.toClassic, - weather = ClassicRef.noSender, - evDataService = None, - ) - - "provide two grid agents on presence of a two winding transformer" in { - val testKit = BehaviorTestKit(Behaviors.receive[GridAgentMessage] { - case (ctx, PrepareNextSweepTrigger(tick)) => - SimonaStandaloneSetup( - typesafeConfig, - ResultFileHierarchy( - "test/tmp", - "GridAgentSetup2WSpec", - ResultEntityPathConfig( - Set.empty[Class[_ <: ResultEntity]], - ResultSinkType( - simonaConfig.simona.output.sink, - simonaConfig.simona.simulationName, - ), - ), - ), - ).buildSubGridToActorRefMap( - gridContainer.getSubGridTopologyGraph, - ctx, - environmentRefs, - Seq.empty[ClassicRef], - ) - - ctx.self ! FinishGridSimulationTrigger(tick) - Behaviors.same - - case other => - fail(s"$other was not expected") - }) - - testKit.run(PrepareNextSweepTrigger(0)) - - // two actor should be spawned - testKit.expectEffectPF { case Spawned(_, str, _) => - str shouldBe "1" - } - - testKit.expectEffectPF { case Spawned(_, str, _) => - str shouldBe "2" - } - } - } -} diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala deleted file mode 100644 index 6e19a2185c..0000000000 --- a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetup3WSpec.scala +++ /dev/null @@ -1,103 +0,0 @@ -/* - * © 2020. TU Dortmund University, - * Institute of Energy Systems, Energy Efficiency and Energy Economics, - * Research group Distribution grid planning and operation - */ - -package edu.ie3.simona.agent.grid - -import com.typesafe.scalalogging.LazyLogging -import edu.ie3.datamodel.models.result.ResultEntity -import edu.ie3.simona.agent.EnvironmentRefs -import edu.ie3.simona.agent.grid.GridAgentMessage.{ - FinishGridSimulationTrigger, - PrepareNextSweepTrigger, -} -import edu.ie3.simona.event.RuntimeEvent -import edu.ie3.simona.io.result.ResultSinkType -import edu.ie3.simona.ontology.messages.SchedulerMessage -import edu.ie3.simona.sim.setup.SimonaStandaloneSetup -import edu.ie3.simona.test.common.{ConfigTestData, ThreeWindingTestData} -import edu.ie3.simona.util.ResultFileHierarchy -import edu.ie3.simona.util.ResultFileHierarchy.ResultEntityPathConfig -import org.apache.pekko.actor.testkit.typed.Effect.Spawned -import org.apache.pekko.actor.testkit.typed.scaladsl.{ - BehaviorTestKit, - ScalaTestWithActorTestKit, - TestProbe, -} -import org.apache.pekko.actor.typed.scaladsl.Behaviors -import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps -import org.apache.pekko.actor.{ActorRef => ClassicRef} -import org.scalatest.wordspec.AnyWordSpecLike - -class GridAgentSetup3WSpec - extends ScalaTestWithActorTestKit - with AnyWordSpecLike - with ThreeWindingTestData - with ConfigTestData - with LazyLogging { - - "The setup of grid agents" must { - - val scheduler: TestProbe[SchedulerMessage] = - TestProbe[SchedulerMessage]("scheduler") - val runtimeEventListener = TestProbe[RuntimeEvent]("listener") - val primaryServiceProxy = TestProbe("primaryServiceProxy") - - val environmentRefs = EnvironmentRefs( - scheduler.ref, - runtimeEventListener.ref, - primaryServiceProxy = primaryServiceProxy.ref.toClassic, - weather = ClassicRef.noSender, - evDataService = None, - ) - - "provide three grid agents on presence of a three winding transformer" in { - - val testKit = BehaviorTestKit(Behaviors.receive[GridAgentMessage] { - case (ctx, PrepareNextSweepTrigger(tick)) => - SimonaStandaloneSetup( - typesafeConfig, - ResultFileHierarchy( - "test/tmp", - "GridAgentSetup3WSpec", - ResultEntityPathConfig( - Set.empty[Class[_ <: ResultEntity]], - ResultSinkType( - simonaConfig.simona.output.sink, - simonaConfig.simona.simulationName, - ), - ), - ), - ).buildSubGridToActorRefMap( - threeWindingTestGrid.getSubGridTopologyGraph, - ctx, - environmentRefs, - Seq.empty[ClassicRef], - ) - ctx.self ! FinishGridSimulationTrigger(tick) - Behaviors.same - - case other => - fail(s"$other was not expected") - }) - - testKit.run(PrepareNextSweepTrigger(0)) - - // three actor should be spawned - testKit.expectEffectPF { case Spawned(_, str, _) => - str shouldBe "1" - } - - testKit.expectEffectPF { case Spawned(_, str, _) => - str shouldBe "2" - } - - testKit.expectEffectPF { case Spawned(_, str, _) => - str shouldBe "3" - } - } - } - -} diff --git a/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetupSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetupSpec.scala new file mode 100644 index 0000000000..5d7eea87c5 --- /dev/null +++ b/src/test/scala/edu/ie3/simona/agent/grid/GridAgentSetupSpec.scala @@ -0,0 +1,88 @@ +/* + * © 2020. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.agent.grid + +import edu.ie3.simona.agent.EnvironmentRefs +import edu.ie3.simona.sim.setup.SimonaStandaloneSetup +import edu.ie3.simona.test.common.input.TransformerInputTestData +import edu.ie3.simona.test.common.{ + ConfigTestData, + ThreeWindingTestData, + UnitSpec, +} +import edu.ie3.simona.util.ResultFileHierarchy +import org.apache.pekko.actor.testkit.typed.Effect.Spawned +import org.apache.pekko.actor.testkit.typed.scaladsl.BehaviorTestKit +import org.apache.pekko.actor.typed.scaladsl.Behaviors +import org.scalatestplus.mockito.MockitoSugar + +class GridAgentSetupSpec + extends UnitSpec + with MockitoSugar + with TransformerInputTestData + with ConfigTestData + with ThreeWindingTestData { + + "The setup of grid agents" must { + + "provide two grid agents on presence of a two winding transformer" in { + + val testKit = BehaviorTestKit(Behaviors.setup[AnyRef] { ctx => + SimonaStandaloneSetup( + typesafeConfig, + mock[ResultFileHierarchy], + ).buildSubGridToActorRefMap( + gridContainer.getSubGridTopologyGraph, + ctx, + mock[EnvironmentRefs], + Seq.empty, + ) + + Behaviors.stopped + }) + + // two actor should be spawned + testKit.expectEffectPF { case Spawned(_, actorName, _) => + actorName shouldBe "1" + } + + testKit.expectEffectPF { case Spawned(_, actorName, _) => + actorName shouldBe "2" + } + } + + "provide three grid agents on presence of a three winding transformer" in { + + val testKit = BehaviorTestKit(Behaviors.setup[AnyRef] { ctx => + SimonaStandaloneSetup( + typesafeConfig, + mock[ResultFileHierarchy], + ).buildSubGridToActorRefMap( + threeWindingTestGrid.getSubGridTopologyGraph, + ctx, + mock[EnvironmentRefs], + Seq.empty, + ) + + Behaviors.stopped + }) + + // three actor should be spawned + testKit.expectEffectPF { case Spawned(_, actorName, _) => + actorName shouldBe "1" + } + + testKit.expectEffectPF { case Spawned(_, actorName, _) => + actorName shouldBe "2" + } + + testKit.expectEffectPF { case Spawned(_, actorName, _) => + actorName shouldBe "3" + } + } + } +} From d7d2c14f9dc85a3bce42e7810ba9ce8178662bbe Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 26 Feb 2024 20:24:06 +0100 Subject: [PATCH 099/123] Implementing requested changes. --- .../ie3/simona/actor/SimonaActorNaming.scala | 10 +- .../ie3/simona/agent/grid/DBFSAlgorithm.scala | 235 +++++++++--------- .../edu/ie3/simona/agent/grid/GridAgent.scala | 46 ++-- .../agent/grid/GridAgentController.scala | 24 +- .../ie3/simona/agent/grid/GridAgentData.scala | 14 +- .../simona/agent/grid/GridAgentMessage.scala | 4 - .../agent/participant/ParticipantAgent.scala | 13 +- .../ie3/simona/sim/setup/SimonaSetup.scala | 4 +- .../sim/setup/SimonaStandaloneSetup.scala | 10 +- .../agent/grid/DBFSAlgorithmCenGridSpec.scala | 33 +-- .../DBFSAlgorithmFailedPowerFlowSpec.scala | 30 ++- .../grid/DBFSAlgorithmParticipantSpec.scala | 13 +- .../agent/grid/DBFSAlgorithmSupGridSpec.scala | 13 +- .../agent/grid/PowerFlowSupportSpec.scala | 2 +- .../ParticipantAgent2ListenerSpec.scala | 6 +- .../edu/ie3/simona/sim/SimonaSimSpec.scala | 4 +- .../simona/sim/setup/SetupHelperSpec.scala | 2 +- .../simona/sim/setup/SimonaSetupSpec.scala | 4 +- 18 files changed, 222 insertions(+), 245 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala b/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala index 0b4686d781..6aeeaf093c 100644 --- a/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala +++ b/src/main/scala/edu/ie3/simona/actor/SimonaActorNaming.scala @@ -7,6 +7,7 @@ package edu.ie3.simona.actor import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps import org.apache.pekko.actor.{ActorRefFactory, Props, ActorRef => ClassicRef} import java.util.UUID @@ -84,14 +85,7 @@ object SimonaActorNaming { * @return * the actor name extract from the ActorRef */ - def actorName(actorRef: ActorRef[_]): String = - actorRef.path.name match { - case "singleton" => - // singletons end in /${actorName}/singleton - actorRef.path.parent.name - case other => - other - } + def actorName(actorRef: ActorRef[_]): String = actorName(actorRef.toClassic) /** Constructs the type name from given props. * diff --git a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala index c9bb5ddc71..cae5528653 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -18,7 +18,7 @@ import edu.ie3.powerflow.model.enums.NodeType import edu.ie3.simona.agent.grid.GridAgent.idle import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentBaseData, - GridAgentValues, + GridAgentConstantData, PowerFlowDoneData, } import edu.ie3.simona.agent.grid.GridAgentMessage._ @@ -28,7 +28,10 @@ import edu.ie3.simona.agent.grid.VoltageMessage.{ ProvideSlackVoltageMessage, RequestSlackVoltageMessage, } -import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage +import edu.ie3.simona.agent.participant.ParticipantAgent.{ + FinishParticipantSimulation, + ParticipantMessage, +} import edu.ie3.simona.event.RuntimeEvent.PowerFlowFailed import edu.ie3.simona.exceptions.agent.DBFSAlgorithmException import edu.ie3.simona.model.grid.{NodeModel, RefSystem} @@ -75,10 +78,10 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentData: GridAgentData, currentTick: Long, )(implicit - values: GridAgentValues, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { - (ctx, message) => + ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + case (ctx, message) => (message, gridAgentData) match { // first part of the grid simulation, same for all gridAgents on all levels // we start with a forward-sweep by requesting the data from our child assets and grids (if any) @@ -165,14 +168,14 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { updatedGridAgentBaseData, currentTick, simulateGrid, - )(ctx, values, buffer) + )(ctx, constantData, buffer) } else { goToPowerFlowCalculationOrStay( allValuesReceived, updatedGridAgentBaseData, currentTick, simulateGrid, - )(ctx, values, buffer) + )(ctx, constantData, buffer) } // if we receive a request for slack voltages from our inferior grids we want to answer it @@ -180,7 +183,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { RequestSlackVoltageMessage( currentSweepNo, nodeUuids, - sender: ActorRef[GridAgentMessage], + sender, ), gridAgentBaseData: GridAgentBaseData, ) => @@ -278,11 +281,11 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // before power flow calc for this sweep we either have to stash() the message to answer it later (in current sweep) // or trigger a new run for the next sweepNo case ( - WrappedPowerMessage( + msg @ WrappedPowerMessage( RequestGridPowerMessage( requestSweepNo, - nodeUuids, - sender: ActorRef[GridAgentMessage], + _, + _, ) ), gridAgentBaseData: GridAgentBaseData, @@ -293,11 +296,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { requestSweepNo, ) - buffer.stash( - WrappedPowerMessage( - RequestGridPowerMessage(requestSweepNo, nodeUuids, sender) - ) - ) + buffer.stash(msg) Behaviors.same } else { @@ -308,11 +307,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) ctx.self ! PrepareNextSweepTrigger(currentTick) - buffer.stash( - WrappedPowerMessage( - RequestGridPowerMessage(requestSweepNo, nodeUuids, sender) - ) - ) + buffer.stash(msg) simulateGrid( gridAgentBaseData.copy(currentSweepNo = requestSweepNo), @@ -475,7 +470,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentBaseData.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => actors.foreach { actor => - actor.toClassic ! FinishGridSimulationTrigger(currentTick) + actor ! FinishParticipantSimulation(currentTick) } } @@ -485,8 +480,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) createAndSendPowerFlowResults( gridAgentBaseData, - currentTick.toDateTime(values.simStartTime), - )(ctx.log, values) + currentTick.toDateTime(constantData.simStartTime), + )(ctx.log, constantData) // do my cleanup stuff ctx.log.debug("Doing my cleanup stuff") @@ -499,18 +494,16 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) // / inform scheduler that we are done with the whole simulation and request new trigger for next time step - values.environmentRefs.scheduler ! Completion( - values.activationAdapter, - Some(currentTick + values.resolution), + constantData.environmentRefs.scheduler ! Completion( + constantData.activationAdapter, + Some(currentTick + constantData.resolution), ) // return to Idle idle(cleanedGridAgentBaseData) - case (StopGridAgent, _) => - Behaviors.stopped - - case (_, _) => + case _ => + // preventing "match may not be exhaustive" Behaviors.unhandled } } @@ -530,12 +523,11 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentData: GridAgentData, currentTick: Long, )(implicit - values: GridAgentValues, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { - (ctx, message) => + ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + case (ctx, message) => (message, gridAgentData) match { - // main method for power flow calculations case ( DoPowerFlowTrigger(currentTick, _), @@ -583,28 +575,29 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridModel.nodeUuidToIndexMap, ) ) - askForAssetPowers( - currentTick, - sweepValueStoreOpt, - gridAgentBaseData.gridEnv.nodeToAssetAgents, - gridModel.mainRefSystem, - gridAgentBaseData.powerFlowParams.sweepTimeout, - )(ctx) match { - case None => - // when we don't have assets we can skip another request for different asset behaviour due to changed - // voltage values and go back to SimulateGrid directly - ctx.log.debug( - s"No generation or load assets in the grid. Going back to SimulateGrid." - ) - // we can answer the stashed grid power requests now - buffer.unstashAll( - simulateGrid(powerFlowDoneData, currentTick) - ) + if ( + askForAssetPowers( + currentTick, + sweepValueStoreOpt, + gridAgentBaseData.gridEnv.nodeToAssetAgents, + gridModel.mainRefSystem, + gridAgentBaseData.powerFlowParams.sweepTimeout, + )(ctx) + ) { + // will return a future based on the `ask-pattern` which will be processed below + handlePowerFlowCalculations(powerFlowDoneData, currentTick) + } else { + // when we don't have assets we can skip another request for different asset behaviour due to changed + // voltage values and go back to SimulateGrid directly + ctx.log.debug( + s"No generation or load assets in the grid. Going back to SimulateGrid." + ) - case Some(_) => - // will return a future based on the `ask-pattern` which will be processed below - handlePowerFlowCalculations(powerFlowDoneData, currentTick) + // we can answer the stashed grid power requests now + buffer.unstashAll( + simulateGrid(powerFlowDoneData, currentTick) + ) } case failedNewtonRaphsonPFResult: FailedNewtonRaphsonPFResult => @@ -671,7 +664,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { updatedGridAgentBaseData, currentTick, handlePowerFlowCalculations, - )(ctx, values, buffer) + )(ctx, constantData, buffer) } else { // no changes from assets, we want to go back to SimulateGrid and report the LF results to our parent grids if any requests @@ -759,33 +752,31 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // when we don't have inferior grids and no assets both methods return None and we can skip doing another power // flow calculation otherwise we go back to simulate grid and wait for the answers - (askForAssetPowersOpt, askForInferiorGridPowersOpt) match { - case (None, None) => - ctx.log.debug( - "I don't have assets or child grids. " + - "Going back to SimulateGrid and provide the power flow result if there is any request left." - ) - - val powerFlowDoneData = - PowerFlowDoneData(gridAgentBaseData, validPowerFlowResult) + if (!askForAssetPowersOpt && !askForInferiorGridPowersOpt) { + ctx.log.debug( + "I don't have assets or child grids. " + + "Going back to SimulateGrid and provide the power flow result if there is any request left." + ) - // we can answer the stashed grid power requests now - buffer.unstashAll( - simulateGrid(powerFlowDoneData, currentTick) - ) + val powerFlowDoneData = + PowerFlowDoneData(gridAgentBaseData, validPowerFlowResult) - case _ => - ctx.log.debug( - "Going back to SimulateGrid and wait for my assets or inferior grids to return." - ) + // we can answer the stashed grid power requests now + buffer.unstashAll( + simulateGrid(powerFlowDoneData, currentTick) + ) + } else { + ctx.log.debug( + "Going back to SimulateGrid and wait for my assets or inferior grids to return." + ) - // go back to simulate grid - simulateGrid( - gridAgentBaseData - .updateWithReceivedSlackVoltages(receivedSlackValues) - .copy(sweepValueStores = updatedSweepValueStore), - currentTick, - ) + // go back to simulate grid + simulateGrid( + gridAgentBaseData + .updateWithReceivedSlackVoltages(receivedSlackValues) + .copy(sweepValueStores = updatedSweepValueStore), + currentTick, + ) } case failedNewtonRaphsonPFResult: FailedNewtonRaphsonPFResult => @@ -805,8 +796,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // (only possible when first simulation triggered and this agent is faster in this state as the request // by a superior grid arrives) case ( - WrappedPowerMessage( - requestGridPowerMessage: RequestGridPowerMessage + msg @ WrappedPowerMessage( + _: RequestGridPowerMessage ), _: GridAgentBaseData, ) => @@ -814,15 +805,15 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { "Received Request for Grid Power too early. Stashing away" ) - buffer.stash(WrappedPowerMessage(requestGridPowerMessage)) + buffer.stash(msg) Behaviors.same // happens only when we received slack data and power values before we received a request to provide grid // (only possible when first simulation triggered and this agent is faster // with its power flow calculation in this state as the request by a superior grid arrives) case ( - WrappedPowerMessage( - requestGridPowerMessage: RequestGridPowerMessage + msg @ WrappedPowerMessage( + _: RequestGridPowerMessage ), _: PowerFlowDoneData, ) => @@ -830,13 +821,11 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { "Received Request for Grid Power too early. Stashing away" ) - buffer.stash(WrappedPowerMessage(requestGridPowerMessage)) + buffer.stash(msg) Behaviors.same - case (StopGridAgent, _) => - Behaviors.stopped - - case (_, _) => + case _ => + // preventing "match may not be exhaustive" Behaviors.unhandled } } @@ -851,9 +840,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { private def checkPowerDifferences( gridAgentBaseData: GridAgentBaseData )(implicit - values: GridAgentValues, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { case (ctx, CheckPowerDifferencesTrigger(currentTick)) => ctx.log.debug("Starting the power differences check ...") @@ -993,15 +982,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { failedResult.cause, ) ctx.self ! FinishGridSimulationTrigger(currentTick) - handlePowerFlowFailure(gridAgentBaseData)(ctx, values) + handlePowerFlowFailure(gridAgentBaseData)(ctx, constantData) simulateGrid(gridAgentBaseData, currentTick) } - - case (_, StopGridAgent) => - Behaviors.stopped - - case (_, _) => - Behaviors.unhandled } /** Checks if all data has been received and if yes checks if the there are @@ -1029,7 +1012,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { behavior: (GridAgentData, Long) => Behavior[GridAgentMessage], )(implicit ctx: ActorContext[GridAgentMessage], - values: GridAgentValues, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = if (allReceived) { @@ -1100,7 +1083,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { behavior: (GridAgentData, Long) => Behavior[GridAgentMessage], )(implicit ctx: ActorContext[GridAgentMessage], - values: GridAgentValues, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = { if (allReceived) { @@ -1143,13 +1126,12 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentBaseData: GridAgentBaseData )(implicit ctx: ActorContext[GridAgentMessage], - values: GridAgentValues, + constantData: GridAgentConstantData, ): Unit = { - values.environmentRefs.runtimeEventListener ! PowerFlowFailed + constantData.environmentRefs.runtimeEventListener ! PowerFlowFailed if (gridAgentBaseData.powerFlowParams.stopOnFailure) { ctx.log.error("Stopping because of failed power flow.") - Behaviors.stopped } } @@ -1171,11 +1153,11 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridAgentBaseData: GridAgentBaseData, currentTick: Long, )(implicit - values: GridAgentValues, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = { - values.environmentRefs.scheduler ! Completion( - values.activationAdapter, + constantData.environmentRefs.scheduler ! Completion( + constantData.activationAdapter, Some(currentTick), ) @@ -1198,6 +1180,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * this [[GridAgent]] * @param askTimeout * a timeout for the request + * @return + * true if this grids contains assets or false if no request has been send + * due to non-existence of assets */ private def askForAssetPowers( currentTick: Long, @@ -1207,7 +1192,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { askTimeout: Duration, )(implicit ctx: ActorContext[GridAgentMessage] - ): Option[Future[GridAgentMessage]] = { + ): Boolean = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) implicit val ec: ExecutionContext = ctx.executionContext @@ -1260,8 +1245,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { .map(res => ReceivedAssetPowerValues(res)) pipeToSelf(future, ctx) - Some(future) - } else None + true + } else false } /** Triggers an execution of the pekko `ask` pattern for all power values @ @@ -1274,6 +1259,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * [[ActorRef]] s of [[GridAgent]] s @ these nodes * @param askTimeout * a timeout for the request + * @return + * true if this grids has connected inferior grids or false if this no + * inferior grids */ private def askInferiorGridsForPowers( currentSweepNo: Int, @@ -1282,7 +1270,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { askTimeout: Duration, )(implicit ctx: ActorContext[GridAgentMessage] - ): Option[Future[GridAgentMessage]] = { + ): Boolean = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) implicit val ec: ExecutionContext = ctx.executionContext implicit val scheduler: Scheduler = ctx.system.scheduler @@ -1292,7 +1280,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { inferiorGridGates, ) - Option.when(inferiorGridGates.nonEmpty) { + if (inferiorGridGates.nonEmpty) { val future = Future .sequence( inferiorGridGates @@ -1332,8 +1320,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) .map(res => ReceivedGridPowerValues(res)) pipeToSelf(future, ctx) - future - } + true + } else false } /** Triggers an execution of the pekko `ask` pattern for all slack voltages of @@ -1346,6 +1334,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * [[ActorRef]] s of [[GridAgent]] s @ these nodes * @param askTimeout * a timeout for the request + * @return + * true if this grids has connected superior grids or false if this no + * superior grids */ private def askSuperiorGridsForSlackVoltages( currentSweepNo: Int, @@ -1354,7 +1345,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { askTimeout: Duration, )(implicit ctx: ActorContext[GridAgentMessage] - ): Option[Future[GridAgentMessage]] = { + ): Boolean = { implicit val timeout: PekkoTimeout = PekkoTimeout.create(askTimeout) implicit val ec: ExecutionContext = ctx.executionContext implicit val scheduler: Scheduler = ctx.system.scheduler @@ -1364,7 +1355,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { superiorGridGates, ) - Option.when(superiorGridGates.nonEmpty) { + if (superiorGridGates.nonEmpty) { val future = Future .sequence( superiorGridGates @@ -1386,8 +1377,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) .map(res => ReceivedSlackVoltageValues(res)) pipeToSelf(future, ctx) - future - } + true + } else false } /** Create an instance of @@ -1407,11 +1398,11 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { currentTimestamp: ZonedDateTime, )(implicit log: Logger, - values: GridAgentValues, + constantData: GridAgentConstantData, ): Unit = { gridAgentBaseData.sweepValueStores.lastOption.foreach { case (_, valueStore) => - values.notifyListener( + constantData.notifyListeners( this.createResultModels( gridAgentBaseData.gridEnv.gridModel, valueStore, @@ -1423,7 +1414,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { } } - /** Simple method to pipe a future to itself. + /** This method uses [[ActorContext.pipeToSelf()]] to send a future message to + * itself. If the future is a [[Success]] the message is send, else a + * [[ReceivedFailure]] with the thrown error is send. * @param future * value * @param ctx diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index c773c2ffe1..6d2cfaaf3b 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -10,8 +10,8 @@ import edu.ie3.simona.actor.SimonaActorNaming import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentBaseData, + GridAgentConstantData, GridAgentInitData, - GridAgentValues, } import edu.ie3.simona.agent.grid.GridAgentMessage._ import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage @@ -26,13 +26,9 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ } import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.TimeUtil -import org.apache.pekko.actor.typed.scaladsl.adapter.{ - ClassicActorRefOps, - TypedActorContextOps, -} +import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorContextOps import org.apache.pekko.actor.typed.scaladsl.{Behaviors, StashBuffer} import org.apache.pekko.actor.typed.{ActorRef, Behavior} -import org.apache.pekko.actor.{ActorRef => ClassicRef} import java.time.ZonedDateTime import java.time.temporal.ChronoUnit @@ -44,7 +40,7 @@ object GridAgent extends DBFSAlgorithm { def apply( environmentRefs: EnvironmentRefs, simonaConfig: SimonaConfig, - listener: Iterable[ClassicRef], + listener: Iterable[ActorRef[ResultEvent]], ): Behavior[GridAgentMessage] = Behaviors.withStash(100) { buffer => Behaviors.setup[GridAgentMessage] { context => context.messageAdapter(msg => WrappedPowerMessage(msg)) @@ -59,7 +55,7 @@ object GridAgent extends DBFSAlgorithm { val simStartTime: ZonedDateTime = TimeUtil.withDefaults .toZonedDateTime(simonaConfig.simona.time.startDateTime) - val agentValues = GridAgentValues( + val agentValues = GridAgentConstantData( environmentRefs, simonaConfig, listener, @@ -73,10 +69,10 @@ object GridAgent extends DBFSAlgorithm { } private def uninitialized(implicit - values: GridAgentValues, + values: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = - Behaviors.receiveMessage[GridAgentMessage] { + Behaviors.receiveMessagePartial[GridAgentMessage] { case CreateGridAgent(gridAgentInitData, unlockKey) => values.environmentRefs.scheduler ! ScheduleActivation( values.activationAdapter, @@ -85,20 +81,14 @@ object GridAgent extends DBFSAlgorithm { ) initializing(gridAgentInitData) - - case GridAgentMessage.StopGridAgent => - Behaviors.stopped - - case _ => - Behaviors.unhandled } private def initializing( gridAgentInitData: GridAgentInitData )(implicit - values: GridAgentValues, + values: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { + ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { case (ctx, WrappedActivation(Activation(INIT_SIM_TICK))) => // fail fast sanity checks failFast(gridAgentInitData, SimonaActorNaming.actorName(ctx.self)) @@ -139,7 +129,7 @@ object GridAgent extends DBFSAlgorithm { val gridAgentController = new GridAgentController( - ctx.toClassic, + ctx, values.environmentRefs, values.simStartTime, TimeUtil.withDefaults @@ -147,7 +137,7 @@ object GridAgent extends DBFSAlgorithm { values.simonaConfig.simona.runtime.participant, values.simonaConfig.simona.output.participant, values.resolution, - values.listener.map(_.toTyped[ResultEvent]), + values.listener, ctx.log, ) @@ -192,11 +182,6 @@ object GridAgent extends DBFSAlgorithm { ) idle(gridAgentBaseData) - case (_, StopGridAgent) => - Behaviors.stopped - - case (_, _) => - Behaviors.unhandled } /** Method that defines the idle [[Behavior]] of the agent. @@ -213,13 +198,13 @@ object GridAgent extends DBFSAlgorithm { private[grid] def idle( gridAgentBaseData: GridAgentBaseData )(implicit - values: GridAgentValues, + values: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receive[GridAgentMessage] { - case (_, pm: WrappedPowerMessage) => + ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + case (_, msg @ WrappedPowerMessage(_)) => // needs to be set here to handle if the messages arrive too early // before a transition to GridAgentBehaviour took place - buffer.stash(pm) + buffer.stash(msg) Behaviors.same case (_, WrappedActivation(activation: Activation)) => @@ -228,9 +213,6 @@ object GridAgent extends DBFSAlgorithm { Some(activation.tick), ) buffer.unstashAll(simulateGrid(gridAgentBaseData, activation.tick)) - - case _ => - Behaviors.unhandled } private def failFast( diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala index b97e6e5fc3..a8904c9ef9 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala @@ -33,11 +33,13 @@ import edu.ie3.simona.util.ConfigUtil import edu.ie3.simona.util.ConfigUtil._ import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import org.apache.pekko.actor.typed.ActorRef +import org.apache.pekko.actor.typed.scaladsl.ActorContext import org.apache.pekko.actor.typed.scaladsl.adapter.{ ClassicActorRefOps, + TypedActorContextOps, TypedActorRefOps, } -import org.apache.pekko.actor.{ActorContext, ActorRef => ClassicRef} +import org.apache.pekko.actor.{ActorRef => ClassicRef} import org.slf4j.Logger import java.time.ZonedDateTime @@ -68,7 +70,7 @@ import scala.jdk.CollectionConverters._ * @since 2019-07-18 */ class GridAgentController( - gridAgentContext: ActorContext, + gridAgentContext: ActorContext[_], environmentRefs: EnvironmentRefs, simulationStartDate: ZonedDateTime, simulationEndDate: ZonedDateTime, @@ -196,7 +198,7 @@ class GridAgentController( thermalIslandGridsByBusId, environmentRefs, ) - introduceAgentToEnvironment(actorRef.toClassic) + introduceAgentToEnvironment(actorRef) // return uuid to actorRef node.getUuid -> actorRef }) @@ -343,7 +345,7 @@ class GridAgentController( requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig, ): ActorRef[ParticipantMessage] = - gridAgentContext + gridAgentContext.toClassic .simonaActorOf( FixedFeedInAgent.props( environmentRefs.scheduler.toClassic, @@ -396,7 +398,7 @@ class GridAgentController( requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig, ): ActorRef[ParticipantMessage] = - gridAgentContext + gridAgentContext.toClassic .simonaActorOf( LoadAgent.props( environmentRefs.scheduler.toClassic, @@ -452,7 +454,7 @@ class GridAgentController( requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig, ): ActorRef[ParticipantMessage] = - gridAgentContext + gridAgentContext.toClassic .simonaActorOf( PvAgent.props( environmentRefs.scheduler.toClassic, @@ -508,7 +510,7 @@ class GridAgentController( requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig, ): ActorRef[ParticipantMessage] = - gridAgentContext + gridAgentContext.toClassic .simonaActorOf( EvcsAgent.props( environmentRefs.scheduler.toClassic, @@ -559,7 +561,7 @@ class GridAgentController( requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig, ): ActorRef[ParticipantMessage] = - gridAgentContext + gridAgentContext.toClassic .simonaActorOf( HpAgent.props( environmentRefs.scheduler.toClassic, @@ -616,7 +618,7 @@ class GridAgentController( requestVoltageDeviationThreshold: Double, outputConfig: NotifierConfig, ): ActorRef[ParticipantMessage] = - gridAgentContext + gridAgentContext.toClassic .simonaActorOf( WecAgent.props( environmentRefs.scheduler.toClassic, @@ -643,11 +645,11 @@ class GridAgentController( * Reference to the actor to add to the environment */ private def introduceAgentToEnvironment( - actorRef: ClassicRef + actorRef: ActorRef[ParticipantMessage] ): Unit = { gridAgentContext.watch(actorRef) environmentRefs.scheduler ! ScheduleActivation( - actorRef.toTyped, + actorRef.toClassic.toTyped, INIT_SIM_TICK, ) } diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala index d5a726bd0b..8f014f40e2 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala @@ -18,7 +18,7 @@ import edu.ie3.simona.agent.grid.ReceivedValues.{ import edu.ie3.simona.agent.grid.ReceivedValuesStore.NodeToReceivedPower import edu.ie3.simona.agent.participant.ParticipantAgent.ParticipantMessage import edu.ie3.simona.config.SimonaConfig -import edu.ie3.simona.event.notifier.Notifier +import edu.ie3.simona.event.ResultEvent import edu.ie3.simona.model.grid.{GridModel, RefSystem} import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.PowerMessage.{ @@ -28,8 +28,6 @@ import edu.ie3.simona.ontology.messages.PowerMessage.{ ProvidePowerMessage, } import org.apache.pekko.actor.typed.ActorRef -import org.apache.pekko.actor.typed.scaladsl.StashBuffer -import org.apache.pekko.actor.{ActorRef => ClassicRef} import java.time.ZonedDateTime import java.util.UUID @@ -54,14 +52,18 @@ object GridAgentData { * @param activationAdapter * adapter for [[Activation]] */ - final case class GridAgentValues private ( + final case class GridAgentConstantData private ( environmentRefs: EnvironmentRefs, simonaConfig: SimonaConfig, - override val listener: Iterable[ClassicRef], + listener: Iterable[ActorRef[ResultEvent]], resolution: Long, simStartTime: ZonedDateTime, activationAdapter: ActorRef[Activation], - ) extends Notifier + ) { + def notifyListeners(event: ResultEvent): Unit = { + listener.foreach(listener => listener ! event) + } + } /** Data that is send to the [[GridAgent]] directly after startup. It contains * the main information for initialization. This data should include all diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala index 4a2b4dbe1c..a40d5bb9e8 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentMessage.scala @@ -73,10 +73,6 @@ object GridAgentMessage { final case class FinishGridSimulationTrigger(tick: Long) extends GridAgentMessage - /** Message that should be send by the - */ - final object StopGridAgent extends GridAgentMessage - /** Wrapper for activation values * * @param activation diff --git a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala index 01673099c1..a01c5677a1 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala @@ -7,9 +7,8 @@ package edu.ie3.simona.agent.participant import edu.ie3.datamodel.models.input.system.SystemParticipantInput -import edu.ie3.simona.agent.{SimonaAgent, ValueStore} -import edu.ie3.simona.agent.grid.GridAgentMessage.FinishGridSimulationTrigger import edu.ie3.simona.agent.participant.ParticipantAgent.{ + FinishParticipantSimulation, StartCalculationTrigger, getAndCheckNodalVoltage, } @@ -33,6 +32,7 @@ import edu.ie3.simona.agent.state.ParticipantAgentState.{ Calculate, HandleInformation, } +import edu.ie3.simona.agent.{SimonaAgent, ValueStore} import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.event.notifier.NotifierConfig import edu.ie3.simona.exceptions.agent.InconsistentStateException @@ -44,13 +44,13 @@ import edu.ie3.simona.model.participant.{ SystemParticipant, } import edu.ie3.simona.ontology.messages.Activation +import edu.ie3.simona.ontology.messages.PowerMessage.RequestAssetPowerMessage +import edu.ie3.simona.ontology.messages.SchedulerMessage.ScheduleActivation import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage.{ FlexResponse, IssueFlexControl, RequestFlexOptions, } -import edu.ie3.simona.ontology.messages.PowerMessage.RequestAssetPowerMessage -import edu.ie3.simona.ontology.messages.SchedulerMessage.ScheduleActivation import edu.ie3.simona.ontology.messages.services.ServiceMessage.RegistrationResponseMessage.RegistrationSuccessfulMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.{ PrimaryServiceRegistrationMessage, @@ -215,7 +215,7 @@ abstract class ParticipantAgent[ ) case Event( - FinishGridSimulationTrigger(tick), + FinishParticipantSimulation(tick), baseStateData: BaseStateData[PD], ) => // clean up agent result value store @@ -872,6 +872,9 @@ object ParticipantAgent { trait ParticipantMessage + final case class FinishParticipantSimulation(tick: Long) + extends ParticipantMessage + final case class StartCalculationTrigger(tick: Long) /** Verifies that a nodal voltage value has been provided in the model diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala b/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala index ee850a092d..16809499b0 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SimonaSetup.scala @@ -10,8 +10,8 @@ import edu.ie3.datamodel.graph.SubGridGate import edu.ie3.datamodel.models.input.connector.Transformer3WInput import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentMessage -import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{ResultEventListener, RuntimeEventListener} +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.scheduler.TimeAdvancer import edu.ie3.simona.sim.SimonaSim @@ -149,7 +149,7 @@ trait SimonaSetup { def gridAgents( context: ActorContext[_], environmentRefs: EnvironmentRefs, - resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], + resultEventListeners: Seq[ActorRef[ResultEvent]], ): Iterable[ActorRef[GridAgentMessage]] /** SIMONA links sub grids connected by a three winding transformer a bit diff --git a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala index d43c2ec4ba..322d02bc93 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/SimonaStandaloneSetup.scala @@ -20,8 +20,8 @@ import edu.ie3.simona.api.data.ExtData import edu.ie3.simona.api.data.ev.{ExtEvData, ExtEvSimulation} import edu.ie3.simona.api.simulation.ExtSimAdapterData import edu.ie3.simona.config.{ArgsParser, RefSystemParser, SimonaConfig} -import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{ResultEventListener, RuntimeEventListener} +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.io.grid.GridProvider import edu.ie3.simona.ontology.messages.SchedulerMessage @@ -68,7 +68,7 @@ class SimonaStandaloneSetup( override def gridAgents( context: ActorContext[_], environmentRefs: EnvironmentRefs, - resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], + resultEventListeners: Seq[ActorRef[ResultEvent]], ): Iterable[ActorRef[GridAgentMessage]] = { /* get the grid */ @@ -91,7 +91,7 @@ class SimonaStandaloneSetup( subGridTopologyGraph, context, environmentRefs, - resultEventListeners.map(_.toClassic), + resultEventListeners, ) val keys = ScheduleLock.multiKey( @@ -322,7 +322,7 @@ class SimonaStandaloneSetup( subGridTopologyGraph: SubGridTopologyGraph, context: ActorContext[_], environmentRefs: EnvironmentRefs, - systemParticipantListener: Seq[ClassicRef], + resultEventListeners: Seq[ActorRef[ResultEvent]], ): Map[Int, ActorRef[GridAgentMessage]] = { subGridTopologyGraph .vertexSet() @@ -333,7 +333,7 @@ class SimonaStandaloneSetup( GridAgent( environmentRefs, simonaConfig, - systemParticipantListener, + resultEventListeners, ), subGridContainer.getSubnet.toString, ) diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala index 56af76d286..6a715fb7dc 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala @@ -10,8 +10,10 @@ import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.agent.grid.GridAgentMessage._ +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent -import edu.ie3.simona.event.listener.ResultEventListener.Request +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower @@ -19,9 +21,6 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } -import VoltageMessage.ProvideSlackVoltageMessage -import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage -import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGrid @@ -83,7 +82,8 @@ class DBFSAlgorithmCenGridSpec evDataService = None, ) - val resultListener: TestProbe[Request] = TestProbe[Request]("resultListener") + val resultListener: TestProbe[ResultEvent] = + TestProbe[ResultEvent]("resultListener") "A GridAgent actor in center position with async test" should { @@ -92,7 +92,7 @@ class DBFSAlgorithmCenGridSpec GridAgent( environmentRefs, simonaConfig, - listener = Iterable(resultListener.ref.toClassic), + listener = Iterable(resultListener.ref), ) ) @@ -129,20 +129,23 @@ class DBFSAlgorithmCenGridSpec key, ) - val msg = scheduler.expectMessageType[ScheduleActivation] - msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) + val gridAgentActivation = scheduler.expectMessageType[ScheduleActivation] + gridAgentActivation shouldBe ScheduleActivation( + gridAgentActivation.actor, + INIT_SIM_TICK, + Some(key), + ) centerGridAgent ! WrappedActivation(Activation(INIT_SIM_TICK)) - val completionMessage = scheduler.expectMessageType[Completion] - completionMessage shouldBe Completion(msg.actor, Some(3600)) + scheduler.expectMessage(Completion(gridAgentActivation.actor, Some(3600))) } s"go to SimulateGrid when it receives an activity start trigger" in { centerGridAgent ! WrappedActivation(Activation(3600)) - val msg = scheduler.expectMessageType[Completion] - msg shouldBe Completion(msg.actor, Some(3600)) + val completionMessage = scheduler.expectMessageType[Completion] + completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) } s"start the simulation when activation is sent" in { @@ -447,10 +450,10 @@ class DBFSAlgorithmCenGridSpec inferiorGrid13.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a CompletionMessage - val cm = scheduler.expectMessageType[Completion] - cm shouldBe Completion(cm.actor, Some(7200)) + val completionMessage = scheduler.expectMessageType[Completion] + completionMessage shouldBe Completion(completionMessage.actor, Some(7200)) - val resultMessage = resultListener.expectMessageType[Request] + val resultMessage = resultListener.expectMessageType[ResultEvent] resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => // we expect results for 4 nodes, 5 lines and 2 transformer2ws diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala index 672e5342c3..b198914136 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala @@ -10,7 +10,9 @@ import edu.ie3.datamodel.models.input.container.ThermalGrid import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.agent.grid.GridAgentMessage._ -import edu.ie3.simona.event.listener.ResultEventListener.Request +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ @@ -21,9 +23,6 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } -import VoltageMessage.ProvideSlackVoltageMessage -import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage -import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.scheduler.ScheduleLock import edu.ie3.simona.test.common.model.grid.DbfsTestGrid @@ -70,7 +69,8 @@ class DBFSAlgorithmFailedPowerFlowSpec evDataService = None, ) - val resultListener: TestProbe[Request] = TestProbe[Request]("resultListener") + val resultListener: TestProbe[ResultEvent] = + TestProbe[ResultEvent]("resultListener") "A GridAgent actor in center position with async test" should { @@ -79,7 +79,7 @@ class DBFSAlgorithmFailedPowerFlowSpec GridAgent( environmentRefs, simonaConfig, - listener = Iterable(resultListener.ref.toClassic), + listener = Iterable(resultListener.ref), ) ) @@ -112,11 +112,15 @@ class DBFSAlgorithmFailedPowerFlowSpec key, ) - val msg = scheduler.expectMessageType[ScheduleActivation] - msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) + val gridAgentActivation = scheduler.expectMessageType[ScheduleActivation] + gridAgentActivation shouldBe ScheduleActivation( + gridAgentActivation.actor, + INIT_SIM_TICK, + Some(key), + ) centerGridAgent ! WrappedActivation(Activation(INIT_SIM_TICK)) - scheduler.expectMessage(Completion(msg.actor, Some(3600))) + scheduler.expectMessage(Completion(gridAgentActivation.actor, Some(3600))) } s"go to SimulateGrid when it receives an activation" in { @@ -125,8 +129,8 @@ class DBFSAlgorithmFailedPowerFlowSpec centerGridAgent ! WrappedActivation(Activation(3600)) // we expect a completion message - val message = scheduler.expectMessageType[Completion] - message shouldBe Completion(message.actor, Some(3600)) + val completionMessage = scheduler.expectMessageType[Completion] + completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) } s"start the simulation when an activation is sent is sent, handle failed power flow if it occurs" in { @@ -208,8 +212,8 @@ class DBFSAlgorithmFailedPowerFlowSpec inferiorGridAgent.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a CompletionMessage - val message = scheduler.expectMessageType[Completion] - message shouldBe Completion(message.actor, Some(7200)) + val completionMessage = scheduler.expectMessageType[Completion] + completionMessage shouldBe Completion(completionMessage.actor, Some(7200)) resultListener.expectNoMessage() diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala index eb4946d119..0d8afa972e 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala @@ -14,16 +14,15 @@ import edu.ie3.simona.agent.grid.GridAgentMessage.{ FinishGridSimulationTrigger, WrappedActivation, } -import edu.ie3.simona.event.listener.ResultEventListener.Request +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage +import edu.ie3.simona.agent.grid.VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } -import VoltageMessage.ProvideSlackVoltageMessage -import VoltageMessage.ProvideSlackVoltageMessage.ExchangeVoltage -import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.ontology.messages.services.ServiceMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.PrimaryServiceRegistrationMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.RegistrationResponseMessage.RegistrationFailedMessage @@ -66,8 +65,8 @@ class DBFSAlgorithmParticipantSpec evDataService = None, ) - protected val resultListener: TestProbe[Request] = - TestProbe[Request]("resultListener") + protected val resultListener: TestProbe[ResultEvent] = + TestProbe[ResultEvent]("resultListener") private val superiorGridAgent = SuperiorGA( TestProbe("superiorGridAgent_1000"), @@ -79,7 +78,7 @@ class DBFSAlgorithmParticipantSpec GridAgent( environmentRefs, simonaConfig, - Iterable(resultListener.ref.toClassic), + Iterable(resultListener.ref), ) ) diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala index f4f43b5757..57e6c1f507 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala @@ -17,8 +17,7 @@ import edu.ie3.simona.agent.grid.GridAgentMessage.{ WrappedPowerMessage, } import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent -import edu.ie3.simona.event.RuntimeEvent -import edu.ie3.simona.event.listener.ResultEventListener.Request +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.model.grid.RefSystem import edu.ie3.simona.ontology.messages.PowerMessage.ProvideGridPowerMessage.ExchangePower import edu.ie3.simona.ontology.messages.PowerMessage.{ @@ -77,14 +76,15 @@ class DBFSAlgorithmSupGridSpec evDataService = None, ) - val resultListener: TestProbe[Request] = TestProbe[Request]("resultListener") + val resultListener: TestProbe[ResultEvent] = + TestProbe[ResultEvent]("resultListener") "A GridAgent actor in superior position with async test" should { val superiorGridAgentFSM: ActorRef[GridAgentMessage] = testKit.spawn( GridAgent( environmentRefs, simonaConfig, - listener = Iterable(resultListener.ref.toClassic), + listener = Iterable(resultListener.ref), ) ) @@ -179,8 +179,7 @@ class DBFSAlgorithmSupGridSpec // we expect another completion message when the agent is in SimulateGrid again case Completion(_, Some(7200)) => // agent should be in Idle again and listener should contain power flow result data - val resultMessage = - resultListener.expectMessageType[Request] + val resultMessage = resultListener.expectMessageType[ResultEvent] resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => @@ -309,7 +308,7 @@ class DBFSAlgorithmSupGridSpec case Completion(_, Some(7200)) => // after doing cleanup stuff, our agent should go back to idle again and listener should contain power flow result data val resultMessage = - resultListener.expectMessageType[Request] + resultListener.expectMessageType[ResultEvent] resultMessage match { case powerFlowResultEvent: PowerFlowResultEvent => diff --git a/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala index 070e771241..719930b288 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/PowerFlowSupportSpec.scala @@ -43,7 +43,7 @@ class PowerFlowSupportSpec implicit val log: Logger = LoggerFactory.getLogger(this.getClass) val actorRef: ActorRef[GridAgentMessage] = - TestProbe[GridAgentMessage]("noSender").ref + TestProbe[GridAgentMessage]("mock_grid_agent").ref /** Setting voltage at slack node to 110 kV and introducing a load of 1 MW at * node 1 diff --git a/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala index 9155f8e480..2db9a91fc0 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/ParticipantAgent2ListenerSpec.scala @@ -9,7 +9,7 @@ package edu.ie3.simona.agent.participant import com.typesafe.config.ConfigFactory import edu.ie3.datamodel.models.input.system.SystemParticipantInput import edu.ie3.datamodel.models.result.system.SystemParticipantResult -import edu.ie3.simona.agent.grid.GridAgentMessage.FinishGridSimulationTrigger +import edu.ie3.simona.agent.participant.ParticipantAgent.FinishParticipantSimulation import edu.ie3.simona.agent.participant.data.Data.PrimaryData.ApparentPower import edu.ie3.simona.agent.participant.statedata.ParticipantStateData.ParticipantInitializeStateData import edu.ie3.simona.config.SimonaConfig @@ -241,7 +241,7 @@ class ParticipantAgent2ListenerSpec case unknownMsg => fail(s"Received unexpected message: $unknownMsg") } - scheduler.send(mockAgent, FinishGridSimulationTrigger(3000L)) + scheduler.send(mockAgent, FinishParticipantSimulation(3000L)) /* Wait for the result event (this is the event listener) */ logger.warn( @@ -303,7 +303,7 @@ class ParticipantAgent2ListenerSpec case unknownMsg => fail(s"Received unexpected message: $unknownMsg") } - scheduler.send(mockAgent, FinishGridSimulationTrigger(3000L)) + scheduler.send(mockAgent, FinishParticipantSimulation(3000L)) /* Make sure nothing else is sent */ expectNoMessage(noReceiveTimeOut.duration) diff --git a/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala b/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala index b179ffe60c..07522bfe44 100644 --- a/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/SimonaSimSpec.scala @@ -9,7 +9,7 @@ package edu.ie3.simona.sim import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentMessage import edu.ie3.simona.api.ExtSimAdapter -import edu.ie3.simona.event.RuntimeEvent +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.event.listener.{ DelayedStopHelper, ResultEventListener, @@ -441,7 +441,7 @@ object SimonaSimSpec { override def gridAgents( context: ActorContext[_], environmentRefs: EnvironmentRefs, - resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], + resultEventListeners: Seq[ActorRef[ResultEvent]], ): Iterable[ActorRef[GridAgentMessage]] = Iterable.empty override def extSimulations( diff --git a/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala b/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala index 383c33d0b9..1a933a3bd9 100644 --- a/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/setup/SetupHelperSpec.scala @@ -37,7 +37,7 @@ class SetupHelperSpec "A setup helper" should { val actorRef: ActorRef[GridAgentMessage] = - TestProbe[GridAgentMessage]("noSender").ref + TestProbe[GridAgentMessage]("mock_grid_agent").ref "reduce multiple SubGridGates between the same superior and inferior nodes to one unique SubGridGate" in { diff --git a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala index 190501f8d3..de7cc0e38d 100644 --- a/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala +++ b/src/test/scala/edu/ie3/simona/sim/setup/SimonaSetupSpec.scala @@ -13,8 +13,8 @@ import edu.ie3.datamodel.models.input.connector.{ } import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentMessage -import edu.ie3.simona.event.RuntimeEvent import edu.ie3.simona.event.listener.{ResultEventListener, RuntimeEventListener} +import edu.ie3.simona.event.{ResultEvent, RuntimeEvent} import edu.ie3.simona.ontology.messages.SchedulerMessage import edu.ie3.simona.scheduler.TimeAdvancer import edu.ie3.simona.sim.SimonaSim @@ -77,7 +77,7 @@ class SimonaSetupSpec extends UnitSpec with SimonaSetup with SubGridGateMokka { override def gridAgents( context: ActorContext[_], environmentRefs: EnvironmentRefs, - resultEventListeners: Seq[ActorRef[ResultEventListener.Request]], + resultEventListeners: Seq[ActorRef[ResultEvent]], ): Iterable[ActorRef[GridAgentMessage]] = throw new NotImplementedException("This is a dummy setup") From 8ab90e329134b18e3e534f53719d6d22bf8b03ce Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Tue, 27 Feb 2024 15:52:03 +0100 Subject: [PATCH 100/123] Minor code adaptations --- .../ie3/simona/agent/grid/DBFSAlgorithm.scala | 14 ++---- .../edu/ie3/simona/agent/grid/GridAgent.scala | 6 +-- .../agent/grid/DBFSAlgorithmCenGridSpec.scala | 37 +++++++-------- .../DBFSAlgorithmFailedPowerFlowSpec.scala | 33 ++++++------- .../grid/DBFSAlgorithmParticipantSpec.scala | 46 ++++++++----------- .../agent/grid/DBFSAlgorithmSupGridSpec.scala | 45 ++++++++---------- 6 files changed, 75 insertions(+), 106 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala index cae5528653..18329de0d8 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -80,7 +80,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { )(implicit constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + ): Behavior[GridAgentMessage] = Behaviors.receivePartial { case (ctx, message) => (message, gridAgentData) match { // first part of the grid simulation, same for all gridAgents on all levels @@ -525,7 +525,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { )(implicit constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + ): Behavior[GridAgentMessage] = Behaviors.receivePartial { case (ctx, message) => (message, gridAgentData) match { // main method for power flow calculations @@ -796,9 +796,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // (only possible when first simulation triggered and this agent is faster in this state as the request // by a superior grid arrives) case ( - msg @ WrappedPowerMessage( - _: RequestGridPowerMessage - ), + msg: WrappedPowerMessage, _: GridAgentBaseData, ) => ctx.log.debug( @@ -812,9 +810,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { // (only possible when first simulation triggered and this agent is faster // with its power flow calculation in this state as the request by a superior grid arrives) case ( - msg @ WrappedPowerMessage( - _: RequestGridPowerMessage - ), + msg: WrappedPowerMessage, _: PowerFlowDoneData, ) => ctx.log.debug( @@ -842,7 +838,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { )(implicit constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + ): Behavior[GridAgentMessage] = Behaviors.receivePartial { case (ctx, CheckPowerDifferencesTrigger(currentTick)) => ctx.log.debug("Starting the power differences check ...") diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 6d2cfaaf3b..e1ede433e3 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -72,7 +72,7 @@ object GridAgent extends DBFSAlgorithm { values: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = - Behaviors.receiveMessagePartial[GridAgentMessage] { + Behaviors.receiveMessagePartial { case CreateGridAgent(gridAgentInitData, unlockKey) => values.environmentRefs.scheduler ! ScheduleActivation( values.activationAdapter, @@ -88,7 +88,7 @@ object GridAgent extends DBFSAlgorithm { )(implicit values: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + ): Behavior[GridAgentMessage] = Behaviors.receivePartial { case (ctx, WrappedActivation(Activation(INIT_SIM_TICK))) => // fail fast sanity checks failFast(gridAgentInitData, SimonaActorNaming.actorName(ctx.self)) @@ -200,7 +200,7 @@ object GridAgent extends DBFSAlgorithm { )(implicit values: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], - ): Behavior[GridAgentMessage] = Behaviors.receivePartial[GridAgentMessage] { + ): Behavior[GridAgentMessage] = Behaviors.receivePartial { case (_, msg @ WrappedPowerMessage(_)) => // needs to be set here to handle if the messages arrive too early // before a transition to GridAgentBehaviour took place diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala index 6a715fb7dc..d1715cb356 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala @@ -52,9 +52,9 @@ class DBFSAlgorithmCenGridSpec with DbfsTestGrid with TestSpawnerTyped { - private val scheduler: TestProbe[SchedulerMessage] = - TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") + private val scheduler: TestProbe[SchedulerMessage] = TestProbe("scheduler") + private val runtimeEvents: TestProbe[RuntimeEvent] = + TestProbe("runtimeEvents") private val primaryService = TestProbe("primaryService") private val weatherService = TestProbe("weatherService") @@ -82,8 +82,7 @@ class DBFSAlgorithmCenGridSpec evDataService = None, ) - val resultListener: TestProbe[ResultEvent] = - TestProbe[ResultEvent]("resultListener") + val resultListener: TestProbe[ResultEvent] = TestProbe("resultListener") "A GridAgent actor in center position with async test" should { @@ -119,33 +118,30 @@ class DBFSAlgorithmCenGridSpec RefSystem("2000 MVA", "110 kV"), ) - val key = - ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) - scheduler - .expectMessageType[ScheduleActivation] // lock activation scheduled + val key = ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) + // lock activation scheduled + scheduler.expectMessageType[ScheduleActivation] centerGridAgent ! CreateGridAgent( gridAgentInitData, key, ) - val gridAgentActivation = scheduler.expectMessageType[ScheduleActivation] - gridAgentActivation shouldBe ScheduleActivation( - gridAgentActivation.actor, - INIT_SIM_TICK, - Some(key), - ) + val scheduleActivationMsg = + scheduler.expectMessageType[ScheduleActivation] + scheduleActivationMsg.tick shouldBe INIT_SIM_TICK + scheduleActivationMsg.unlockKey shouldBe Some(key) + val gridAgentActivation = scheduleActivationMsg.actor centerGridAgent ! WrappedActivation(Activation(INIT_SIM_TICK)) - scheduler.expectMessage(Completion(gridAgentActivation.actor, Some(3600))) + scheduler.expectMessage(Completion(gridAgentActivation, Some(3600))) } s"go to SimulateGrid when it receives an activity start trigger" in { centerGridAgent ! WrappedActivation(Activation(3600)) - val completionMessage = scheduler.expectMessageType[Completion] - completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) + scheduler.expectMessageType[Completion].newTick shouldBe Some(3600) } s"start the simulation when activation is sent" in { @@ -449,9 +445,8 @@ class DBFSAlgorithmCenGridSpec inferiorGrid13.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) - // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a CompletionMessage - val completionMessage = scheduler.expectMessageType[Completion] - completionMessage shouldBe Completion(completionMessage.actor, Some(7200)) + // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a Completion + scheduler.expectMessageType[Completion].newTick shouldBe Some(7200) val resultMessage = resultListener.expectMessageType[ResultEvent] resultMessage match { diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala index b198914136..5e24639625 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmFailedPowerFlowSpec.scala @@ -47,9 +47,9 @@ class DBFSAlgorithmFailedPowerFlowSpec with DbfsTestGrid with TestSpawnerTyped { - private val scheduler: TestProbe[SchedulerMessage] = - TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") + private val scheduler: TestProbe[SchedulerMessage] = TestProbe("scheduler") + private val runtimeEvents: TestProbe[RuntimeEvent] = + TestProbe("runtimeEvents") private val primaryService = TestProbe("primaryService") private val weatherService = TestProbe("weatherService") @@ -69,8 +69,7 @@ class DBFSAlgorithmFailedPowerFlowSpec evDataService = None, ) - val resultListener: TestProbe[ResultEvent] = - TestProbe[ResultEvent]("resultListener") + val resultListener: TestProbe[ResultEvent] = TestProbe("resultListener") "A GridAgent actor in center position with async test" should { @@ -105,22 +104,22 @@ class DBFSAlgorithmFailedPowerFlowSpec val key = ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) - scheduler.expectMessageType[SchedulerMessage] // lock activation scheduled + // lock activation scheduled + scheduler.expectMessageType[ScheduleActivation] centerGridAgent ! CreateGridAgent( gridAgentInitData, key, ) - val gridAgentActivation = scheduler.expectMessageType[ScheduleActivation] - gridAgentActivation shouldBe ScheduleActivation( - gridAgentActivation.actor, - INIT_SIM_TICK, - Some(key), - ) + val scheduleActivationMsg = + scheduler.expectMessageType[ScheduleActivation] + scheduleActivationMsg.tick shouldBe INIT_SIM_TICK + scheduleActivationMsg.unlockKey shouldBe Some(key) + val gridAgentActivation = scheduleActivationMsg.actor centerGridAgent ! WrappedActivation(Activation(INIT_SIM_TICK)) - scheduler.expectMessage(Completion(gridAgentActivation.actor, Some(3600))) + scheduler.expectMessage(Completion(gridAgentActivation, Some(3600))) } s"go to SimulateGrid when it receives an activation" in { @@ -129,8 +128,7 @@ class DBFSAlgorithmFailedPowerFlowSpec centerGridAgent ! WrappedActivation(Activation(3600)) // we expect a completion message - val completionMessage = scheduler.expectMessageType[Completion] - completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) + scheduler.expectMessageType[Completion].newTick shouldBe Some(3600) } s"start the simulation when an activation is sent is sent, handle failed power flow if it occurs" in { @@ -211,9 +209,8 @@ class DBFSAlgorithmFailedPowerFlowSpec // should receive a FinishGridSimulationTrigger inferiorGridAgent.gaProbe.expectMessage(FinishGridSimulationTrigger(3600)) - // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a CompletionMessage - val completionMessage = scheduler.expectMessageType[Completion] - completionMessage shouldBe Completion(completionMessage.actor, Some(7200)) + // after all grids have received a FinishGridSimulationTrigger, the scheduler should receive a Completion + scheduler.expectMessageType[Completion].newTick shouldBe Some(7200) resultListener.expectNoMessage() diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala index 0d8afa972e..4bcbe85b42 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmParticipantSpec.scala @@ -50,11 +50,11 @@ class DBFSAlgorithmParticipantSpec with DbfsTestGridWithParticipants with TestSpawnerTyped { - private val scheduler: TestProbe[SchedulerMessage] = - TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") + private val scheduler: TestProbe[SchedulerMessage] = TestProbe("scheduler") + private val runtimeEvents: TestProbe[RuntimeEvent] = + TestProbe("runtimeEvents") private val primaryService: TestProbe[ServiceMessage] = - TestProbe[ServiceMessage]("primaryService") + TestProbe("primaryService") private val weatherService = TestProbe("weatherService") private val environmentRefs = EnvironmentRefs( @@ -66,7 +66,7 @@ class DBFSAlgorithmParticipantSpec ) protected val resultListener: TestProbe[ResultEvent] = - TestProbe[ResultEvent]("resultListener") + TestProbe("resultListener") private val superiorGridAgent = SuperiorGA( TestProbe("superiorGridAgent_1000"), @@ -104,28 +104,20 @@ class DBFSAlgorithmParticipantSpec gridAgentWithParticipants ! CreateGridAgent(gridAgentInitData, key) - val msg = scheduler.expectMessageType[ScheduleActivation] - msg shouldBe ScheduleActivation(msg.actor, INIT_SIM_TICK, Some(key)) + val scheduleActivationMsg = + scheduler.expectMessageType[ScheduleActivation] + scheduleActivationMsg.tick shouldBe INIT_SIM_TICK + scheduleActivationMsg.unlockKey shouldBe Some(key) + val gridAgentActivation = scheduleActivationMsg.actor - // send init data to agent and expect a CompletionMessage + // send init data to agent and expect a Completion gridAgentWithParticipants ! WrappedActivation(Activation(INIT_SIM_TICK)) - val message = scheduler.expectMessageType[ScheduleActivation] + val scheduleLoadAgentMsg = scheduler.expectMessageType[ScheduleActivation] + scheduleLoadAgentMsg.tick shouldBe INIT_SIM_TICK + val loadAgent = scheduleLoadAgentMsg.actor - val loadAgent: ActorRef[Activation] = message match { - case ScheduleActivation( - loadAgent, - INIT_SIM_TICK, - _, - ) => - loadAgent - - case other => - fail(s"$other was not expected") - } - - val completionMessage = scheduler.expectMessageType[Completion] - completionMessage shouldBe Completion(completionMessage.actor, Some(3600)) + scheduler.expectMessage(Completion(gridAgentActivation, Some(3600))) loadAgent ! Activation(INIT_SIM_TICK) @@ -142,7 +134,7 @@ class DBFSAlgorithmParticipantSpec // triggering the loadAgent's calculation loadAgent ! Activation(0) - // the load agent should send a CompletionMessage + // the load agent should send a Completion scheduler.expectMessage(Completion(loadAgent, None)) } @@ -153,8 +145,7 @@ class DBFSAlgorithmParticipantSpec gridAgentWithParticipants ! WrappedActivation(Activation(3600)) // we expect a completion message - val message = scheduler.expectMessageType[Completion] - message shouldBe Completion(message.actor, Some(3600)) + scheduler.expectMessageType[Completion].newTick shouldBe Some(3600) } s"check the request asset power message indirectly" in { @@ -244,8 +235,7 @@ class DBFSAlgorithmParticipantSpec // (here we do it by hand) gridAgentWithParticipants ! FinishGridSimulationTrigger(3600L) - val message = scheduler.expectMessageType[Completion] - message shouldBe Completion(message.actor, Some(7200)) + scheduler.expectMessageType[Completion].newTick shouldBe Some(7200) } } } diff --git a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala index 57e6c1f507..1c2907a411 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmSupGridSpec.scala @@ -59,14 +59,13 @@ class DBFSAlgorithmSupGridSpec with DbfsTestGrid with TestSpawnerTyped { - private val scheduler: TestProbe[SchedulerMessage] = - TestProbe[SchedulerMessage]("scheduler") - private val runtimeEvents = TestProbe[RuntimeEvent]("runtimeEvents") + private val scheduler: TestProbe[SchedulerMessage] = TestProbe("scheduler") + private val runtimeEvents: TestProbe[RuntimeEvent] = + TestProbe("runtimeEvents") private val primaryService: TestProbe[ServiceMessage] = - TestProbe[ServiceMessage]("primaryService") + TestProbe("primaryService") private val weatherService = TestProbe("weatherService") - private val hvGrid: TestProbe[GridAgentMessage] = - TestProbe[GridAgentMessage]("hvGrid") + private val hvGrid: TestProbe[GridAgentMessage] = TestProbe("hvGrid") private val environmentRefs = EnvironmentRefs( scheduler = scheduler.ref, @@ -76,8 +75,7 @@ class DBFSAlgorithmSupGridSpec evDataService = None, ) - val resultListener: TestProbe[ResultEvent] = - TestProbe[ResultEvent]("resultListener") + val resultListener: TestProbe[ResultEvent] = TestProbe("resultListener") "A GridAgent actor in superior position with async test" should { val superiorGridAgentFSM: ActorRef[GridAgentMessage] = testKit.spawn( @@ -102,18 +100,19 @@ class DBFSAlgorithmSupGridSpec val key = ScheduleLock.singleKey(TSpawner, scheduler.ref, INIT_SIM_TICK) - scheduler - .expectMessageType[ScheduleActivation] // lock activation scheduled + // lock activation scheduled + scheduler.expectMessageType[ScheduleActivation] superiorGridAgentFSM ! CreateGridAgent(gridAgentInitData, key) - val am = scheduler.expectMessageType[ScheduleActivation] - am shouldBe ScheduleActivation(am.actor, INIT_SIM_TICK, Some(key)) + val scheduleActivationMsg = + scheduler.expectMessageType[ScheduleActivation] + scheduleActivationMsg.tick shouldBe INIT_SIM_TICK + scheduleActivationMsg.unlockKey shouldBe Some(key) + val gridAgentActivation = scheduleActivationMsg.actor superiorGridAgentFSM ! WrappedActivation(Activation(INIT_SIM_TICK)) - - val cm = scheduler.expectMessageType[Completion] - cm shouldBe Completion(cm.actor, Some(3600)) + scheduler.expectMessage(Completion(gridAgentActivation, Some(3600))) } s"go to SimulateGrid when it receives an activity start trigger" in { @@ -121,8 +120,7 @@ class DBFSAlgorithmSupGridSpec superiorGridAgentFSM ! WrappedActivation(Activation(3600)) // we expect a completion message - val message = scheduler.expectMessageType[Completion] - message shouldBe Completion(message.actor, Some(3600)) + scheduler.expectMessageType[Completion].newTick shouldBe Some(3600) } s"start the simulation, do 2 sweeps and should end afterwards when no deviation on nodal " + @@ -171,10 +169,7 @@ class DBFSAlgorithmSupGridSpec // we expect a completion message here and that the agent goes back to simulate grid // and waits until the newly scheduled StartGridSimulationTrigger is send // wait 30 seconds max for power flow to finish - val completionMessage = - scheduler.expectMessageType[Completion](130 seconds) - - completionMessage match { + scheduler.expectMessageType[Completion](130 seconds) match { case Completion(_, Some(3600)) => // we expect another completion message when the agent is in SimulateGrid again case Completion(_, Some(7200)) => @@ -249,8 +244,7 @@ class DBFSAlgorithmSupGridSpec superiorGridAgentFSM ! WrappedActivation(Activation(3600)) // we expect a completion message - val message = scheduler.expectMessageType[Completion] - message shouldBe Completion(message.actor, Some(3600)) + scheduler.expectMessageType[Completion].newTick shouldBe Some(3600) // go on with testing the sweep behaviour for (sweepNo <- 0 to maxNumberOfTestSweeps) { @@ -298,10 +292,7 @@ class DBFSAlgorithmSupGridSpec // Simulate Grid // wait 30 seconds max for power flow to finish - val completionMessage = - scheduler.expectMessageType[Completion](30 seconds) - - completionMessage match { + scheduler.expectMessageType[Completion](30 seconds) match { case Completion(_, Some(3600)) => // when we received a FinishGridSimulationTrigger (as inferior grid agent) // we expect another completion message then as well (scheduler view) From 6cd336a5fa8c451e6e54a237618535d14979a859 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 27 Feb 2024 17:28:40 +0100 Subject: [PATCH 101/123] Implementing requested changes. --- .../ie3/simona/agent/grid/DBFSAlgorithm.scala | 23 ++++---- .../edu/ie3/simona/agent/grid/GridAgent.scala | 53 +++++++++---------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala index 18329de0d8..f47f3ef8b8 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -978,8 +978,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { failedResult.cause, ) ctx.self ! FinishGridSimulationTrigger(currentTick) - handlePowerFlowFailure(gridAgentBaseData)(ctx, constantData) - simulateGrid(gridAgentBaseData, currentTick) + handlePowerFlowFailure(gridAgentBaseData, currentTick, ctx) } } @@ -1100,8 +1099,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ctx.log.warn("Power flow failed! This incident will be reported!") ctx.self ! FinishGridSimulationTrigger(currentTick) - handlePowerFlowFailure(gridAgentBaseData) - simulateGrid(gridAgentBaseData, currentTick) + handlePowerFlowFailure(gridAgentBaseData, currentTick, ctx) } else { ctx.self ! CheckPowerDifferencesTrigger(currentTick) checkPowerDifferences(gridAgentBaseData) @@ -1117,18 +1115,25 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { /** Method for handling failed power flows. * @param gridAgentBaseData * state data of the actor + * @param currentTick + * of the simulation */ private def handlePowerFlowFailure( - gridAgentBaseData: GridAgentBaseData - )(implicit + gridAgentBaseData: GridAgentBaseData, + currentTick: Long, ctx: ActorContext[GridAgentMessage], + )(implicit constantData: GridAgentConstantData, - ): Unit = { + buffer: StashBuffer[GridAgentMessage], + ): Behavior[GridAgentMessage] = { constantData.environmentRefs.runtimeEventListener ! PowerFlowFailed if (gridAgentBaseData.powerFlowParams.stopOnFailure) { ctx.log.error("Stopping because of failed power flow.") + Behaviors.stopped } + + simulateGrid(gridAgentBaseData, currentTick) } /** Normally only reached by the superior (dummy) agent! @@ -1414,9 +1419,9 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { * itself. If the future is a [[Success]] the message is send, else a * [[ReceivedFailure]] with the thrown error is send. * @param future - * value + * future message that should be send to the agent after it was processed * @param ctx - * context + * [[ActorContext]] of the receiving actor */ private def pipeToSelf( future: Future[GridAgentMessage], diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index e1ede433e3..3b8fce03d3 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -26,7 +26,6 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{ } import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.TimeUtil -import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorContextOps import org.apache.pekko.actor.typed.scaladsl.{Behaviors, StashBuffer} import org.apache.pekko.actor.typed.{ActorRef, Behavior} @@ -69,13 +68,13 @@ object GridAgent extends DBFSAlgorithm { } private def uninitialized(implicit - values: GridAgentConstantData, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = Behaviors.receiveMessagePartial { case CreateGridAgent(gridAgentInitData, unlockKey) => - values.environmentRefs.scheduler ! ScheduleActivation( - values.activationAdapter, + constantData.environmentRefs.scheduler ! ScheduleActivation( + constantData.activationAdapter, INIT_SIM_TICK, Some(unlockKey), ) @@ -86,7 +85,7 @@ object GridAgent extends DBFSAlgorithm { private def initializing( gridAgentInitData: GridAgentInitData )(implicit - values: GridAgentConstantData, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = Behaviors.receivePartial { case (ctx, WrappedActivation(Activation(INIT_SIM_TICK))) => @@ -120,24 +119,24 @@ object GridAgent extends DBFSAlgorithm { subGridContainer, refSystem, TimeUtil.withDefaults.toZonedDateTime( - values.simonaConfig.simona.time.startDateTime + constantData.simonaConfig.simona.time.startDateTime ), TimeUtil.withDefaults.toZonedDateTime( - values.simonaConfig.simona.time.endDateTime + constantData.simonaConfig.simona.time.endDateTime ), ) val gridAgentController = new GridAgentController( ctx, - values.environmentRefs, - values.simStartTime, + constantData.environmentRefs, + constantData.simStartTime, TimeUtil.withDefaults - .toZonedDateTime(values.simonaConfig.simona.time.endDateTime), - values.simonaConfig.simona.runtime.participant, - values.simonaConfig.simona.output.participant, - values.resolution, - values.listener, + .toZonedDateTime(constantData.simonaConfig.simona.time.endDateTime), + constantData.simonaConfig.simona.runtime.participant, + constantData.simonaConfig.simona.output.participant, + constantData.resolution, + constantData.listener, ctx.log, ) @@ -165,20 +164,20 @@ object GridAgent extends DBFSAlgorithm { gridAgentInitData.superiorGridNodeUuids, gridAgentInitData.inferiorGridGates, PowerFlowParams( - values.simonaConfig.simona.powerflow.maxSweepPowerDeviation, - values.simonaConfig.simona.powerflow.newtonraphson.epsilon.toVector.sorted, - values.simonaConfig.simona.powerflow.newtonraphson.iterations, - values.simonaConfig.simona.powerflow.sweepTimeout, - values.simonaConfig.simona.powerflow.stopOnFailure, + constantData.simonaConfig.simona.powerflow.maxSweepPowerDeviation, + constantData.simonaConfig.simona.powerflow.newtonraphson.epsilon.toVector.sorted, + constantData.simonaConfig.simona.powerflow.newtonraphson.iterations, + constantData.simonaConfig.simona.powerflow.sweepTimeout, + constantData.simonaConfig.simona.powerflow.stopOnFailure, ), SimonaActorNaming.actorName(ctx.self), ) ctx.log.debug("Je suis initialized") - values.environmentRefs.scheduler ! Completion( - values.activationAdapter, - Some(values.resolution), + constantData.environmentRefs.scheduler ! Completion( + constantData.activationAdapter, + Some(constantData.resolution), ) idle(gridAgentBaseData) @@ -188,7 +187,7 @@ object GridAgent extends DBFSAlgorithm { * * @param gridAgentBaseData * state data of the actor - * @param values + * @param constantData * immutable [[GridAgent]] values * @param buffer * for [[GridAgentMessage]]s @@ -198,18 +197,18 @@ object GridAgent extends DBFSAlgorithm { private[grid] def idle( gridAgentBaseData: GridAgentBaseData )(implicit - values: GridAgentConstantData, + constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], ): Behavior[GridAgentMessage] = Behaviors.receivePartial { - case (_, msg @ WrappedPowerMessage(_)) => + case (_, msg: WrappedPowerMessage) => // needs to be set here to handle if the messages arrive too early // before a transition to GridAgentBehaviour took place buffer.stash(msg) Behaviors.same case (_, WrappedActivation(activation: Activation)) => - values.environmentRefs.scheduler ! Completion( - values.activationAdapter, + constantData.environmentRefs.scheduler ! Completion( + constantData.activationAdapter, Some(activation.tick), ) buffer.unstashAll(simulateGrid(gridAgentBaseData, activation.tick)) From d9f233a878298ab38b92d22950cca65f35a7d4ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Feb 2024 07:15:35 +0000 Subject: [PATCH 102/123] Bump com.sksamuel.scapegoat:scalac-scapegoat-plugin_2.13.12 (#755) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8b36a3241e..c906d29af3 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ ext { jtsVersion = '1.19.0' confluentKafkaVersion = '7.4.0' tscfgVersion = '1.0.0' - scapegoatVersion = '2.1.4' + scapegoatVersion = '2.1.5' testContainerVersion = '0.41.3' From 0dffae93632e4d78dc47e3ac4d3123b26b19d5ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Feb 2024 07:16:08 +0000 Subject: [PATCH 103/123] Bump org.scala-lang:scala-library from 2.13.12 to 2.13.13 Bumps [org.scala-lang:scala-library](https://github.com/scala/scala) from 2.13.12 to 2.13.13. - [Release notes](https://github.com/scala/scala/releases) - [Commits](https://github.com/scala/scala/compare/v2.13.12...v2.13.13) --- updated-dependencies: - dependency-name: org.scala-lang:scala-library dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c906d29af3..947731e542 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ ext { javaVersion = JavaVersion.VERSION_17 scalaVersion = '2.13' - scalaBinaryVersion = '2.13.12' + scalaBinaryVersion = '2.13.13' pekkoVersion = '1.0.2' jtsVersion = '1.19.0' confluentKafkaVersion = '7.4.0' From 136ab1072762bcc6852248c1fbc387a213468d3d Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 10:20:32 +0100 Subject: [PATCH 104/123] Bumping scoverage version to 2.1.0 --- gradle/scripts/scoverage.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/scripts/scoverage.gradle b/gradle/scripts/scoverage.gradle index 0a2e0157e8..e8ac99cf1f 100644 --- a/gradle/scripts/scoverage.gradle +++ b/gradle/scripts/scoverage.gradle @@ -3,7 +3,7 @@ // https://github.com/scoverage/gradle-scoverage/issues/109 for details scoverage { - scoverageVersion = "2.0.11" + scoverageVersion = "2.1.0" scoverageScalaVersion = scalaBinaryVersion coverageOutputHTML = false coverageOutputXML = true From 7a0f35407f665e767d04e5700f8d4c03d1809ec9 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Feb 2024 13:51:37 +0100 Subject: [PATCH 105/123] enhance scaladoc --- .../TransformerControlGroupModel.scala | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index 737ea0217f..49c2d73761 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -144,6 +144,19 @@ object TransformerControlGroupModel { .map(_.getNode.getUuid) ) + /** Determine the regulation criterion of the nodes to control + * + * @param complexVoltage + * Collection of all known [[MeasurementUnitInput]] s + * @param vMax + * and + * @param vMin + * Voltage limits of the node + * @return + * The RegulationCriterion in this case a set of node uuids and optional + * voltage deviation + */ + private def regulationFunction( complexVoltage: Complex, vMax: Double, @@ -159,6 +172,15 @@ object TransformerControlGroupModel { } } + /** Function to harmonize contrary requests for regulation + * + * @param regulationRequests: + * Array of all regulation requests + * @return + * None in case of contrary requests, else the highest or lowest voltage + * depending of the direction for regulation + */ + private def harmonizationFunction : Array[Dimensionless] => Option[Dimensionless] = (regulationRequests: Array[Dimensionless]) => { From ee1479a5d681cedafe759d3ed278718ad5d4fb56 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Feb 2024 13:52:11 +0100 Subject: [PATCH 106/123] fix TransformerControlGroupModel and include reviewers feedback --- .../TransformerControlGroupModel.scala | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index 49c2d73761..a8045e5264 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -12,7 +12,10 @@ import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup -import edu.ie3.simona.model.control.TransformerControlGroupModel.RegulationCriterion +import edu.ie3.simona.model.control.TransformerControlGroupModel.{ + RegulationCriterion, + harmonizationFunction, +} import squants.{Dimensionless, Each} import java.util.UUID @@ -25,13 +28,9 @@ import scala.jdk.CollectionConverters._ * @param nodalRegulationCriterion * Mapping from nodal index to a partial function, that determines the * regulation need at this node - * @param harmonizeRegulationNeeds - * Partial function to harmonize different, possible contradictory regulation - * needs */ final case class TransformerControlGroupModel( - nodalRegulationCriterion: Map[UUID, RegulationCriterion], - harmonizeRegulationNeeds: Array[Dimensionless] => Option[Dimensionless], + nodalRegulationCriterion: Map[UUID, RegulationCriterion] ) { /** Based on the given successful power flow result, determine the difference @@ -64,7 +63,7 @@ final case class TransformerControlGroupModel( }.flatten Option .when(regulationNeeds.nonEmpty)( - harmonizeRegulationNeeds(regulationNeeds) + harmonizationFunction(regulationNeeds) ) .flatten } @@ -161,14 +160,16 @@ object TransformerControlGroupModel { complexVoltage: Complex, vMax: Double, vMin: Double, - ): Option[Dimensionless] = { - val vMag = complexVoltage.abs - vMag match { - case mag if mag > vMax => - Some(vMax - mag).map(Each(_)) - case mag if mag < vMin => - Some(vMin - mag).map(Each(_)) - case _ => None + ): RegulationCriterion = { (voltage: Complex) => + { + val vMag = voltage.abs + vMag match { + case mag if mag > vMax => + Some(vMax - mag).map(Each(_)) + case mag if mag < vMin => + Some(vMin - mag).map(Each(_)) + case _ => None + } } } @@ -228,8 +229,7 @@ object TransformerControlGroupModel { }.toMap TransformerControlGroupModel( - nodeUuidToRegulationCriterion, - harmonizationFunction, + nodeUuidToRegulationCriterion ) } } From 5fb97ff676d51988e675aa2b3f2655a12452976f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Feb 2024 13:52:35 +0100 Subject: [PATCH 107/123] include simonaConfig into GridAgent --- .../scala/edu/ie3/simona/agent/grid/GridAgent.scala | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 5bb2fd5b7a..8cd2a6b1f6 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -63,13 +63,14 @@ object GridAgent extends DBFSAlgorithm { activationAdapter, ) - uninitialized(agentValues, buffer) + uninitialized(agentValues, buffer, simonaConfig) } } private def uninitialized(implicit constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], + simonaConfig: SimonaConfig, ): Behavior[GridAgentMessage] = Behaviors.receiveMessagePartial { case CreateGridAgent(gridAgentInitData, unlockKey) => @@ -78,12 +79,12 @@ object GridAgent extends DBFSAlgorithm { INIT_SIM_TICK, Some(unlockKey), ) - - initializing(gridAgentInitData) + initializing(gridAgentInitData, simonaConfig) } private def initializing( - gridAgentInitData: GridAgentInitData + gridAgentInitData: GridAgentInitData, + simonaConfig: SimonaConfig, )(implicit constantData: GridAgentConstantData, buffer: StashBuffer[GridAgentMessage], @@ -124,6 +125,7 @@ object GridAgent extends DBFSAlgorithm { TimeUtil.withDefaults.toZonedDateTime( constantData.simonaConfig.simona.time.endDateTime ), + simonaConfig, ) val gridAgentController = @@ -138,8 +140,7 @@ object GridAgent extends DBFSAlgorithm { constantData.resolution, constantData.listener, ctx.log, - simonaConfig, - ) + ) /* Reassure, that there are also calculation models for the given uuids */ val nodeToAssetAgentsMap: Map[UUID, Set[ActorRef[ParticipantMessage]]] = From 502f3755566329421a6f999969308cd525e7e45e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Feb 2024 13:53:47 +0100 Subject: [PATCH 108/123] include simonaConfig into tests --- .../edu/ie3/simona/model/grid/TransformerModelSpec.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala index d88624026e..880ca12116 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/TransformerModelSpec.scala @@ -18,7 +18,7 @@ import edu.ie3.powerflow.model.NodeData.{PresetData, StateData} import edu.ie3.powerflow.model.StartData.WithForcedStartVoltages import edu.ie3.powerflow.model.enums.NodeType import edu.ie3.powerflow.model.{NodeData, PowerFlowResult} -import edu.ie3.simona.test.common.UnitSpec +import edu.ie3.simona.test.common.{ConfigTestData, UnitSpec} import edu.ie3.simona.test.common.model.grid.{ TapTestData, TransformerTestData, @@ -36,7 +36,10 @@ import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.UUID -class TransformerModelSpec extends UnitSpec with TableDrivenPropertyChecks { +class TransformerModelSpec + extends UnitSpec + with TableDrivenPropertyChecks + with ConfigTestData { val quantityTolerance: Double = 1e-5 val testingTolerancePf = 1e-9 implicit val electricCurrentTolerance: squants.electro.ElectricCurrent = @@ -378,7 +381,7 @@ class TransformerModelSpec extends UnitSpec with TableDrivenPropertyChecks { refSystem, defaultSimulationStart, defaultSimulationEnd, - controlConfig = None, + simonaConfig, ) gridModel.gridComponents.transformers From 9076e3403daf74aa50fbfcb745f56859355239f5 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Feb 2024 14:47:09 +0100 Subject: [PATCH 109/123] fix TransformerControlGroupModelSpec --- .../TransformerControlGroupModelSpec.scala | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala index 2ea7876057..c0c47d92cd 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala @@ -26,21 +26,22 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { Symbol("buildTransformerControlModels") ) implicit val tolerance: Dimensionless = Each(1e-10) - val dut = GridModel invokePrivate buildTransformerControlModels( - Set( - UUID.fromString( - "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" + val dut = + TransformerControlGroupModel invokePrivate buildTransformerControlModels( + Set( + UUID.fromString( + "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" + ), + UUID.fromString( + "08b8d2ca-993d-45cd-9456-f009ecb47bc0" + ), + UUID.fromString( + "324f49e5-1c35-4c49-afb1-3cf41696bf93" + ), ), - UUID.fromString( - "08b8d2ca-993d-45cd-9456-f009ecb47bc0" - ), - UUID.fromString( - "324f49e5-1c35-4c49-afb1-3cf41696bf93" - ), - ), - 1.1, - 0.9, - ) + 1.1, + 0.9, + ) val uuidToIndex = Map( UUID.fromString( From 7fce4a4a81964cc65a7dbde207745cc5b4c1bf7c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Feb 2024 14:55:00 +0100 Subject: [PATCH 110/123] fix GridSpec --- src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 49ada4cf9e..1e49031a52 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -546,7 +546,7 @@ class GridSpec ) val expectedUuids = Set(node1, node2).map(_.getUuid) - val actual = GridModel invokePrivate determineNodeUuids( + val actual = TransformerControlGroupModel invokePrivate determineNodeUuids( measurementUnits, selectedMeasurements, ) From d641373cda86e1065f3a8c3798b83cb00462f9d3 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Feb 2024 14:57:38 +0100 Subject: [PATCH 111/123] fmt --- src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 1e49031a52..5311e5238a 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -546,10 +546,11 @@ class GridSpec ) val expectedUuids = Set(node1, node2).map(_.getUuid) - val actual = TransformerControlGroupModel invokePrivate determineNodeUuids( - measurementUnits, - selectedMeasurements, - ) + val actual = + TransformerControlGroupModel invokePrivate determineNodeUuids( + measurementUnits, + selectedMeasurements, + ) actual should contain theSameElementsAs expectedUuids } } From a9ece9837725a428c78b031bd6b4fe1696f9ec84 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 15:40:42 +0100 Subject: [PATCH 112/123] Language error message --- src/main/scala/edu/ie3/simona/model/grid/GridModel.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index da108c62e9..438de62f55 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -498,12 +498,12 @@ object GridModel { val measurementUnit = measurementUnits.getOrElse( measurement, throw new GridAgentInitializationException( - s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which UUID does not exist in this subnet." + s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement unit whose UUID does not exist in this subnet." ), ) if (!measurementUnit.getVMag) throw new GridAgentInitializationException( - s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement which does not measure voltage magnitude." + s"${subGridContainer.getGridName} has a transformer control group (${control.transformer.toString}) with a measurement unit which does not measure voltage magnitude." ) } } From 75025707010945a11e253a20d685ae2fd5b1b228 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 15:56:13 +0100 Subject: [PATCH 113/123] Shortened syntax --- .../simona/model/control/GridControls.scala | 4 +- .../edu/ie3/simona/model/grid/GridModel.scala | 71 ++++++++----------- .../edu/ie3/simona/model/grid/GridSpec.scala | 10 +-- .../model/grid/BasicGridWithSwitches.scala | 2 +- 4 files changed, 37 insertions(+), 50 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/GridControls.scala b/src/main/scala/edu/ie3/simona/model/control/GridControls.scala index 2afa0f283d..b2d00cba17 100644 --- a/src/main/scala/edu/ie3/simona/model/control/GridControls.scala +++ b/src/main/scala/edu/ie3/simona/model/control/GridControls.scala @@ -19,7 +19,5 @@ object GridControls { /** Represents an empty GridControls group */ - def emptyGridControls: GridControls = GridControls( - Set.empty[TransformerControlGroupModel] - ) + def empty: GridControls = GridControls(Set.empty) } diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 438de62f55..e2f093a471 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -11,7 +11,6 @@ import breeze.math.Complex import edu.ie3.datamodel.exceptions.InvalidGridException import edu.ie3.datamodel.models.input.connector._ import edu.ie3.datamodel.models.input.container.SubGridContainer -import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.GridInconsistencyException import edu.ie3.simona.exceptions.agent.GridAgentInitializationException @@ -465,28 +464,27 @@ object GridModel { * @param maybeControlConfig * Config of ControlGroup */ - private def checkControlGroupsForMeasurement( + private def validateControlGroups( subGridContainer: SubGridContainer, maybeControlConfig: Option[SimonaConfig.Simona.Control], ): Unit = { - - val measurementUnits = - subGridContainer.getRawGrid.getMeasurementUnits.asScala - .map(measurement => measurement.getUuid -> measurement) - .toMap - - val transformerUnits2W = - subGridContainer.getRawGrid.getTransformer2Ws.asScala - .map(transformer2w => transformer2w.getUuid -> transformer2w) - .toMap - - val transformerUnits3W = - subGridContainer.getRawGrid.getTransformer3Ws.asScala - .map(transformer3w => transformer3w.getUuid -> transformer3w) - .toMap - - maybeControlConfig.foreach(control => - control.transformer.foreach(controlGroup => + maybeControlConfig.foreach { control => + val measurementUnits = + subGridContainer.getRawGrid.getMeasurementUnits.asScala + .map(measurement => measurement.getUuid -> measurement) + .toMap + + val transformerUnits2W = + subGridContainer.getRawGrid.getTransformer2Ws.asScala + .map(transformer2w => transformer2w.getUuid -> transformer2w) + .toMap + + val transformerUnits3W = + subGridContainer.getRawGrid.getTransformer3Ws.asScala + .map(transformer3w => transformer3w.getUuid -> transformer3w) + .toMap + + control.transformer.foreach { controlGroup => controlGroup.transformers.map(UUID.fromString).foreach { transformer => val transformerUnit2W = transformerUnits2W.get(transformer) val transformerUnit3W = transformerUnits3W.get(transformer) @@ -507,9 +505,10 @@ object GridModel { ) } } + } - ) - ) + } + } } private def buildAndValidate( @@ -602,31 +601,21 @@ object GridModel { ) /* Build transformer control groups */ - val maybeControlConfig: Option[SimonaConfig.Simona.Control] = - simonaConfig.simona.control match { - case Some(control) => simonaConfig.simona.control - case None => None - } - - val transformerControlGroups = maybeControlConfig + val transformerControlGroups = simonaConfig.simona.control .map { controlConfig => TransformerControlGroupModel.buildControlGroups( controlConfig.transformer, subGridContainer.getRawGrid.getMeasurementUnits, ) } - .getOrElse(Set.empty[TransformerControlGroupModel]) + .getOrElse(Set.empty) - /* Build grid related control strategies */ - val gridControls = GridControls(transformerControlGroups) - - val gridModel = - GridModel( - subGridContainer.getSubnet, - refSystem, - gridComponents, - gridControls, - ) + val gridModel = GridModel( + subGridContainer.getSubnet, + refSystem, + gridComponents, + GridControls(transformerControlGroups), + ) /** Check and validates the grid. Especially the consistency of the grid * model the connectivity of the grid model if there is InitData for @@ -637,7 +626,7 @@ object GridModel { // validate validateConsistency(gridModel) validateConnectivity(gridModel) - checkControlGroupsForMeasurement( + validateControlGroups( subGridContainer, simonaConfig.simona.control, ) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 5311e5238a..1fa4122da3 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -217,7 +217,7 @@ class GridSpec Set.empty[Transformer3wModel], switches, ), - GridControls(Set.empty[TransformerControlGroupModel]), + GridControls.empty, ) // get the private method for validation val validateConnectivity: PrivateMethod[Unit] = @@ -246,7 +246,7 @@ class GridSpec Set.empty[Transformer3wModel], Set.empty[SwitchModel], ), - GridControls(Set.empty[TransformerControlGroupModel]), + GridControls.empty, ) // get the private method for validation @@ -292,7 +292,7 @@ class GridSpec Set.empty[Transformer3wModel], switches, ), - GridControls.emptyGridControls, + GridControls.empty, ) // get the private method for validation @@ -397,7 +397,7 @@ class GridSpec Set.empty[Transformer3wModel], switches, ), - GridControls(Set.empty[TransformerControlGroupModel]), + GridControls.empty, ) // update the uuidToIndexMap @@ -449,7 +449,7 @@ class GridSpec Set.empty[Transformer3wModel], Set.empty[SwitchModel], ), - GridControls(Set.empty[TransformerControlGroupModel]), + GridControls.empty, ) // update the uuidToIndexMap diff --git a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala index d57d902bc1..bd709daa01 100644 --- a/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala +++ b/src/test/scala/edu/ie3/simona/test/common/model/grid/BasicGridWithSwitches.scala @@ -231,7 +231,7 @@ trait BasicGridWithSwitches extends BasicGrid { Set.empty[Transformer3wModel], gridSwitches, ), - GridControls.emptyGridControls, + GridControls.empty, ) } From b7c6a6f372877308d125723da7d1cc97e4bf4a5d Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 16:36:15 +0100 Subject: [PATCH 114/123] More syntax changes --- .../TransformerControlGroupModel.scala | 69 +++++++++---------- .../edu/ie3/simona/model/grid/GridModel.scala | 2 +- .../simona/config/ConfigFailFastSpec.scala | 4 +- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index a8045e5264..2e277561e2 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -14,12 +14,11 @@ import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.config.SimonaConfig.TransformerControlGroup import edu.ie3.simona.model.control.TransformerControlGroupModel.{ RegulationCriterion, - harmonizationFunction, + harmonizeRegulationNeeds, } import squants.{Dimensionless, Each} import java.util.UUID -import scala.jdk.CollectionConverters._ /** Business logic for a transformer control group. It's main purpose is to * determine, if there is any regulation need and if yes, to what extent (here: @@ -63,7 +62,7 @@ final case class TransformerControlGroupModel( }.flatten Option .when(regulationNeeds.nonEmpty)( - harmonizationFunction(regulationNeeds) + harmonizeRegulationNeeds(regulationNeeds) ) .flatten } @@ -84,7 +83,7 @@ object TransformerControlGroupModel { */ def buildControlGroups( config: List[SimonaConfig.TransformerControlGroup], - measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementUnitInput: Set[MeasurementUnitInput], ): Set[TransformerControlGroupModel] = config.map { case TransformerControlGroup(measurements, _, vMax, vMin) => buildTransformerControlGroupModel( @@ -112,7 +111,7 @@ object TransformerControlGroupModel { * A [[TransformerControlGroupModel]] */ private def buildTransformerControlGroupModel( - measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementUnitInput: Set[MeasurementUnitInput], measurementConfigs: Set[String], vMax: Double, vMin: Double, @@ -133,10 +132,10 @@ object TransformerControlGroupModel { * A set of relevant nodal uuids */ private def determineNodeUuids( - measurementUnitInput: java.util.Set[MeasurementUnitInput], + measurementUnitInput: Set[MeasurementUnitInput], measurementConfigs: Set[String], ): Set[UUID] = Set.from( - measurementUnitInput.asScala + measurementUnitInput .filter(input => measurementConfigs.contains(input.getUuid.toString) && input.getVMag ) @@ -161,15 +160,12 @@ object TransformerControlGroupModel { vMax: Double, vMin: Double, ): RegulationCriterion = { (voltage: Complex) => - { - val vMag = voltage.abs - vMag match { - case mag if mag > vMax => - Some(vMax - mag).map(Each(_)) - case mag if mag < vMin => - Some(vMin - mag).map(Each(_)) - case _ => None - } + voltage.abs match { + case vMag if vMag > vMax => + Some(vMax - vMag).map(Each(_)) + case vMag if vMag < vMin => + Some(vMin - vMag).map(Each(_)) + case _ => None } } @@ -181,29 +177,28 @@ object TransformerControlGroupModel { * None in case of contrary requests, else the highest or lowest voltage * depending of the direction for regulation */ - - private def harmonizationFunction - : Array[Dimensionless] => Option[Dimensionless] = - (regulationRequests: Array[Dimensionless]) => { - val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) - val positiveRequests = regulationRequests.filter(_ > Each(0d)) - - (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { - case (true, true) => - /* There are requests for higher and lower voltages at the same time => do nothing! */ - None - case (true, false) => - /* There are only requests for lower voltages => decide for the lowest required voltage */ - negativeRequests.minOption - case (false, true) => - /* There are only requests for higher voltages => decide for the highest required voltage */ - positiveRequests.maxOption - case _ => - None - } - + private def harmonizeRegulationNeeds( + regulationRequests: Array[Dimensionless] + ): Option[Dimensionless] = { + val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) + val positiveRequests = regulationRequests.filter(_ > Each(0d)) + + (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { + case (true, true) => + /* There are requests for higher and lower voltages at the same time => do nothing! */ + None + case (true, false) => + /* There are only requests for lower voltages => decide for the lowest required voltage */ + negativeRequests.minOption + case (false, true) => + /* There are only requests for higher voltages => decide for the highest required voltage */ + positiveRequests.maxOption + case _ => + None } + } + /** Build a single control group model. Currently, only limit violation * prevention logic is captured: The nodal regulation need is equal to the * voltage change needed to comply with the given thresholds diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index e2f093a471..1eec288b80 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -605,7 +605,7 @@ object GridModel { .map { controlConfig => TransformerControlGroupModel.buildControlGroups( controlConfig.transformer, - subGridContainer.getRawGrid.getMeasurementUnits, + subGridContainer.getRawGrid.getMeasurementUnits.asScala.toSet, ) } .getOrElse(Set.empty) diff --git a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala index 515bba93bc..3b587fac30 100644 --- a/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala +++ b/src/test/scala/edu/ie3/simona/config/ConfigFailFastSpec.scala @@ -961,7 +961,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { "throw an exception, if the measurements are empty" in { val dut = TransformerControlGroup( - List.empty[String], + List.empty, List("a16cf7ca-8bbf-46e1-a74e-ffa6513c89a8"), 1.02, 0.98, @@ -975,7 +975,7 @@ class ConfigFailFastSpec extends UnitSpec with ConfigTestData { "throw an exception, if the transformers are empty" in { val dut = TransformerControlGroup( List("6888c53a-7629-4563-ac8e-840f80b03106"), - List.empty[String], + List.empty, 1.02, 0.98, ) From c74bad66d56171dc93c07a18f639e15af07ffea0 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 16:47:05 +0100 Subject: [PATCH 115/123] Unnecessary parameter --- .../control/TransformerControlGroupModel.scala | 14 ++++---------- .../control/TransformerControlGroupModelSpec.scala | 3 ++- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index 2e277561e2..f188e5804b 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -144,19 +144,14 @@ object TransformerControlGroupModel { /** Determine the regulation criterion of the nodes to control * - * @param complexVoltage - * Collection of all known [[MeasurementUnitInput]] s * @param vMax - * and + * Maximum voltage limit * @param vMin - * Voltage limits of the node + * Minimum voltage limit * @return - * The RegulationCriterion in this case a set of node uuids and optional - * voltage deviation + * The regulation need, if applicable */ - private def regulationFunction( - complexVoltage: Complex, vMax: Double, vMin: Double, ): RegulationCriterion = { (voltage: Complex) => @@ -218,9 +213,8 @@ object TransformerControlGroupModel { vMin: Double, ): TransformerControlGroupModel = { /* Determine the voltage regulation criterion for each of the available nodes */ - val voltage = Complex(1.0, 0.0) val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> regulationFunction(voltage, vMax, vMin) + uuid -> regulationFunction(vMax, vMin) }.toMap TransformerControlGroupModel( diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala index c0c47d92cd..ae827342d9 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala @@ -11,7 +11,6 @@ import breeze.math.Complex import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult import edu.ie3.powerflow.model.enums.NodeType -import edu.ie3.simona.model.grid.GridModel import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.matchers.QuantityMatchers import squants.{Dimensionless, Each} @@ -19,7 +18,9 @@ import squants.{Dimensionless, Each} import java.util.UUID class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { + implicit val tolerance: Dimensionless = Each(1e-10) + "Checking the function of transformer control groups" should { val buildTransformerControlModels = PrivateMethod[TransformerControlGroupModel]( From 5916a980d33abaaa9210aacd30b5f3cc2fa859c8 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 17:15:13 +0100 Subject: [PATCH 116/123] Removing obsolete test --- .../edu/ie3/simona/model/grid/GridSpec.scala | 97 ++----------------- 1 file changed, 6 insertions(+), 91 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index 1fa4122da3..bdf17b1170 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -6,17 +6,13 @@ package edu.ie3.simona.model.grid -import java.util.UUID import breeze.linalg.DenseMatrix import breeze.math.Complex import breeze.numerics.abs - import edu.ie3.datamodel.exceptions.InvalidGridException -import edu.ie3.datamodel.models.input.MeasurementUnitInput -import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils - import edu.ie3.simona.exceptions.GridInconsistencyException -import edu.ie3.simona.model.control.{GridControls, TransformerControlGroupModel} +import edu.ie3.simona.model.control.GridControls +import edu.ie3.simona.model.grid.GridModel.GridComponents import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} import edu.ie3.simona.test.common.model.grid.{ BasicGrid, @@ -24,11 +20,8 @@ import edu.ie3.simona.test.common.model.grid.{ FiveLinesWithNodes, } import edu.ie3.simona.test.common.{ConfigTestData, DefaultTestData, UnitSpec} -import testutils.TestObjectFactory -import scala.jdk.CollectionConverters.SetHasAsJava - -import edu.ie3.simona.model.grid.GridModel.GridComponents +import java.util.UUID class GridSpec extends UnitSpec @@ -470,89 +463,9 @@ class GridSpec gridModel.nodeUuidToIndexMap.keySet.toVector.sorted should be( nodes.map(node => node.uuid).toVector.sorted ) - } - } - - "build correct transformer control models" should { - /* Testing of distinct transformer control group building can be found in the spec for transformer control groups */ - - "determine node uuids correctly" in { - val determineNodeUuids = - PrivateMethod[Set[UUID]](Symbol("determineNodeUuids")) - - val node0 = TestObjectFactory.buildNodeInput( - false, - GermanVoltageLevelUtils.MV_10KV, - 1, - ) - val node1 = TestObjectFactory.buildNodeInput( - false, - GermanVoltageLevelUtils.MV_10KV, - 1, - ) - val node2 = TestObjectFactory.buildNodeInput( - false, - GermanVoltageLevelUtils.MV_10KV, - 1, - ) - val node3 = TestObjectFactory.buildNodeInput( - false, - GermanVoltageLevelUtils.MV_10KV, - 1, - ) - val measurementUnits = Set( - new MeasurementUnitInput( - UUID.fromString("3ad9e076-c02b-4cf9-8720-18e2bb541ede"), - "measurement_unit_0", - node0, - true, - false, - false, - false, - ), - new MeasurementUnitInput( - UUID.fromString("ab66fbb0-ece1-44b9-9341-86a884233ec4"), - "measurement_unit_1", - node1, - true, - false, - false, - false, - ), - new MeasurementUnitInput( - UUID.fromString("93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d"), - "measurement_unit_2", - node2, - true, - false, - false, - false, - ), - new MeasurementUnitInput( - UUID.fromString("8e84eb8a-2940-4900-b0ce-0eeb6bca8bae"), - "measurement_unit_3", - node3, - false, - false, - false, - false, - ), - ).asJava - val selectedMeasurements = Set( - "ab66fbb0-ece1-44b9-9341-86a884233ec4", - "93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d", - "8e84eb8a-2940-4900-b0ce-0eeb6bca8bae", - ) - val expectedUuids = Set(node1, node2).map(_.getUuid) - - val actual = - TransformerControlGroupModel invokePrivate determineNodeUuids( - measurementUnits, - selectedMeasurements, - ) - actual should contain theSameElementsAs expectedUuids } + } "process a valid GridInputModel without an Exception" in new GridInputTestData { @@ -563,6 +476,8 @@ class GridSpec defaultSimulationEnd, simonaConfig, ) + } } + } From 38f1e66141a94e928eec92f0de8e28802ad1800f Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 17:16:40 +0100 Subject: [PATCH 117/123] A more radical reduction of code... --- .../TransformerControlGroupModel.scala | 123 ++---------------- .../edu/ie3/simona/model/grid/GridModel.scala | 3 +- .../TransformerControlGroupModelSpec.scala | 49 ++----- 3 files changed, 23 insertions(+), 152 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index f188e5804b..ccfafe2143 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -7,7 +7,6 @@ package edu.ie3.simona.model.control import breeze.math.Complex -import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult import edu.ie3.simona.config.SimonaConfig @@ -18,18 +17,16 @@ import edu.ie3.simona.model.control.TransformerControlGroupModel.{ } import squants.{Dimensionless, Each} -import java.util.UUID - /** Business logic for a transformer control group. It's main purpose is to * determine, if there is any regulation need and if yes, to what extent (here: * voltage raise or reduction to achieve) * - * @param nodalRegulationCriterion + * @param regulationCriterion * Mapping from nodal index to a partial function, that determines the * regulation need at this node */ final case class TransformerControlGroupModel( - nodalRegulationCriterion: Map[UUID, RegulationCriterion] + regulationCriterion: RegulationCriterion ) { /** Based on the given successful power flow result, determine the difference @@ -38,33 +35,18 @@ final case class TransformerControlGroupModel( * * @param result * Power flow result to account for - * @param uuidToIndex - * Mapping from node's uuid to nodal index * @return * Optional voltage magnitude, that a transformer tap regulation needs to * achieve */ def determineRegulationNeed( - result: SuccessFullPowerFlowResult, - uuidToIndex: Map[UUID, Int], + result: SuccessFullPowerFlowResult ): Option[Dimensionless] = { val regulationNeeds = result.nodeData.flatMap { - case StateData(resultNodeIndex, _, voltage, _) => - /* Find possible matching criterion and evaluate it */ - nodalRegulationCriterion - .find { case (uuid, _) => - val index = uuidToIndex(uuid) - index == resultNodeIndex - } - .map { case (_, criterion) => - criterion(voltage) - } - }.flatten - Option - .when(regulationNeeds.nonEmpty)( - harmonizeRegulationNeeds(regulationNeeds) - ) - .flatten + case StateData(_, _, voltage, _) => + regulationCriterion(voltage) + } + harmonizeRegulationNeeds(regulationNeeds) } } @@ -76,72 +58,16 @@ object TransformerControlGroupModel { * * @param config * List of configs for control groups - * @param measurementUnitInput - * Set of [[MeasurementUnitInput]] s * @return * A set of control group business models */ def buildControlGroups( - config: List[SimonaConfig.TransformerControlGroup], - measurementUnitInput: Set[MeasurementUnitInput], + config: Iterable[SimonaConfig.TransformerControlGroup] ): Set[TransformerControlGroupModel] = config.map { - case TransformerControlGroup(measurements, _, vMax, vMin) => - buildTransformerControlGroupModel( - measurementUnitInput, - measurements.toSet, - vMax, - vMin, - ) + case TransformerControlGroup(_, _, vMax, vMin) => + TransformerControlGroupModel(regulationFunction(vMax, vMin)) }.toSet - /** Build a single control group model. Currently, only limit violation - * prevention logic is captured: The nodal regulation need is equal to the - * voltage change needed to comply with the given thresholds - * - * @param measurementUnitInput - * Collection of all known [[MeasurementUnitInput]] s - * @param measurementConfigs - * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] - * s does belong to this control group - * @param vMax - * Upper permissible voltage magnitude - * @param vMin - * Lower permissible voltage magnitude - * @return - * A [[TransformerControlGroupModel]] - */ - private def buildTransformerControlGroupModel( - measurementUnitInput: Set[MeasurementUnitInput], - measurementConfigs: Set[String], - vMax: Double, - vMin: Double, - ): TransformerControlGroupModel = { - val nodeUuids = - determineNodeUuids(measurementUnitInput, measurementConfigs) - buildTransformerControlModels(nodeUuids, vMax, vMin) - } - - /** Determine the uuids of the nodes to control - * - * @param measurementUnitInput - * Collection of all known [[MeasurementUnitInput]] s - * @param measurementConfigs - * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] - * s does belong to this control group - * @return - * A set of relevant nodal uuids - */ - private def determineNodeUuids( - measurementUnitInput: Set[MeasurementUnitInput], - measurementConfigs: Set[String], - ): Set[UUID] = Set.from( - measurementUnitInput - .filter(input => - measurementConfigs.contains(input.getUuid.toString) && input.getVMag - ) - .map(_.getNode.getUuid) - ) - /** Determine the regulation criterion of the nodes to control * * @param vMax @@ -175,7 +101,7 @@ object TransformerControlGroupModel { private def harmonizeRegulationNeeds( regulationRequests: Array[Dimensionless] ): Option[Dimensionless] = { - val negativeRequests = regulationRequests.array.filter(_ < Each(0d)) + val negativeRequests = regulationRequests.filter(_ < Each(0d)) val positiveRequests = regulationRequests.filter(_ > Each(0d)) (negativeRequests.nonEmpty, positiveRequests.nonEmpty) match { @@ -194,31 +120,4 @@ object TransformerControlGroupModel { } - /** Build a single control group model. Currently, only limit violation - * prevention logic is captured: The nodal regulation need is equal to the - * voltage change needed to comply with the given thresholds - * - * @param nodeUuids - * Collection of all relevant node uuids - * @param vMax - * Upper permissible voltage magnitude - * @param vMin - * Lower permissible voltage magnitude - * @return - * A [[TransformerControlGroupModel]] - */ - private def buildTransformerControlModels( - nodeUuids: Set[UUID], - vMax: Double, - vMin: Double, - ): TransformerControlGroupModel = { - /* Determine the voltage regulation criterion for each of the available nodes */ - val nodeUuidToRegulationCriterion = nodeUuids.map { uuid => - uuid -> regulationFunction(vMax, vMin) - }.toMap - - TransformerControlGroupModel( - nodeUuidToRegulationCriterion - ) - } } diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index 1eec288b80..c3d5e3cff9 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -604,8 +604,7 @@ object GridModel { val transformerControlGroups = simonaConfig.simona.control .map { controlConfig => TransformerControlGroupModel.buildControlGroups( - controlConfig.transformer, - subGridContainer.getRawGrid.getMeasurementUnits.asScala.toSet, + controlConfig.transformer ) } .getOrElse(Set.empty) diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala index ae827342d9..364ca91c8c 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala @@ -11,50 +11,23 @@ import breeze.math.Complex import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult import edu.ie3.powerflow.model.enums.NodeType +import edu.ie3.simona.model.control.TransformerControlGroupModel.RegulationCriterion import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.matchers.QuantityMatchers import squants.{Dimensionless, Each} -import java.util.UUID - class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { implicit val tolerance: Dimensionless = Each(1e-10) "Checking the function of transformer control groups" should { - val buildTransformerControlModels = - PrivateMethod[TransformerControlGroupModel]( - Symbol("buildTransformerControlModels") - ) - implicit val tolerance: Dimensionless = Each(1e-10) - val dut = - TransformerControlGroupModel invokePrivate buildTransformerControlModels( - Set( - UUID.fromString( - "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" - ), - UUID.fromString( - "08b8d2ca-993d-45cd-9456-f009ecb47bc0" - ), - UUID.fromString( - "324f49e5-1c35-4c49-afb1-3cf41696bf93" - ), - ), - 1.1, - 0.9, - ) + val regulationFunction = + PrivateMethod[RegulationCriterion](Symbol("regulationFunction")) + + val regulationCriterion = + TransformerControlGroupModel invokePrivate regulationFunction(1.1, 0.9) - val uuidToIndex = Map( - UUID.fromString( - "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" - ) -> 0, - UUID.fromString( - "08b8d2ca-993d-45cd-9456-f009ecb47bc0" - ) -> 1, - UUID.fromString( - "324f49e5-1c35-4c49-afb1-3cf41696bf93" - ) -> 2, - ) + val dut = TransformerControlGroupModel(regulationCriterion) "return no regulation need, if everything is fine" in { val result = ValidNewtonRaphsonPFResult( @@ -67,7 +40,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result, uuidToIndex) + val actual = dut.determineRegulationNeed(result) actual shouldBe None } @@ -83,7 +56,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result, uuidToIndex) + val actual = dut.determineRegulationNeed(result) actual shouldBe None } @@ -99,7 +72,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result, uuidToIndex) + val actual = dut.determineRegulationNeed(result) actual match { case Some(regulationNeed) => @@ -119,7 +92,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result, uuidToIndex) + val actual = dut.determineRegulationNeed(result) actual match { case Some(regulationNeed) => From 12a28e6852b40d9c1b481bde186e167c5dacab9e Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Feb 2024 18:29:27 +0100 Subject: [PATCH 118/123] Including measured nodes in a different way --- .../TransformerControlGroupModel.scala | 58 ++++++++++--- .../edu/ie3/simona/model/grid/GridModel.scala | 3 +- .../TransformerControlGroupModelSpec.scala | 37 ++++++-- .../edu/ie3/simona/model/grid/GridSpec.scala | 86 ++++++++++++++++++- 4 files changed, 167 insertions(+), 17 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala index ccfafe2143..2354770480 100644 --- a/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala +++ b/src/main/scala/edu/ie3/simona/model/control/TransformerControlGroupModel.scala @@ -7,6 +7,7 @@ package edu.ie3.simona.model.control import breeze.math.Complex +import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.powerflow.model.NodeData.StateData import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult import edu.ie3.simona.config.SimonaConfig @@ -17,16 +18,20 @@ import edu.ie3.simona.model.control.TransformerControlGroupModel.{ } import squants.{Dimensionless, Each} +import java.util.UUID + /** Business logic for a transformer control group. It's main purpose is to * determine, if there is any regulation need and if yes, to what extent (here: * voltage raise or reduction to achieve) * + * @param measuredNodes + * The nodes (with voltage measurement) to consider * @param regulationCriterion - * Mapping from nodal index to a partial function, that determines the - * regulation need at this node + * Function that determines the regulation need */ final case class TransformerControlGroupModel( - regulationCriterion: RegulationCriterion + measuredNodes: Set[UUID], + regulationCriterion: RegulationCriterion, ) { /** Based on the given successful power flow result, determine the difference @@ -35,17 +40,25 @@ final case class TransformerControlGroupModel( * * @param result * Power flow result to account for + * @param uuidToIndex + * Mapping from node's uuid to nodal index * @return * Optional voltage magnitude, that a transformer tap regulation needs to * achieve */ def determineRegulationNeed( - result: SuccessFullPowerFlowResult + result: SuccessFullPowerFlowResult, + uuidToIndex: Map[UUID, Int], ): Option[Dimensionless] = { - val regulationNeeds = result.nodeData.flatMap { - case StateData(_, _, voltage, _) => + val regulationNeeds = result.nodeData + .filter { case StateData(resultNodeIndex, _, _, _) => + measuredNodes.exists { uuid => + resultNodeIndex == uuidToIndex(uuid) + } + } + .flatMap { case StateData(_, _, voltage, _) => regulationCriterion(voltage) - } + } harmonizeRegulationNeeds(regulationNeeds) } } @@ -56,18 +69,43 @@ object TransformerControlGroupModel { /** Build business models for control groups * + * @param measurementUnitInput + * Set of [[MeasurementUnitInput]] s * @param config * List of configs for control groups * @return * A set of control group business models */ def buildControlGroups( - config: Iterable[SimonaConfig.TransformerControlGroup] + measurementUnitInput: Set[MeasurementUnitInput], + config: Iterable[SimonaConfig.TransformerControlGroup], ): Set[TransformerControlGroupModel] = config.map { - case TransformerControlGroup(_, _, vMax, vMin) => - TransformerControlGroupModel(regulationFunction(vMax, vMin)) + case TransformerControlGroup(measurements, _, vMax, vMin) => + val nodeUuids = + determineNodeUuids(measurementUnitInput, measurements.toSet) + TransformerControlGroupModel(nodeUuids, regulationFunction(vMax, vMin)) }.toSet + /** Determine the uuids of the nodes to control + * + * @param measurementUnitInput + * Collection of all known [[MeasurementUnitInput]] s + * @param measurementConfigs + * Collection of all uuids, denoting which of the [[MeasurementUnitInput]] + * s does belong to this control group + * @return + * A set of relevant nodal uuids + */ + private def determineNodeUuids( + measurementUnitInput: Set[MeasurementUnitInput], + measurementConfigs: Set[String], + ): Set[UUID] = + measurementUnitInput + .filter(input => + measurementConfigs.contains(input.getUuid.toString) && input.getVMag + ) + .map(_.getNode.getUuid) + /** Determine the regulation criterion of the nodes to control * * @param vMax diff --git a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala index c3d5e3cff9..f2eab5ff1d 100644 --- a/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala +++ b/src/main/scala/edu/ie3/simona/model/grid/GridModel.scala @@ -604,7 +604,8 @@ object GridModel { val transformerControlGroups = simonaConfig.simona.control .map { controlConfig => TransformerControlGroupModel.buildControlGroups( - controlConfig.transformer + subGridContainer.getRawGrid.getMeasurementUnits.asScala.toSet, + controlConfig.transformer, ) } .getOrElse(Set.empty) diff --git a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala index 364ca91c8c..67d762dca7 100644 --- a/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/control/TransformerControlGroupModelSpec.scala @@ -16,6 +16,8 @@ import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.matchers.QuantityMatchers import squants.{Dimensionless, Each} +import java.util.UUID + class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { implicit val tolerance: Dimensionless = Each(1e-10) @@ -27,7 +29,32 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { val regulationCriterion = TransformerControlGroupModel invokePrivate regulationFunction(1.1, 0.9) - val dut = TransformerControlGroupModel(regulationCriterion) + val dut = TransformerControlGroupModel( + Set( + UUID.fromString( + "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" + ), + UUID.fromString( + "08b8d2ca-993d-45cd-9456-f009ecb47bc0" + ), + UUID.fromString( + "324f49e5-1c35-4c49-afb1-3cf41696bf93" + ), + ), + regulationCriterion, + ) + + val uuidToIndex = Map( + UUID.fromString( + "d4d650be-87b7-4cf6-be7f-03f0bbcde3e3" + ) -> 0, + UUID.fromString( + "08b8d2ca-993d-45cd-9456-f009ecb47bc0" + ) -> 1, + UUID.fromString( + "324f49e5-1c35-4c49-afb1-3cf41696bf93" + ) -> 2, + ) "return no regulation need, if everything is fine" in { val result = ValidNewtonRaphsonPFResult( @@ -40,7 +67,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result) + val actual = dut.determineRegulationNeed(result, uuidToIndex) actual shouldBe None } @@ -56,7 +83,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result) + val actual = dut.determineRegulationNeed(result, uuidToIndex) actual shouldBe None } @@ -72,7 +99,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result) + val actual = dut.determineRegulationNeed(result, uuidToIndex) actual match { case Some(regulationNeed) => @@ -92,7 +119,7 @@ class TransformerControlGroupModelSpec extends UnitSpec with QuantityMatchers { DenseMatrix.zeros(1, 1), ) - val actual = dut.determineRegulationNeed(result) + val actual = dut.determineRegulationNeed(result, uuidToIndex) actual match { case Some(regulationNeed) => diff --git a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala index bdf17b1170..53165fc018 100644 --- a/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/grid/GridSpec.scala @@ -10,8 +10,10 @@ import breeze.linalg.DenseMatrix import breeze.math.Complex import breeze.numerics.abs import edu.ie3.datamodel.exceptions.InvalidGridException +import edu.ie3.datamodel.models.input.MeasurementUnitInput +import edu.ie3.datamodel.models.voltagelevels.GermanVoltageLevelUtils import edu.ie3.simona.exceptions.GridInconsistencyException -import edu.ie3.simona.model.control.GridControls +import edu.ie3.simona.model.control.{GridControls, TransformerControlGroupModel} import edu.ie3.simona.model.grid.GridModel.GridComponents import edu.ie3.simona.test.common.input.{GridInputTestData, LineInputTestData} import edu.ie3.simona.test.common.model.grid.{ @@ -20,6 +22,7 @@ import edu.ie3.simona.test.common.model.grid.{ FiveLinesWithNodes, } import edu.ie3.simona.test.common.{ConfigTestData, DefaultTestData, UnitSpec} +import testutils.TestObjectFactory import java.util.UUID @@ -463,7 +466,88 @@ class GridSpec gridModel.nodeUuidToIndexMap.keySet.toVector.sorted should be( nodes.map(node => node.uuid).toVector.sorted ) + } + } + + "build correct transformer control models" should { + /* Testing of distinct transformer control group building can be found in the spec for transformer control groups */ + "determine node uuids correctly" in { + val determineNodeUuids = + PrivateMethod[Set[UUID]](Symbol("determineNodeUuids")) + + val node0 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1, + ) + val node1 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1, + ) + val node2 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1, + ) + val node3 = TestObjectFactory.buildNodeInput( + false, + GermanVoltageLevelUtils.MV_10KV, + 1, + ) + + val measurementUnits = Set( + new MeasurementUnitInput( + UUID.fromString("3ad9e076-c02b-4cf9-8720-18e2bb541ede"), + "measurement_unit_0", + node0, + true, + false, + false, + false, + ), + new MeasurementUnitInput( + UUID.fromString("ab66fbb0-ece1-44b9-9341-86a884233ec4"), + "measurement_unit_1", + node1, + true, + false, + false, + false, + ), + new MeasurementUnitInput( + UUID.fromString("93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d"), + "measurement_unit_2", + node2, + true, + false, + false, + false, + ), + new MeasurementUnitInput( + UUID.fromString("8e84eb8a-2940-4900-b0ce-0eeb6bca8bae"), + "measurement_unit_3", + node3, + false, + false, + false, + false, + ), + ) + val selectedMeasurements = Set( + "ab66fbb0-ece1-44b9-9341-86a884233ec4", + "93b4d0d8-cc67-41f5-9d5c-1cd6dbb2e70d", + "8e84eb8a-2940-4900-b0ce-0eeb6bca8bae", + ) + val expectedUuids = Set(node1, node2).map(_.getUuid) + + val actual = + TransformerControlGroupModel invokePrivate determineNodeUuids( + measurementUnits, + selectedMeasurements, + ) + actual should contain theSameElementsAs expectedUuids } } From b50a071698ac344f18a7050c7629aa539e7570a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Feb 2024 09:43:29 +0000 Subject: [PATCH 119/123] Bump ch.qos.logback:logback-classic from 1.5.0 to 1.5.1 (#758) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 947731e542..e043a1d639 100644 --- a/build.gradle +++ b/build.gradle @@ -97,7 +97,7 @@ dependencies { /* logging */ implementation "com.typesafe.scala-logging:scala-logging_${scalaVersion}:3.9.5" // pekko scala logging - implementation "ch.qos.logback:logback-classic:1.5.0" + implementation "ch.qos.logback:logback-classic:1.5.1" /* testing */ testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0' From 3b7cd2c4fac016ac91a611fde21bf928b8a2b078 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:44:08 +0100 Subject: [PATCH 120/123] Bump de.undercouch.download from 5.5.0 to 5.6.0 (#759) * Bump de.undercouch.download from 5.5.0 to 5.6.0 Bumps [de.undercouch.download](https://github.com/michel-kraemer/gradle-download-task) from 5.5.0 to 5.6.0. - [Release notes](https://github.com/michel-kraemer/gradle-download-task/releases) - [Commits](https://github.com/michel-kraemer/gradle-download-task/compare/5.5.0...5.6.0) --- updated-dependencies: - dependency-name: de.undercouch.download dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix links * fix fix links --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: danielfeismann --- build.gradle | 2 +- docs/readthedocs/models/cts_model.md | 2 +- docs/readthedocs/models/thermal_grid_model.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index e043a1d639..7097a0a779 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ plugins { id 'pmd' // code check, working on source code id 'com.diffplug.spotless' version '6.25.0'// code format id "com.github.ben-manes.versions" version '0.51.0' - id "de.undercouch.download" version "5.5.0" // downloads plugin + id "de.undercouch.download" version "5.6.0" // downloads plugin id "kr.motd.sphinx" version "2.10.1" // documentation generation id "com.github.johnrengelman.shadow" version "8.1.1" // fat jar id "org.sonarqube" version "4.4.1.3373" // sonarqube diff --git a/docs/readthedocs/models/cts_model.md b/docs/readthedocs/models/cts_model.md index eea6fcfe0c..0ca51a7395 100644 --- a/docs/readthedocs/models/cts_model.md +++ b/docs/readthedocs/models/cts_model.md @@ -7,7 +7,7 @@ This storage model operates on volumes, although the functions it provides for o ## Attributes, Units and Remarks -Please refer to {doc}`PowerSystemDataModel - CTS Model ` for Attributes and Units used in this Model. +Please refer to {doc}`PowerSystemDataModel - CTS Model ` for Attributes and Units used in this Model. ## Calculations ### Maximal storage capacity diff --git a/docs/readthedocs/models/thermal_grid_model.md b/docs/readthedocs/models/thermal_grid_model.md index e7aa2c214e..fc16159552 100644 --- a/docs/readthedocs/models/thermal_grid_model.md +++ b/docs/readthedocs/models/thermal_grid_model.md @@ -5,4 +5,4 @@ The Thermal Grid Model introduces a coupling point to thermal system, equivalent ## Attributes, Units and Remarks -Please refer to {doc}`PowerSystemDataModel - Thermal Bus ` for Attributes and Units used in this Model. +Please refer to {doc}`PowerSystemDataModel - Thermal Bus ` for Attributes and Units used in this Model. From 417775ee5686c67af0637bb5a37cc766a8c36a17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 09:53:28 +0000 Subject: [PATCH 121/123] Bump org.mockito:mockito-core from 5.10.0 to 5.11.0 (#760) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7097a0a779..0712396ca2 100644 --- a/build.gradle +++ b/build.gradle @@ -102,7 +102,7 @@ dependencies { /* testing */ testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0' testImplementation 'org.scalatestplus:mockito-3-4_2.13:3.2.10.0' - testImplementation 'org.mockito:mockito-core:5.10.0' // mocking framework + testImplementation 'org.mockito:mockito-core:5.11.0' // mocking framework testImplementation "org.scalatest:scalatest_${scalaVersion}:3.2.18" testRuntimeOnly 'com.vladsch.flexmark:flexmark-all:0.64.8' //scalatest html output testImplementation group: 'org.pegdown', name: 'pegdown', version: '1.6.0' From 77deb60e6714a487e5ae3cbfc48cdb9b2b2c000f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:00:16 +0000 Subject: [PATCH 122/123] Bump ch.qos.logback:logback-classic from 1.5.1 to 1.5.2 (#761) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0712396ca2..00887fd062 100644 --- a/build.gradle +++ b/build.gradle @@ -97,7 +97,7 @@ dependencies { /* logging */ implementation "com.typesafe.scala-logging:scala-logging_${scalaVersion}:3.9.5" // pekko scala logging - implementation "ch.qos.logback:logback-classic:1.5.1" + implementation "ch.qos.logback:logback-classic:1.5.2" /* testing */ testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0' From 32b4808a291fadf3f30890f3605156094b4ca8fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 07:28:14 +0000 Subject: [PATCH 123/123] Bump ch.qos.logback:logback-classic from 1.5.2 to 1.5.3 (#762) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 00887fd062..b4a0226708 100644 --- a/build.gradle +++ b/build.gradle @@ -97,7 +97,7 @@ dependencies { /* logging */ implementation "com.typesafe.scala-logging:scala-logging_${scalaVersion}:3.9.5" // pekko scala logging - implementation "ch.qos.logback:logback-classic:1.5.2" + implementation "ch.qos.logback:logback-classic:1.5.3" /* testing */ testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0'