diff --git a/CHANGELOG.md b/CHANGELOG.md index 88db7d5a69..ff2796b77b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Adapt to new simonaAPI snapshot [#95](https://github.com/ie3-institute/simona/issues/95) - Update Sphinx to 4.5.0 as well as extensions [#214](https://github.com/ie3-institute/simona/issues/214) - Improved code quality in and around DBFS algorithm [#265](https://github.com/ie3-institute/simona/issues/265) +- Adapt test to new PowerSystemUtils snapshot [#294](https://github.com/ie3-institute/simona/issues/294) +- Simplified ParticipantConfigUtil [#273](https://github.com/ie3-institute/simona/issues/273) ### Fixed - Location of `vn_simona` test grid (was partially in Berlin and Dortmund) [#72](https://github.com/ie3-institute/simona/issues/72) @@ -50,6 +52,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed some unreachable code [#167](https://github.com/ie3-institute/simona/issues/167) - Fix treatment of non-InitializeTrigger triggers in initialization within SimScheduler [#237](https://github.com/ie3-institute/simona/issues/237) - Fix breaking SIMONA caused by introducing temperature dependant load profiles in PSDM [#255](https://github.com/ie3-institute/simona/issues/255) +- Respect for voltage angle in DBFS slack voltage exchange protocol [#69](https://github.com/ie3-institute/simona/issues/69) +- Adapted to changed time series interfaces in PSDM [#296](https://github.com/ie3-institute/simona/issues/296) ### Removed - Remove workaround for tscfg tmp directory [#178](https://github.com/ie3-institute/simona/issues/178) diff --git a/build.gradle b/build.gradle index 7892e8c7fe..27d6b01279 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'signing' id 'maven-publish' // publish to a maven repo (local or mvn central, has to be defined) id 'pmd' // code check, working on source code - id 'com.diffplug.spotless' version '6.7.2'// code format + id 'com.diffplug.spotless' version '6.9.0'// code format id 'com.github.onslip.gradle-one-jar' version '1.0.6' // pack a self contained jar id "com.github.ben-manes.versions" version '0.42.0' id "de.undercouch.download" version "5.1.0" // downloads plugin @@ -29,9 +29,9 @@ ext { akkaVersion = '2.6.19' jtsVersion = '1.19.0' tscfgVersion = '0.9.998' - scapegoatVersion = '1.4.14' + scapegoatVersion = '1.4.15' - testContainerVersion = '0.40.8' + testContainerVersion = '0.40.9' scriptsLocation = 'gradle' + File.separator + 'scripts' + File.separator // location of script plugins } @@ -147,7 +147,7 @@ dependencies { /* Kafka */ implementation group: 'org.apache.kafka', name: 'kafka-clients', version: '3.2.0' - implementation 'io.confluent:kafka-streams-avro-serde:7.1.2' + implementation 'io.confluent:kafka-streams-avro-serde:7.2.1' implementation "com.sksamuel.avro4s:avro4s-core_${scalaVersion}:4.1.0" implementation 'org.apache.commons:commons-math3:3.6.1' // apache commons math3 diff --git a/gradle.properties b/gradle.properties index b761da57f7..7206f5237b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,20 +9,11 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. - -# Workaround to make spotless work with java 17 - -# see https://github.com/diffplug/spotless/tree/main/plugin-gradle#google-java-format and -# https://github.com/ie3-institute/simona/issues/59 for details -org.gradle.jvmargs=-Xmx4096m \ - --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ - --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ - --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ - --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ - --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +org.gradle.jvmargs=-Xmx4096m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -com.github.maiflai.gradle-scalatest.mode = append \ No newline at end of file +com.github.maiflai.gradle-scalatest.mode = append 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 1a62da2bee..71c9b6ea98 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala @@ -433,21 +433,23 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { ) val gridModel = gridAgentBaseData.gridEnv.gridModel - val powerFlowResult = newtonRaphsonPF( + + val (operatingPoint, slackNodeVoltages) = composeOperatingPoint( + gridModel.gridComponents.nodes, + gridModel.gridComponents.transformers, + gridModel.gridComponents.transformers3w, + gridModel.nodeUuidToIndexMap, + gridAgentBaseData.receivedValueStore, + gridModel.mainRefSystem + ) + + newtonRaphsonPF( gridModel, gridAgentBaseData.powerFlowParams.maxIterations, - composeOperatingPoint( - gridModel.gridComponents.nodes, - gridModel.gridComponents.transformers, - gridModel.gridComponents.transformers3w, - gridModel.nodeUuidToIndexMap, - gridAgentBaseData.receivedValueStore, - gridModel.mainRefSystem - ) - )(gridAgentBaseData.powerFlowParams.epsilon) - - // if res is valid, ask our assets (if any) for updated power values based on the newly determined nodal voltages - powerFlowResult match { + 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( "{}", @@ -579,9 +581,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { s"$actorName Unable to get results from previous sweep ${gridAgentBaseData.currentSweepNo - 1}!" ) ) - newtonRaphsonPF( - gridModel, - gridAgentBaseData.powerFlowParams.maxIterations, + + val (operatingPoint, slackNodeVoltages) = composeOperatingPointWithUpdatedSlackVoltages( receivedSlackValues, previousSweepData.sweepData, @@ -589,6 +590,12 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { gridModel.gridComponents.transformers3w, gridModel.mainRefSystem ) + + newtonRaphsonPF( + gridModel, + gridAgentBaseData.powerFlowParams.maxIterations, + operatingPoint, + slackNodeVoltages )(gridAgentBaseData.powerFlowParams.epsilon) match { case validPowerFlowResult: ValidNewtonRaphsonPFResult => log.debug( @@ -658,7 +665,10 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { case failedNewtonRaphsonPFResult: FailedNewtonRaphsonPFResult => val powerFlowDoneData = - PowerFlowDoneData(gridAgentBaseData, failedNewtonRaphsonPFResult) + PowerFlowDoneData( + gridAgentBaseData, + failedNewtonRaphsonPFResult + ) log.warning( "Power flow with updated slack voltage did finally not converge!" ) @@ -705,7 +715,7 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { /* This is the highest grid agent, therefore no data is received for the slack node. Suppress, that it is looked * up in the empty store. */ - val operationPoint = composeOperatingPoint( + val (operationPoint, slackNodeVoltages) = composeOperatingPoint( gridModel.gridComponents.nodes, gridModel.gridComponents.transformers, gridModel.gridComponents.transformers3w, @@ -729,7 +739,8 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport { newtonRaphsonPF( gridModel, gridAgentBaseData.powerFlowParams.maxIterations, - operationPoint + operationPoint, + slackNodeVoltages )(gridAgentBaseData.powerFlowParams.epsilon) match { case validPowerFlowResult: ValidNewtonRaphsonPFResult => log.debug( 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 3379d9333c..a4c23b635b 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala @@ -221,7 +221,9 @@ class GridAgentController( case input: FixedFeedInInput => buildFixedFeedIn( input, - participantConfigUtil.getFixedFeedConfigOrDefault(input.getUuid), + participantConfigUtil.getOrDefault[FixedFeedInRuntimeConfig]( + input.getUuid + ), environmentRefs.primaryServiceProxy, simulationStartDate, simulationEndDate, @@ -232,7 +234,9 @@ class GridAgentController( case input: LoadInput => buildLoad( input, - participantConfigUtil.getLoadConfigOrDefault(input.getUuid), + participantConfigUtil.getOrDefault[LoadRuntimeConfig]( + input.getUuid + ), environmentRefs.primaryServiceProxy, simulationStartDate, simulationEndDate, @@ -243,7 +247,9 @@ class GridAgentController( case input: PvInput => buildPV( input, - participantConfigUtil.getPvConfigOrDefault(input.getUuid), + participantConfigUtil.getOrDefault[PvRuntimeConfig]( + input.getUuid + ), environmentRefs.primaryServiceProxy, environmentRefs.weather, simulationStartDate, @@ -255,7 +261,9 @@ class GridAgentController( case input: WecInput => buildWec( input, - participantConfigUtil.getWecConfigOrDefault(input.getUuid), + participantConfigUtil.getOrDefault[WecRuntimeConfig]( + input.getUuid + ), environmentRefs.primaryServiceProxy, environmentRefs.weather, simulationStartDate, @@ -267,7 +275,9 @@ class GridAgentController( case input: EvcsInput => buildEvcs( input, - participantConfigUtil.getEvcsConfigOrDefault(input.getUuid), + participantConfigUtil.getOrDefault[EvcsRuntimeConfig]( + input.getUuid + ), environmentRefs.primaryServiceProxy, environmentRefs.evDataService.getOrElse( throw new GridAgentInitializationException( 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 428c26e596..735801bfd3 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 java.util.UUID import breeze.math.Complex import edu.ie3.powerflow.NewtonRaphsonPF import edu.ie3.powerflow.model.NodeData.{PresetData, StateData} @@ -16,22 +15,16 @@ import edu.ie3.powerflow.model.StartData.WithForcedStartVoltages import edu.ie3.powerflow.model.enums.NodeType import edu.ie3.simona.agent.grid.ReceivedValues.ReceivedSlackValues import edu.ie3.simona.exceptions.agent.DBFSAlgorithmException -import edu.ie3.simona.model.grid.{ - GridModel, - NodeModel, - RefSystem, - Transformer3wModel, - TransformerModel -} +import edu.ie3.simona.model.grid._ import edu.ie3.simona.ontology.messages.PowerMessage.ProvidePowerMessage import edu.ie3.simona.ontology.messages.VoltageMessage.ProvideSlackVoltageMessage import edu.ie3.util.quantities.PowerSystemUnits import tech.units.indriya.ComparableQuantity +import tech.units.indriya.quantity.Quantities +import java.util.UUID import javax.measure.Quantity import javax.measure.quantity.{Dimensionless, ElectricPotential} -import tech.units.indriya.quantity.Quantities - import scala.collection.mutable import scala.util.{Failure, Success, Try} @@ -67,7 +60,8 @@ trait PowerFlowSupport { * receivedValuesStore) * @return * current operating point of the grid to be used with - * [[edu.ie3.powerflow.NewtonRaphsonPF.calculate()]] + * [[edu.ie3.powerflow.NewtonRaphsonPF.calculate()]] as well as the complex + * slack node target voltages */ protected def composeOperatingPoint( nodes: Set[NodeModel], @@ -78,14 +72,13 @@ trait PowerFlowSupport { gridMainRefSystem: RefSystem, targetVoltageFromReceivedData: Boolean = true, ignoreTargetVoltage: Boolean = false - ): Array[PresetData] = { - - val mainRefSystemPowerUnit = gridMainRefSystem.nominalPower.getUnit - + ): (Array[PresetData], WithForcedStartVoltages) = { nodes.toArray.map { nodeModel => // note: currently we only support pq nodes as we not distinguish between pq/pv nodes - // when slack emulators or pv-node assets are added this needs to be considered here val nodeType = if (nodeModel.isSlack) NodeType.SL else NodeType.PQ + + /* Determine the operating point for this given node */ val nodeIdx = nodeUuidToIndexMap.getOrElse( nodeModel.uuid, throw new RuntimeException( @@ -97,6 +90,7 @@ trait PowerFlowSupport { receivedValuesStore.nodeToReceivedPower .get(nodeModel.uuid) match { case Some(actorRefsWithPower) => + val powerUnit = gridMainRefSystem.nominalPower.getUnit val (p, q) = actorRefsWithPower .map { case (_, powerMsg) => powerMsg } .collect { @@ -113,8 +107,8 @@ trait PowerFlowSupport { } .foldLeft( ( - Quantities.getQuantity(0, mainRefSystemPowerUnit), - Quantities.getQuantity(0, mainRefSystemPowerUnit) + Quantities.getQuantity(0, powerUnit), + Quantities.getQuantity(0, powerUnit) ) ) { case ((pSum, qSum), powerMessage) => (pSum.add(powerMessage.p), qSum.add(powerMessage.q)) @@ -127,8 +121,8 @@ trait PowerFlowSupport { case None => new Complex(0, 0) } - val targetVoltageInPu = - if (targetVoltageFromReceivedData && nodeType == NodeType.SL) { + val targetVoltage = + if (targetVoltageFromReceivedData && nodeModel.isSlack) { /* If the preset voltage is meant to be determined by means of received data and the node is a slack node * (only then there is received data), look it up and transform it */ val receivedSlackVoltage = @@ -148,17 +142,37 @@ trait PowerFlowSupport { gridMainRefSystem ) } else { - /* Either, the received data shall not be considered or the node is not a slack node: Depending on if the - * node's is meant to be neglected or not, return a dummy value. */ - Complex.one * (if (!ignoreTargetVoltage) - nodeModel.vTarget - .to(PowerSystemUnits.PU) - .getValue - .doubleValue() - else 1.0) + // Either the received data shall not be considered or the node is not a slack node + Complex.one * + (if (!ignoreTargetVoltage) + nodeModel.vTarget + .to(PowerSystemUnits.PU) + .getValue + .doubleValue() + else 1.0) } - PresetData(nodeIdx, nodeType, apparentPower, targetVoltageInPu.abs) + val optStateData = Option.when(nodeModel.isSlack)( + StateData( + nodeIdx, + NodeType.SL, + targetVoltage, + apparentPower + ) + ) + + ( + PresetData( + nodeIdx, + nodeType, + apparentPower, + targetVoltage.abs + ), + optStateData + ) + }.unzip match { + case (operatingPoint, stateData) => + (operatingPoint, WithForcedStartVoltages(stateData.flatten)) } } @@ -181,7 +195,8 @@ trait PowerFlowSupport { * instance of [[RefSystem]] of the grid under investigation * @return * current operating point of the grid to be used with - * [[edu.ie3.powerflow.NewtonRaphsonPF.calculate()]] + * [[edu.ie3.powerflow.NewtonRaphsonPF.calculate()]] as well as the complex + * slack node target voltages */ protected def composeOperatingPointWithUpdatedSlackVoltages( receivedSlackValues: ReceivedSlackValues, @@ -189,43 +204,54 @@ trait PowerFlowSupport { transformers2w: Set[TransformerModel], transformers3w: Set[Transformer3wModel], gridMainRefSystem: RefSystem - ): Array[PresetData] = { - sweepDataValues - .map(sweepValueStoreData => { - - val nodeStateData = sweepValueStoreData.stateData - val targetVoltage = if (nodeStateData.nodeType == NodeType.SL) { - val receivedSlackVoltage = receivedSlackValues.values - .map { case (_, slackVoltageMsg) => slackVoltageMsg } - .find(_.nodeUuid == sweepValueStoreData.nodeUuid) - .getOrElse( - throw new RuntimeException( - s"Unable to find node with uuid " + - s"${sweepValueStoreData.nodeUuid} in received slack voltage values!" - ) + ): (Array[PresetData], WithForcedStartVoltages) = + sweepDataValues.map { sweepValueStoreData => + val nodeStateData = sweepValueStoreData.stateData + val targetVoltage = if (nodeStateData.nodeType == NodeType.SL) { + val receivedSlackVoltage = receivedSlackValues.values + .map { case (_, slackVoltageMsg) => slackVoltageMsg } + .find(_.nodeUuid == sweepValueStoreData.nodeUuid) + .getOrElse( + throw new RuntimeException( + s"Unable to find node with uuid " + + s"${sweepValueStoreData.nodeUuid} in received slack voltage values!" ) - - transformVoltage( - receivedSlackVoltage, - sweepValueStoreData.nodeUuid, - transformers2w, - transformers3w, - gridMainRefSystem ) - } else - new Complex(1, 0) - // note: target voltage will be ignored for slack node if provided + transformVoltage( + receivedSlackVoltage, + sweepValueStoreData.nodeUuid, + transformers2w, + transformers3w, + gridMainRefSystem + ) + } else + Complex.one + + // note: target voltage will be ignored for slack node if provided + ( PresetData( nodeStateData.index, nodeStateData.nodeType, nodeStateData.power, targetVoltage.abs + ), + Option.when(nodeStateData.nodeType == NodeType.SL)( + StateData( + nodeStateData.index, + nodeStateData.nodeType, + targetVoltage, + nodeStateData.power + ) ) - }) - .toArray - - } + ) + }.unzip match { + case (operatingPoint, stateData) => + ( + operatingPoint.toArray, + WithForcedStartVoltages(stateData.flatten.toArray) + ) + } /** A debug method that composes a string with voltage information (in p.u.) * from a [[ValidNewtonRaphsonPFResult]] @@ -409,6 +435,8 @@ trait PowerFlowSupport { * Maximum permissible iterations * @param operatingPoint * Current operation point of the grid + * @param slackVoltages + * Complex target voltages of the slack nodes * @param epsilons * Ascending ordered list of convergence thresholds for relaxation * @return @@ -417,7 +445,8 @@ trait PowerFlowSupport { protected final def newtonRaphsonPF( gridModel: GridModel, maxIterations: Int, - operatingPoint: Array[PresetData] + operatingPoint: Array[PresetData], + slackVoltages: WithForcedStartVoltages )(epsilons: Vector[Double]): PowerFlowResult = { epsilons.headOption match { case Some(epsilon) => @@ -426,18 +455,7 @@ trait PowerFlowSupport { gridModel.nodeUuidToIndexMap, gridModel.gridComponents ) - // / add WithForcedVoltageVector for slackNode - // / as we know that there is at least one slack in every grid available here, we can do a direct call on element zero - // // NOTE: currently only the first slack node is taken, needs to be adapted when several slacks are present - val forcedSlackNodeVoltage = - operatingPoint.find(_.nodeType == NodeType.SL) match { - case Some(slackNodeData) => - WithForcedStartVoltages(Array(StateData(slackNodeData))) - case None => - throw new DBFSAlgorithmException( - s"Unable to find a slack node in grid ${gridModel.subnetNo}." - ) - } + // / execute val powerFlow = NewtonRaphsonPF(epsilon, maxIterations, admittanceMatrix) @@ -445,7 +463,7 @@ trait PowerFlowSupport { Try { powerFlow.calculate( operatingPoint, - Some(forcedSlackNodeVoltage) + Some(slackVoltages) ) }.map { case _: PowerFlowResult.FailedPowerFlowResult if epsilons.size > 1 => @@ -456,7 +474,12 @@ trait PowerFlowSupport { epsilon, epsilonsLeft.headOption.getOrElse("") ) - newtonRaphsonPF(gridModel, maxIterations, operatingPoint)( + newtonRaphsonPF( + gridModel, + maxIterations, + operatingPoint, + slackVoltages + )( epsilonsLeft ) case result => diff --git a/src/main/scala/edu/ie3/simona/service/primary/PrimaryServiceProxy.scala b/src/main/scala/edu/ie3/simona/service/primary/PrimaryServiceProxy.scala index e0444514b5..003e5ab512 100644 --- a/src/main/scala/edu/ie3/simona/service/primary/PrimaryServiceProxy.scala +++ b/src/main/scala/edu/ie3/simona/service/primary/PrimaryServiceProxy.scala @@ -8,24 +8,24 @@ package edu.ie3.simona.service.primary import akka.actor.{Actor, ActorRef, PoisonPill, Props} import edu.ie3.datamodel.io.connectors.SqlConnector +import edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation +import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation import edu.ie3.datamodel.io.naming.{ DatabaseNamingStrategy, EntityPersistenceNamingStrategy, FileNamingStrategy } -import edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation -import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation -import edu.ie3.datamodel.io.source.{ - TimeSeriesMappingSource, - TimeSeriesTypeSource -} import edu.ie3.datamodel.io.source.csv.{ CsvTimeSeriesMappingSource, - CsvTimeSeriesTypeSource + CsvTimeSeriesMetaInformationSource } import edu.ie3.datamodel.io.source.sql.{ SqlTimeSeriesMappingSource, - SqlTimeSeriesTypeSource + SqlTimeSeriesMetaInformationSource +} +import edu.ie3.datamodel.io.source.{ + TimeSeriesMappingSource, + TimeSeriesMetaInformationSource } import edu.ie3.datamodel.models.value.Value import edu.ie3.simona.config.SimonaConfig @@ -67,6 +67,7 @@ import java.text.SimpleDateFormat import java.time.ZonedDateTime import java.util.UUID import scala.Option.when +import scala.compat.java8.OptionConverters.RichOptionalGeneric import scala.jdk.CollectionConverters._ import scala.util.{Failure, Success, Try} @@ -148,15 +149,13 @@ case class PrimaryServiceProxy( createSources(primaryConfig).map { case (mappingSource, metaInformationSource) => val modelToTimeSeries = mappingSource.getMapping.asScala.toMap - val timeSeriesMetaInformation = - metaInformationSource.getTimeSeriesMetaInformation.asScala.toMap - val timeSeriesToSourceRef = modelToTimeSeries.values .to(LazyList) .distinct .flatMap { timeSeriesUuid => - timeSeriesMetaInformation - .get(timeSeriesUuid) match { + metaInformationSource + .getTimeSeriesMetaInformation(timeSeriesUuid) + .asScala match { case Some(metaInformation) => /* Only register those entries, that meet the supported column schemes */ when( @@ -186,7 +185,7 @@ case class PrimaryServiceProxy( private def createSources( primaryConfig: PrimaryConfig - ): Try[(TimeSeriesMappingSource, TimeSeriesTypeSource)] = { + ): Try[(TimeSeriesMappingSource, TimeSeriesMetaInformationSource)] = { Seq( primaryConfig.sqlParams, primaryConfig.influxDb1xParams, @@ -201,7 +200,7 @@ case class PrimaryServiceProxy( directoryPath, fileNamingStrategy ), - new CsvTimeSeriesTypeSource( + new CsvTimeSeriesMetaInformationSource( csvSep, directoryPath, fileNamingStrategy @@ -219,7 +218,7 @@ case class PrimaryServiceProxy( sqlParams.schemaName, new EntityPersistenceNamingStrategy() ), - new SqlTimeSeriesTypeSource( + new SqlTimeSeriesMetaInformationSource( sqlConnector, sqlParams.schemaName, new DatabaseNamingStrategy() diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala index cd625a216a..9d7cbb0723 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala @@ -45,7 +45,7 @@ import edu.ie3.simona.util.TickUtil import edu.ie3.simona.util.TickUtil.TickLong import edu.ie3.util.exceptions.EmptyQuantityException import edu.ie3.util.interval.ClosedInterval -import edu.ie3.util.scala.DoubleUtils.ImplicitDouble +import edu.ie3.util.DoubleUtils.ImplicitDouble import tech.units.indriya.quantity.Quantities import tech.units.indriya.unit.Units diff --git a/src/main/scala/edu/ie3/simona/util/ConfigUtil.scala b/src/main/scala/edu/ie3/simona/util/ConfigUtil.scala index ceef9abbdd..37c0abdd8d 100644 --- a/src/main/scala/edu/ie3/simona/util/ConfigUtil.scala +++ b/src/main/scala/edu/ie3/simona/util/ConfigUtil.scala @@ -12,8 +12,6 @@ import edu.ie3.datamodel.io.connectors.{ InfluxDbConnector, SqlConnector } - -import java.util.{Properties, UUID} import edu.ie3.datamodel.models.result.connector.{ LineResult, SwitchResult, @@ -30,91 +28,43 @@ import org.apache.kafka.common.KafkaException import java.io.File import java.util.concurrent.ExecutionException +import java.util.{Properties, UUID} import scala.collection.mutable import scala.jdk.CollectionConverters._ +import scala.reflect.ClassTag import scala.util.{Failure, Success, Try, Using} object ConfigUtil { final case class ParticipantConfigUtil private ( private val configs: Map[UUID, SimonaConfig.BaseRuntimeConfig], - private val defaultLoadConfig: LoadRuntimeConfig, - private val defaultFixedFeedInConfig: FixedFeedInRuntimeConfig, - private val defaultPvConfig: PvRuntimeConfig, - private val defaultWecConfig: WecRuntimeConfig, - private val defaultEvcsConfig: EvcsRuntimeConfig + private val defaultConfigs: Map[Class[_], BaseRuntimeConfig] ) { - /** Queries for a [[LoadRuntimeConfig]], that applies for the given uuid and - * either returns the config for the requested uuid or the default config. - * If the requested uuid is valid, but the return type is not of type - * [[LoadRuntimeConfig]] the default config for this type is returned. - * - * @param uuid - * Identifier of the requested load model - * @return - * the requested [[LoadRuntimeConfig]] or a default value - */ - def getLoadConfigOrDefault(uuid: UUID): LoadRuntimeConfig = - configs.get(uuid) match { - case Some(loadConfig: LoadRuntimeConfig) => loadConfig - case _ => defaultLoadConfig - } - - /** Queries for a [[PvRuntimeConfig]], that applies for the given uuid and - * either returns the config for the requested uuid or the default config. - * If the requested uuid is valid, but the return type is not of type - * [[PvRuntimeConfig]] the default config for this type is returned. + /** Queries for a [[BaseRuntimeConfig]] of type [[T]], that applies for the + * given uuid and either returns the config for the requested uuid or the + * default config for type [[T]]. * * @param uuid * Identifier of the requested load model * @return - * the requested [[PvRuntimeConfig]] or a default value + * the requested config or a default value of type [[T]] */ - def getPvConfigOrDefault(uuid: UUID): PvRuntimeConfig = + def getOrDefault[T <: BaseRuntimeConfig]( + uuid: UUID + )(implicit tag: ClassTag[T]): T = configs.get(uuid) match { - case Some(pvRuntimeConfig: PvRuntimeConfig) => pvRuntimeConfig - case _ => defaultPvConfig - } - - def getWecConfigOrDefault(uuid: UUID): WecRuntimeConfig = - configs.get(uuid) match { - case Some(wecRuntimeConfig: WecRuntimeConfig) => wecRuntimeConfig - case _ => defaultWecConfig - } - - /** Queries for a [[FixedFeedInRuntimeConfig]], that applies for the given - * uuid and either returns the config for the requested uuid or the default - * config. If the requested uuid is valid, but the return type is not of - * type [[FixedFeedInRuntimeConfig]] the default config for this type is - * returned. - * - * @param uuid - * Identifier of the requested fixed feed in model - * @return - * the requested [[FixedFeedInRuntimeConfig]] or a default value - */ - def getFixedFeedConfigOrDefault(uuid: UUID): FixedFeedInRuntimeConfig = - configs.get(uuid) match { - case Some(ffinConfig: FixedFeedInRuntimeConfig) => ffinConfig - case _ => defaultFixedFeedInConfig + case Some(conf: T) => conf + case _ => + defaultConfigs.get(tag.runtimeClass) match { + case Some(conf: T) => conf + case _ => + throw new RuntimeException( + s"No config found for $uuid of type ${tag.runtimeClass.getSimpleName}." + ) + } } - /** Queries for a [[EvcsRuntimeConfig]], that applies for the given uuid and - * either returns the config for the requested uuid or the default config. - * If the requested uuid is valid, but the return type is not of type - * [[EvcsRuntimeConfig]] the default config for this type is returned. - * - * @param uuid - * Identifier of the requested Evcs model - * @return - * the requested [[EvcsRuntimeConfig]] or a default value - */ - def getEvcsConfigOrDefault(uuid: UUID): EvcsRuntimeConfig = - configs.get(uuid) match { - case Some(evcsConfig: EvcsRuntimeConfig) => evcsConfig - case _ => defaultEvcsConfig - } } object ParticipantConfigUtil { @@ -131,24 +81,28 @@ object ConfigUtil { def apply( subConfig: SimonaConfig.Simona.Runtime.Participant ): ParticipantConfigUtil = { - new ParticipantConfigUtil( + ParticipantConfigUtil( buildUuidMapping( - subConfig.load.individualConfigs ++ - subConfig.fixedFeedIn.individualConfigs ++ - subConfig.pv.individualConfigs ++ - subConfig.evcs.individualConfigs ++ + Seq( + subConfig.load.individualConfigs, + subConfig.fixedFeedIn.individualConfigs, + subConfig.pv.individualConfigs, + subConfig.evcs.individualConfigs, subConfig.wec.individualConfigs + ).reduceOption(_ ++ _).getOrElse(Seq.empty) ), - subConfig.load.defaultConfig, - subConfig.fixedFeedIn.defaultConfig, - subConfig.pv.defaultConfig, - subConfig.wec.defaultConfig, - subConfig.evcs.defaultConfig + Seq( + subConfig.load.defaultConfig, + subConfig.fixedFeedIn.defaultConfig, + subConfig.pv.defaultConfig, + subConfig.evcs.defaultConfig, + subConfig.wec.defaultConfig + ).map { conf => conf.getClass -> conf }.toMap ) } private def buildUuidMapping( - configs: List[BaseRuntimeConfig] + configs: Seq[BaseRuntimeConfig] ): Map[UUID, BaseRuntimeConfig] = configs .flatMap(modelConfig => @@ -480,33 +434,31 @@ object ConfigUtil { properties.put("bootstrap.servers", kafkaParams.bootstrapServers) properties.put("default.api.timeout.ms", 2000) properties.put("request.timeout.ms", 1000) - try { - Using(AdminClient.create(properties)) { client => - val existingTopics = client.listTopics.names().get().asScala - topics.filterNot(existingTopics.contains) - } match { - case Failure(ke: KafkaException) => - throw new InvalidConfigParameterException( - s"Exception creating kafka client for broker ${kafkaParams.bootstrapServers}.", - ke - ) - case Failure(ee: ExecutionException) => - throw new InvalidConfigParameterException( - s"Connection with kafka broker ${kafkaParams.bootstrapServers} failed.", - ee - ) - case Failure(other) => - throw new InvalidConfigParameterException( - s"Checking kafka config failed with unexpected exception.", - other - ) - case Success(missingTopics) if missingTopics.nonEmpty => - throw new InvalidConfigParameterException( - s"Required kafka topics {${missingTopics.mkString}} do not exist." - ) - case Success(_) => - // testing connection succeeded, do nothing - } + Using(AdminClient.create(properties)) { client => + val existingTopics = client.listTopics.names().get().asScala + topics.filterNot(existingTopics.contains) + } match { + case Failure(ke: KafkaException) => + throw new InvalidConfigParameterException( + s"Exception creating kafka client for broker ${kafkaParams.bootstrapServers}.", + ke + ) + case Failure(ee: ExecutionException) => + throw new InvalidConfigParameterException( + s"Connection with kafka broker ${kafkaParams.bootstrapServers} failed.", + ee + ) + case Failure(other) => + throw new InvalidConfigParameterException( + s"Checking kafka config failed with unexpected exception.", + other + ) + case Success(missingTopics) if missingTopics.nonEmpty => + throw new InvalidConfigParameterException( + s"Required kafka topics {${missingTopics.mkString}} do not exist." + ) + case Success(_) => + // testing connection succeeded, do nothing } } } 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 ef344b6642..d805ff2488 100644 --- a/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/grid/DBFSAlgorithmCenGridSpec.scala @@ -372,8 +372,8 @@ class DBFSAlgorithmCenGridSpec secondSlackAskSender ! ProvideSlackVoltageMessage( secondSweepNo, slackRequestNodeUuid, - Quantities.getQuantity(380, KILOVOLT), - Quantities.getQuantity(0, KILOVOLT) + Quantities.getQuantity(374.22694614463, KILOVOLT), // 380 kV @ 10° + Quantities.getQuantity(65.9863075134335, KILOVOLT) // 380 kV @ 10° ) // after the intermediate power flow calculation @@ -408,7 +408,7 @@ 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 4 inferior grid agents inferiorGridNodeUuids.foreach { nodeUuid => - centerGridAgent ! RequestSlackVoltageMessage(firstSweepNo, nodeUuid) + centerGridAgent ! RequestSlackVoltageMessage(secondSweepNo, nodeUuid) } // as we are in the second sweep, all provided slack voltages should be unequal @@ -426,28 +426,28 @@ class DBFSAlgorithmCenGridSpec secondProvidedSlackVoltages.size shouldBe 4 val secondExpectedResults = List( ProvideSlackVoltageMessage( - firstSweepNo, + secondSweepNo, UUID.fromString("d44ba8ed-81db-4a22-a40d-f7c0d0808a75"), - Quantities.getQuantity(110.1277081582144170, KILOVOLT), - Quantities.getQuantity(-0.011124597905979507, KILOVOLT) + Quantities.getQuantity(108.4565525820633120, KILOVOLT), + Quantities.getQuantity(19.11252024208434820, KILOVOLT) ), ProvideSlackVoltageMessage( - firstSweepNo, + secondSweepNo, UUID.fromString("e364ef00-e6ca-46b1-ba2b-bb73c0c6fee0"), - Quantities.getQuantity(110.1422124824355620, KILOVOLT), - Quantities.getQuantity(-0.014094294956794604, KILOVOLT) + Quantities.getQuantity(108.4713522355223970, KILOVOLT), + Quantities.getQuantity(19.11211431087968570, KILOVOLT) ), ProvideSlackVoltageMessage( - firstSweepNo, + secondSweepNo, UUID.fromString("78c5d473-e01b-44c4-afd2-e4ff3c4a5d7c"), - Quantities.getQuantity(110.1196117051188620, KILOVOLT), - Quantities.getQuantity(-0.009318349620959118, KILOVOLT) + Quantities.getQuantity(108.4482654805414590, KILOVOLT), + Quantities.getQuantity(19.11289311507043710, KILOVOLT) ), ProvideSlackVoltageMessage( - firstSweepNo, + secondSweepNo, UUID.fromString("47ef9983-8fcf-4713-be90-093fc27864ae"), - Quantities.getQuantity(110.147346134387320, KILOVOLT), - Quantities.getQuantity(-0.015819259689252657, KILOVOLT) + Quantities.getQuantity(108.4767074327598750, KILOVOLT), + Quantities.getQuantity(19.11130700154577660, KILOVOLT) ) ) @@ -524,11 +524,11 @@ class DBFSAlgorithmCenGridSpec case ProvideGridPowerMessage(nodeUuid, p, q) => nodeUuid shouldBe slackNodeUuid p should equalWithTolerance( - Quantities.getQuantity(0.080423711881452700000, MEGAVOLTAMPERE), + Quantities.getQuantity(0.08042371202897453, MEGAVOLTAMPERE), floatPrecision ) q should equalWithTolerance( - Quantities.getQuantity(-1.45357503915621860000, MEGAVOLTAMPERE), + Quantities.getQuantity(-1.4535750374419432, MEGAVOLTAMPERE), floatPrecision ) case x => diff --git a/src/test/scala/edu/ie3/simona/agent/participant/FixedFeedInAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/FixedFeedInAgentModelCalculationSpec.scala index 66f28b4c41..a6e44bef27 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/FixedFeedInAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/FixedFeedInAgentModelCalculationSpec.scala @@ -99,9 +99,10 @@ class FixedFeedInAgentModelCalculationSpec private val fixedFeedConfigUtil = ConfigUtil.ParticipantConfigUtil( simonaConfig.simona.runtime.participant ) - private val modelConfig = fixedFeedConfigUtil.getFixedFeedConfigOrDefault( - voltageSensitiveInput.getUuid - ) + private val modelConfig = + fixedFeedConfigUtil.getOrDefault[FixedFeedInRuntimeConfig]( + voltageSensitiveInput.getUuid + ) private val services = None private val resolution = simonaConfig.simona.powerflow.resolution.getSeconds diff --git a/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentFixedModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentFixedModelCalculationSpec.scala index 3af3a4cc79..9e2891941f 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentFixedModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentFixedModelCalculationSpec.scala @@ -87,9 +87,10 @@ class LoadAgentFixedModelCalculationSpec private val loadConfigUtil = ConfigUtil.ParticipantConfigUtil( simonaConfig.simona.runtime.participant ) - private val modelConfig = loadConfigUtil.getLoadConfigOrDefault( - voltageSensitiveInput.getUuid - ) + private val modelConfig = + loadConfigUtil.getOrDefault[LoadRuntimeConfig]( + voltageSensitiveInput.getUuid + ) private val services = None private val resolution = simonaConfig.simona.powerflow.resolution.getSeconds diff --git a/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentProfileModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentProfileModelCalculationSpec.scala index f6c3cd2748..da24d2f8c9 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentProfileModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/LoadAgentProfileModelCalculationSpec.scala @@ -87,9 +87,10 @@ class LoadAgentProfileModelCalculationSpec private val loadConfigUtil = ConfigUtil.ParticipantConfigUtil( simonaConfig.simona.runtime.participant ) - private val modelConfig = loadConfigUtil.getLoadConfigOrDefault( - voltageSensitiveInput.getUuid - ) + private val modelConfig = + loadConfigUtil.getOrDefault[LoadRuntimeConfig]( + voltageSensitiveInput.getUuid + ) private val services = None private val resolution = simonaConfig.simona.powerflow.resolution.getSeconds diff --git a/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala index 39edbf6921..a9037e8aca 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala @@ -113,7 +113,7 @@ class PVAgentModelCalculationSpec private val configUtil = ConfigUtil.ParticipantConfigUtil( simonaConfig.simona.runtime.participant ) - private val modelConfig = configUtil.getPvConfigOrDefault( + private val modelConfig = configUtil.getOrDefault[PvRuntimeConfig]( voltageSensitiveInput.getUuid ) private val noServices = None diff --git a/src/test/scala/edu/ie3/simona/agent/participant/WecAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/WecAgentModelCalculationSpec.scala index 9b284a2cba..4c88f0274b 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/WecAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/WecAgentModelCalculationSpec.scala @@ -117,7 +117,9 @@ class WecAgentModelCalculationSpec simonaConfig.simona.runtime.participant ) private val modelConfig = - configUtil.getWecConfigOrDefault(voltageSensitiveInput.getUuid) + configUtil.getOrDefault[WecRuntimeConfig]( + voltageSensitiveInput.getUuid + ) private val withServices = Some( Vector(ActorWeatherService(weatherService.ref)) diff --git a/src/test/scala/edu/ie3/simona/model/assets/control/QControlSpec.scala b/src/test/scala/edu/ie3/simona/model/assets/control/QControlSpec.scala index fcd76be9b9..63a6eee22d 100644 --- a/src/test/scala/edu/ie3/simona/model/assets/control/QControlSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/assets/control/QControlSpec.scala @@ -71,7 +71,7 @@ class QControlSpec extends UnitSpec with TableDrivenPropertyChecks { ) intercept[QControlException]( QControl(invalidInput) - ).getMessage shouldBe "Got an invalid definition of fixed power factor: cosPhiFixed{points=[CharacteristicCoordinate{x=1 PU, y=2 PU}, CharacteristicCoordinate{x=3 PU, y=4 PU}]}. It may only contain one coordinate" + ).getMessage shouldBe "Got an invalid definition of fixed power factor: cosPhiFixed{points=[CharacteristicCoordinate{x=1 p.u., y=2 p.u.}, CharacteristicCoordinate{x=3 p.u., y=4 p.u.}]}. It may only contain one coordinate" } "parse a valid CosPhiFixed correctly" in { diff --git a/src/test/scala/edu/ie3/simona/model/participant/FixedFeedInModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/FixedFeedInModelSpec.scala index 79a6e02890..fed5968bd6 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/FixedFeedInModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/FixedFeedInModelSpec.scala @@ -7,6 +7,7 @@ package edu.ie3.simona.model.participant import edu.ie3.simona.config.SimonaConfig +import edu.ie3.simona.config.SimonaConfig.FixedFeedInRuntimeConfig import edu.ie3.simona.model.participant.control.QControl import edu.ie3.simona.model.participant.load.{LoadModelBehaviour, LoadReference} import edu.ie3.simona.test.common.input.FixedFeedInputTestData @@ -39,7 +40,7 @@ class FixedFeedInModelSpec .ParticipantConfigUtil( simonaConfig.simona.runtime.participant ) - .getFixedFeedConfigOrDefault(fixedFeedInput.getUuid) + .getOrDefault[FixedFeedInRuntimeConfig](fixedFeedInput.getUuid) val actualModel = FixedFeedInModel.apply( fixedFeedInput, diff --git a/src/test/scala/edu/ie3/simona/service/ev/ExtEvDataServiceSpec.scala b/src/test/scala/edu/ie3/simona/service/ev/ExtEvDataServiceSpec.scala index 5d844053f2..63a1ec44fd 100644 --- a/src/test/scala/edu/ie3/simona/service/ev/ExtEvDataServiceSpec.scala +++ b/src/test/scala/edu/ie3/simona/service/ev/ExtEvDataServiceSpec.scala @@ -741,7 +741,7 @@ class ExtEvDataServiceSpec extData.receiveTriggerQueue.size() shouldBe 1 // only evcs 1 should be included, the other one is full extData.receiveTriggerQueue.take() shouldBe new ProvideEvcsFreeLots( - Map(evcs1UUID -> new Integer(2)).asJava + Map(evcs1UUID -> Integer.valueOf(2)).asJava ) } diff --git a/src/test/scala/edu/ie3/simona/test/common/input/EvcsInputTestData.scala b/src/test/scala/edu/ie3/simona/test/common/input/EvcsInputTestData.scala index c64f3f0f2b..a726e074b9 100644 --- a/src/test/scala/edu/ie3/simona/test/common/input/EvcsInputTestData.scala +++ b/src/test/scala/edu/ie3/simona/test/common/input/EvcsInputTestData.scala @@ -56,7 +56,7 @@ trait EvcsInputTestData extends DefaultTestData with NodeInputTestData { ) protected val modelConfig: SimonaConfig.EvcsRuntimeConfig = - configUtil.getEvcsConfigOrDefault( + configUtil.getOrDefault[SimonaConfig.EvcsRuntimeConfig]( evcsInputModel.getUuid ) diff --git a/src/test/scala/edu/ie3/simona/test/common/input/TimeSeriesTestData.scala b/src/test/scala/edu/ie3/simona/test/common/input/TimeSeriesTestData.scala index 64d674e3ad..492a3124d9 100644 --- a/src/test/scala/edu/ie3/simona/test/common/input/TimeSeriesTestData.scala +++ b/src/test/scala/edu/ie3/simona/test/common/input/TimeSeriesTestData.scala @@ -6,10 +6,8 @@ package edu.ie3.simona.test.common.input -import edu.ie3.datamodel.io.naming.timeseries.{ - ColumnScheme, - IndividualTimeSeriesMetaInformation -} +import edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation +import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme import java.util.UUID @@ -21,19 +19,22 @@ trait TimeSeriesTestData { protected val uuidPqh: UUID = UUID.fromString("46be1e57-e4ed-4ef7-95f1-b2b321cb2047") - protected val metaP: IndividualTimeSeriesMetaInformation = - new IndividualTimeSeriesMetaInformation( + protected val metaP: CsvIndividualTimeSeriesMetaInformation = + new CsvIndividualTimeSeriesMetaInformation( uuidP, - ColumnScheme.ACTIVE_POWER + ColumnScheme.ACTIVE_POWER, + s"its_p_$uuidP" ) - protected val metaPq: IndividualTimeSeriesMetaInformation = - new IndividualTimeSeriesMetaInformation( + protected val metaPq: CsvIndividualTimeSeriesMetaInformation = + new CsvIndividualTimeSeriesMetaInformation( uuidPq, - ColumnScheme.APPARENT_POWER + ColumnScheme.APPARENT_POWER, + s"its_pq_$uuidPq" ) - protected val metaPqh: IndividualTimeSeriesMetaInformation = - new IndividualTimeSeriesMetaInformation( + protected val metaPqh: CsvIndividualTimeSeriesMetaInformation = + new CsvIndividualTimeSeriesMetaInformation( uuidPqh, - ColumnScheme.APPARENT_POWER_AND_HEAT_DEMAND + ColumnScheme.APPARENT_POWER_AND_HEAT_DEMAND, + s"its_pqh_$uuidPqh" ) } diff --git a/src/test/scala/edu/ie3/simona/util/ConfigUtilSpec.scala b/src/test/scala/edu/ie3/simona/util/ConfigUtilSpec.scala index bec0818021..27f0595e69 100644 --- a/src/test/scala/edu/ie3/simona/util/ConfigUtilSpec.scala +++ b/src/test/scala/edu/ie3/simona/util/ConfigUtilSpec.scala @@ -56,27 +56,30 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(configs, defaultLoadConfig, _, _, _, _) => - configs shouldBe Map.empty[UUID, SimonaConfig.LoadRuntimeConfig] - inside(defaultLoadConfig) { - case LoadRuntimeConfig( + inside(actual) { case ParticipantConfigUtil(configs, defaultConfigs) => + configs shouldBe Map.empty[UUID, SimonaConfig.LoadRuntimeConfig] + defaultConfigs.size shouldBe 5 + + inside(defaultConfigs.get(classOf[LoadRuntimeConfig])) { + case Some( + LoadRuntimeConfig( calculateMissingReactivePowerWithModel, scaling, uuids, modelBehaviour, reference - ) => - calculateMissingReactivePowerWithModel shouldBe false - modelBehaviour shouldBe "fix" - reference shouldBe "power" - scaling shouldBe 1.0 - uuids shouldBe List("default") - } - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + ) + ) => + calculateMissingReactivePowerWithModel shouldBe false + modelBehaviour shouldBe "fix" + reference shouldBe "power" + scaling shouldBe 1.0 + uuids shouldBe List("default") + case unexpected => + fail( + s"Expected a default $LoadRuntimeConfig. I got '$unexpected" + ) + } } } @@ -109,16 +112,33 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(configs, _, _, _, _, _) => - configs.size shouldBe 1 - configs.contains( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + inside(actual) { case ParticipantConfigUtil(configs, defaultConfigs) => + configs.size shouldBe 1 + configs.contains( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) + + defaultConfigs.size shouldBe 5 + inside(defaultConfigs.get(classOf[LoadRuntimeConfig])) { + case Some( + LoadRuntimeConfig( + calculateMissingReactivePowerWithModel, + scaling, + uuids, + modelBehaviour, + reference + ) + ) => + calculateMissingReactivePowerWithModel shouldBe false + modelBehaviour shouldBe "profile" + reference shouldBe "power" + scaling shouldBe 1.3 + uuids shouldBe List("default") + case unexpected => + fail( + s"Expected a default $LoadRuntimeConfig. I got '$unexpected" + ) + } } } @@ -151,25 +171,21 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(configs, _, _, _, _, _) => - configs.size shouldBe 2 - configs.contains( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) - configs.contains( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) - actual.getLoadConfigOrDefault( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) shouldBe actual.getLoadConfigOrDefault( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + inside(actual) { case ParticipantConfigUtil(configs, _) => + configs.size shouldBe 2 + configs.contains( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) + configs.contains( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) } + + actual.getOrDefault[LoadRuntimeConfig]( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) shouldBe actual.getOrDefault[LoadRuntimeConfig]( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) } "setup on multiple correct load input configs correctly" in { @@ -208,40 +224,36 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(configs, _, _, _, _, _) => - configs.size shouldBe 2 - configs.contains( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) - configs.contains( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) - actual.getLoadConfigOrDefault( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) shouldBe - LoadRuntimeConfig( - calculateMissingReactivePowerWithModel = false, - 1.3, - List("49f250fa-41ff-4434-a083-79c98d260a76"), - "profile", - "power" - ) - actual.getLoadConfigOrDefault( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) shouldBe - LoadRuntimeConfig( - calculateMissingReactivePowerWithModel = false, - 1.5, - List("fb8f1443-1843-4ecd-a94a-59be8148397f"), - "random", - "energy" - ) - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + inside(actual) { case ParticipantConfigUtil(configs, _) => + configs.size shouldBe 2 + configs.contains( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) + configs.contains( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) } + + actual.getOrDefault[LoadRuntimeConfig]( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) shouldBe + LoadRuntimeConfig( + calculateMissingReactivePowerWithModel = false, + 1.3, + List("49f250fa-41ff-4434-a083-79c98d260a76"), + "profile", + "power" + ) + actual.getOrDefault[LoadRuntimeConfig]( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) shouldBe + LoadRuntimeConfig( + calculateMissingReactivePowerWithModel = false, + 1.5, + List("fb8f1443-1843-4ecd-a94a-59be8148397f"), + "random", + "energy" + ) } } @@ -265,31 +277,26 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil( - configs, - _, - defaultFixedFeedInConfig, - _, - _, - _ - ) => - configs shouldBe Map - .empty[UUID, SimonaConfig.FixedFeedInRuntimeConfig] - inside(defaultFixedFeedInConfig) { - case FixedFeedInRuntimeConfig( + inside(actual) { case ParticipantConfigUtil(configs, defaultConfigs) => + configs shouldBe Map + .empty[UUID, SimonaConfig.FixedFeedInRuntimeConfig] + + inside(defaultConfigs.get(classOf[FixedFeedInRuntimeConfig])) { + case Some( + FixedFeedInRuntimeConfig( calculateMissingReactivePowerWithModel, scaling, uuids - ) => - calculateMissingReactivePowerWithModel shouldBe false - scaling shouldBe 1.0 - uuids shouldBe List("default") - } - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + ) + ) => + calculateMissingReactivePowerWithModel shouldBe false + scaling shouldBe 1.0 + uuids shouldBe List("default") + case unexpected => + fail( + s"Expected a default $FixedFeedInRuntimeConfig. I got '$unexpected" + ) + } } } @@ -318,16 +325,29 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(fixedFeedInConfigs, _, _, _, _, _) => - fixedFeedInConfigs.size shouldBe 1 - fixedFeedInConfigs.contains( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + inside(actual) { case ParticipantConfigUtil(configs, defaultConfigs) => + configs.size shouldBe 1 + configs.contains( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) + + defaultConfigs.size shouldBe 5 + inside(defaultConfigs.get(classOf[FixedFeedInRuntimeConfig])) { + case Some( + FixedFeedInRuntimeConfig( + calculateMissingReactivePowerWithModel, + scaling, + uuids + ) + ) => + calculateMissingReactivePowerWithModel shouldBe false + scaling shouldBe 1.3 + uuids shouldBe List("default") + case unexpected => + fail( + s"Expected a default $FixedFeedInRuntimeConfig. I got '$unexpected" + ) + } } } @@ -356,24 +376,20 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(fixedFeedInConfigs, _, _, _, _, _) => - fixedFeedInConfigs.size shouldBe 2 - fixedFeedInConfigs.contains( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) - fixedFeedInConfigs.contains( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) - actual.getFixedFeedConfigOrDefault( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) shouldBe actual.getFixedFeedConfigOrDefault( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + inside(actual) { case ParticipantConfigUtil(configs, _) => + configs.size shouldBe 2 + configs.contains( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) + configs.contains( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) + + actual.getOrDefault[FixedFeedInRuntimeConfig]( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) shouldBe actual.getOrDefault[FixedFeedInRuntimeConfig]( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) } } @@ -407,36 +423,32 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(fixedFeedInConfigs, _, _, _, _, _) => - fixedFeedInConfigs.size shouldBe 2 - fixedFeedInConfigs.contains( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) - fixedFeedInConfigs.contains( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) - actual.getFixedFeedConfigOrDefault( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) shouldBe - FixedFeedInRuntimeConfig( - calculateMissingReactivePowerWithModel = false, - 1.3, - List("49f250fa-41ff-4434-a083-79c98d260a76") - ) - actual.getFixedFeedConfigOrDefault( - UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) shouldBe - FixedFeedInRuntimeConfig( - calculateMissingReactivePowerWithModel = false, - 1.5, - List("fb8f1443-1843-4ecd-a94a-59be8148397f") - ) - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) + inside(actual) { case ParticipantConfigUtil(configs, _) => + configs.size shouldBe 2 + configs.contains( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) + configs.contains( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) } + + actual.getOrDefault[FixedFeedInRuntimeConfig]( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) shouldBe + FixedFeedInRuntimeConfig( + calculateMissingReactivePowerWithModel = false, + 1.3, + List("49f250fa-41ff-4434-a083-79c98d260a76") + ) + actual.getOrDefault[FixedFeedInRuntimeConfig]( + UUID.fromString("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) shouldBe + FixedFeedInRuntimeConfig( + calculateMissingReactivePowerWithModel = false, + 1.5, + List("fb8f1443-1843-4ecd-a94a-59be8148397f") + ) } } @@ -515,46 +527,41 @@ class ConfigUtilSpec simonaConfig.simona.runtime.participant ) - inside(actual) { - case ParticipantConfigUtil(configs, _, _, _, _, _) => - configs.size shouldBe 4 - // return default if a request for fix feed is done, but a load config is found - actual.getFixedFeedConfigOrDefault( - UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") - ) shouldBe - FixedFeedInRuntimeConfig( - calculateMissingReactivePowerWithModel = false, - 1.0, - List("default") - ) + inside(actual) { case ParticipantConfigUtil(configs, _) => + configs.size shouldBe 4 + } - // return default if a request for load is done, but fixed feed is found - actual.getLoadConfigOrDefault( - UUID.fromString("50f250fa-41ff-4434-a083-79c98d260a76") - ) shouldBe - LoadRuntimeConfig( - calculateMissingReactivePowerWithModel = false, - 1.0, - List("default"), - "profile", - "power" - ) + // return default if a request for fix feed is done, but a load config is found + actual.getOrDefault[FixedFeedInRuntimeConfig]( + UUID.fromString("49f250fa-41ff-4434-a083-79c98d260a76") + ) shouldBe + FixedFeedInRuntimeConfig( + calculateMissingReactivePowerWithModel = false, + 1.0, + List("default") + ) - // return default if a request for pv is done, but fixed feed is found - actual.getPvConfigOrDefault( - UUID.fromString("50f250fa-41ff-4434-a083-79c98d260a76") - ) shouldBe - PvRuntimeConfig( - calculateMissingReactivePowerWithModel = false, - 1.0, - List("default") - ) + // return default if a request for load is done, but fixed feed is found + actual.getOrDefault[LoadRuntimeConfig]( + UUID.fromString("50f250fa-41ff-4434-a083-79c98d260a76") + ) shouldBe + LoadRuntimeConfig( + calculateMissingReactivePowerWithModel = false, + 1.0, + List("default"), + "profile", + "power" + ) - case unexpected => - fail( - s"The input is supposed to be converted to ${ParticipantConfigUtil.getClass.getSimpleName}. I got '$unexpected" - ) - } + // return default if a request for pv is done, but fixed feed is found + actual.getOrDefault[PvRuntimeConfig]( + UUID.fromString("50f250fa-41ff-4434-a083-79c98d260a76") + ) shouldBe + PvRuntimeConfig( + calculateMissingReactivePowerWithModel = false, + 1.0, + List("default") + ) } }