diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a7f37e5..d007c967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,12 @@ All notable changes to this project will be documented in this file. 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] - ## [1.0.0] - 2021-08-03 ### Added - Basic functionality to convert SimBench data sets to [PowerSystemDataModel](https://github.com/ie3-institute/powersystemdatamodel) +## [Unreleased] +### Changed +- Line type can be mapped to more than one vRated voltage. [Unreleased]: https://github.com/ie3-institute/simbench2psdm/compare/v1.0...HEAD [1.0.0]: https://github.com/ie3-institute/simbench2psdm/releases/tag/1.0 diff --git a/src/main/scala/edu/ie3/simbench/convert/LineConverter.scala b/src/main/scala/edu/ie3/simbench/convert/LineConverter.scala index 1bbef7af..9163993f 100644 --- a/src/main/scala/edu/ie3/simbench/convert/LineConverter.scala +++ b/src/main/scala/edu/ie3/simbench/convert/LineConverter.scala @@ -12,7 +12,9 @@ import edu.ie3.datamodel.utils.GridAndGeoUtils import edu.ie3.simbench.exception.ConversionException import edu.ie3.simbench.model.datamodel.types.LineType import edu.ie3.simbench.model.datamodel.{Line, Node} -import edu.ie3.util.quantities.PowerSystemUnits.KILOMETRE +import edu.ie3.util.quantities.PowerSystemUnits.{KILOMETRE, KILOVOLT} +import javax.measure.quantity.ElectricPotential +import tech.units.indriya.ComparableQuantity import tech.units.indriya.quantity.Quantities import scala.collection.parallel.CollectionConverters._ @@ -29,15 +31,21 @@ case object LineConverter extends LazyLogging { */ def convert( inputs: Vector[Line[_ <: LineType]], - types: Map[LineType, LineTypeInput], + types: Map[ + (LineType, ComparableQuantity[ElectricPotential]), + LineTypeInput + ], nodes: Map[Node, NodeInput] ): Vector[LineInput] = inputs.par.flatMap { case acLine: Line.ACLine => val (nodeA, nodeB) = NodeConverter.getNodes(acLine.nodeA, acLine.nodeB, nodes) + /** + * This part of the code works only if no calculations are done with the voltage provided here. + */ val lineType = types.getOrElse( - acLine.lineType, + (acLine.lineType, Quantities.getQuantity(acLine.nodeA.vmR, KILOVOLT)), throw ConversionException( s"Cannot find conversion result for line type ${acLine.lineType.id}" ) diff --git a/src/main/scala/edu/ie3/simbench/convert/types/LineTypeConverter.scala b/src/main/scala/edu/ie3/simbench/convert/types/LineTypeConverter.scala index fc7caf53..9e7ba0c2 100644 --- a/src/main/scala/edu/ie3/simbench/convert/types/LineTypeConverter.scala +++ b/src/main/scala/edu/ie3/simbench/convert/types/LineTypeConverter.scala @@ -33,24 +33,14 @@ case object LineTypeConverter extends LazyLogging { */ def convert( lines: Vector[Line[_ <: LineType]] - ): Map[LineType, LineTypeInput] = { - val ratedVoltageMapping = getRatedVoltages(lines) - val lineTypes = lines.map(line => line.lineType).distinct - - lineTypes - .map( - lineType => - lineType -> convert( - lineType, - ratedVoltageMapping.getOrElse( - lineType, - throw SimbenchDataModelException( - s"Cannot find the rated voltage vor line type ${lineType}" - ) - ) - ) - ) - .toMap + ): Map[(LineType, ComparableQuantity[ElectricPotential]), LineTypeInput] = { + assignRatedVoltages(lines).map { + case pair @ (lineType, vRated) => + pair -> convert( + lineType, + vRated + ) + }.toMap } /** @@ -91,42 +81,10 @@ case object LineTypeConverter extends LazyLogging { * @param lines [[Vector]] of [[Line]]s * @return Mapping of [[LineType]] to [[ComparableQuantity]] of type [[ElectricPotential]] */ - def getRatedVoltages( + def assignRatedVoltages( lines: Vector[Line[_ <: LineType]] - ): Map[LineType, ComparableQuantity[ElectricPotential]] = { - val rawMapping = lines - .distinctBy(line => line.lineType) - .map(line => determineRatedVoltage(line)) - .groupMap(_._1)(_._2) - - /* Sanity check, that there is no ambiguous mapping */ - rawMapping.find { - case (_, ratedVoltages) if ratedVoltages.length > 1 => - true - case _ => - false - } match { - case Some(ambiguousEntry) => - throw SimbenchDataModelException( - s"Found ambiguous rated voltages for at least one entry: $ambiguousEntry" - ) - case None => - logger.debug( - "Great! Found only unambiguous line type to rated voltage mappings." - ) - } - - /* Mapping the line type to the rated voltage of the first entry of the Vector of each raw mapping. That nothing - * is missed is ensured by the sanity check beforehand */ - rawMapping.map { - case (lineType, lineTypeVRatedVector) => - lineType -> lineTypeVRatedVector.headOption.getOrElse( - throw SimbenchDataModelException( - s"Cannot receive rated voltage for line type '$lineType'." - ) - ) - } - } + ): Vector[(LineType, ComparableQuantity[ElectricPotential])] = + lines.map(line => determineRatedVoltage(line)).distinct /** * Maps the [[LineType]] of the specific line to it's rated voltage based on the line's nodes' rated voltages diff --git a/src/test/scala/edu/ie3/simbench/convert/types/LineTypeConverterSpec.scala b/src/test/scala/edu/ie3/simbench/convert/types/LineTypeConverterSpec.scala index c02ac2a4..1329e6cc 100644 --- a/src/test/scala/edu/ie3/simbench/convert/types/LineTypeConverterSpec.scala +++ b/src/test/scala/edu/ie3/simbench/convert/types/LineTypeConverterSpec.scala @@ -58,6 +58,28 @@ class LineTypeConverterSpec extends UnitSpec with ConverterTestData { 7 ) ) + val EHVlines = Vector( + ACLine( + "EHV Line 4", + getNodePair("EHV Bus 49")._1, + getNodePair("EHV Bus 59")._1, + getACLineTypes("LineType_1")._1, + BigDecimal("194.581"), + BigDecimal("100"), + "EHV 1", + 1 + ), + ACLine( + "EHV Line 273", + getNodePair("EHV Bus 1433")._1, + getNodePair("EHV Bus 1435")._1, + getACLineTypes("LineType_1")._1, + BigDecimal("43.396"), + BigDecimal("100"), + "EHV 1", + 1 + ) + ) val uuid: UUID = UUID.randomUUID() @@ -85,12 +107,12 @@ class LineTypeConverterSpec extends UnitSpec with ConverterTestData { } "build line type to rated voltage mapping correctly" in { - val actual = LineTypeConverter.getRatedVoltages(lineVec) + val actual = LineTypeConverter.assignRatedVoltages(lineVec) val expected = Map( getACLineTypes("NAYY 4x150SE 0.6/1kV")._1 -> Quantities .getQuantity(0.4, KILOVOLT), getACLineTypes("24-AL1/4-ST1A 20.0")._1 -> Quantities - .getQuantity(0.4, KILOVOLT) + .getQuantity(0.4, KILOVOLT) ) actual.toSet shouldBe expected.toSet } @@ -136,5 +158,19 @@ class LineTypeConverterSpec extends UnitSpec with ConverterTestData { ) thrown.getMessage shouldBe "DC line types are currently not supported by ie3's data model." } + + "extract the rated voltage of lines with same line type but different rated voltages correctly" in { + val actual = LineTypeConverter invokePrivate determineRatedVoltageMethod( + EHVlines(0) + ) + actual shouldBe (getACLineTypes("LineType_1")._1, Quantities + .getQuantity(380, KILOVOLT)) + val actualVal = LineTypeConverter invokePrivate determineRatedVoltageMethod( + EHVlines(1) + ) + actualVal shouldBe (getACLineTypes("LineType_1")._1, Quantities + .getQuantity(220, KILOVOLT)) + } + } } diff --git a/src/test/scala/edu/ie3/test/common/ConverterTestData.scala b/src/test/scala/edu/ie3/test/common/ConverterTestData.scala index 37caf055..f3c07024 100644 --- a/src/test/scala/edu/ie3/test/common/ConverterTestData.scala +++ b/src/test/scala/edu/ie3/test/common/ConverterTestData.scala @@ -340,6 +340,110 @@ trait ConverterTestData { LV, 2 ) + ), + "EHV Bus 49" -> ConversionPair( + Node( + "EHV Bus 49", + DoubleBusBar, + Some(BigDecimal("1.092")), + None, + BigDecimal("380"), + BigDecimal("0.9"), + BigDecimal("1.1"), + None, + None, + "EHV1", + 1 + ), + new NodeInput( + UUID.randomUUID(), + "EHV Bus 49", + OperatorInput.NO_OPERATOR_ASSIGNED, + OperationTime.notLimited(), + Quantities.getQuantity(1.092, PU), + false, + NodeInput.DEFAULT_GEO_POSITION, + GermanVoltageLevelUtils.EHV_380KV, + 1 + ) + ), + "EHV Bus 59" -> ConversionPair( + Node( + "EHV Bus 59", + DoubleBusBar, + None, + None, + BigDecimal("380"), + BigDecimal("0.9"), + BigDecimal("1.1"), + None, + None, + "EHV1", + 1 + ), + new NodeInput( + UUID.randomUUID(), + "EHV Bus 59", + OperatorInput.NO_OPERATOR_ASSIGNED, + OperationTime.notLimited(), + Quantities.getQuantity(0, PU), + false, + NodeInput.DEFAULT_GEO_POSITION, + GermanVoltageLevelUtils.EHV_380KV, + 1 + ) + ), + "EHV Bus 1433" -> ConversionPair( + Node( + "EHV Bus 1433", + DoubleBusBar, + Some(BigDecimal("1.068")), + None, + BigDecimal("220"), + BigDecimal("0.9"), + BigDecimal("1.1"), + None, + None, + "EHV1", + 1 + ), + new NodeInput( + UUID.randomUUID(), + "EHV Bus 1433", + OperatorInput.NO_OPERATOR_ASSIGNED, + OperationTime.notLimited(), + Quantities.getQuantity(1.068, PU), + false, + NodeInput.DEFAULT_GEO_POSITION, + GermanVoltageLevelUtils.EHV_220KV, + 1 + ) + ), + "EHV Bus 1435" -> ConversionPair( + Node( + "EHV Bus 1435", + DoubleBusBar, + None, + None, + BigDecimal("220"), + BigDecimal("0.9"), + BigDecimal("1.1"), + None, + None, + "EHV1", + 1 + ), + new NodeInput( + UUID.randomUUID(), + "EHV Bus 1435", + OperatorInput.NO_OPERATOR_ASSIGNED, + OperationTime.notLimited(), + Quantities.getQuantity(0, PU), + false, + NodeInput.DEFAULT_GEO_POSITION, + GermanVoltageLevelUtils.EHV_220KV, + 1 + ) ) ) @@ -463,7 +567,50 @@ trait ConverterTestData { Quantities.getQuantity(652d, ELECTRIC_CURRENT_MAGNITUDE), Quantities.getQuantity(20d, RATED_VOLTAGE_MAGNITUDE) ) + ), + "LineType_1" -> ConversionPair( + ACLineType( + "LineType_1", + BigDecimal("0.08"), + BigDecimal("0.32"), + BigDecimal("361.283"), + BigDecimal("1300"), + LineStyle.OverheadLine + ), + new LineTypeInput( + UUID.randomUUID(), + "LineType_1", + Quantities + .getQuantity(361.283d, ADMITTANCE_PER_LENGTH), + Quantities.getQuantity(0d, ADMITTANCE_PER_LENGTH), + Quantities.getQuantity(0.08d, IMPEDANCE_PER_LENGTH), + Quantities.getQuantity(0.32d, IMPEDANCE_PER_LENGTH), + Quantities.getQuantity(1300d, ELECTRIC_CURRENT_MAGNITUDE), + Quantities.getQuantity(220d, RATED_VOLTAGE_MAGNITUDE) + ) + ), + "LineType_1" -> ConversionPair( + ACLineType( + "LineType_1", + BigDecimal("0.08"), + BigDecimal("0.32"), + BigDecimal("361.283"), + BigDecimal("1300"), + LineStyle.OverheadLine + ), + new LineTypeInput( + UUID.randomUUID(), + "LineType_1", + Quantities + .getQuantity(361.283d, ADMITTANCE_PER_LENGTH), + Quantities.getQuantity(0d, ADMITTANCE_PER_LENGTH), + Quantities.getQuantity(0.08d, IMPEDANCE_PER_LENGTH), + Quantities.getQuantity(0.32d, IMPEDANCE_PER_LENGTH), + Quantities.getQuantity(1300d, ELECTRIC_CURRENT_MAGNITUDE), + Quantities.getQuantity(380d, RATED_VOLTAGE_MAGNITUDE) + ) ) + ) val dcLineTypes = Map(