From 543ee86421c4dc3b852a83e43f5e24b835efa0d4 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier Date: Mon, 5 Aug 2024 16:00:32 +0200 Subject: [PATCH 01/21] test --- .../simona/model/participant/BMModel.scala | 14 +- .../model/participant/BMModelSpec.scala | 210 ++++++++++++++++++ 2 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala diff --git a/src/main/scala/edu/ie3/simona/model/participant/BMModel.scala b/src/main/scala/edu/ie3/simona/model/participant/BMModel.scala index 418af563d5..556fc67d64 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/BMModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/BMModel.scala @@ -52,7 +52,7 @@ final case class BMModel( /** Saves power output of last cycle. Needed for load gradient */ - private var _lastPower: Option[Power] = None + var _lastPower: Option[Power] = None override def calculatePower( tick: Long, @@ -100,7 +100,7 @@ final case class BMModel( * @return * factor k1 */ - private def calculateK1(time: ZonedDateTime): Double = { + def calculateK1(time: ZonedDateTime): Double = { val weekendCorr = Vector(0.98, 0.985, 0.982, 0.982, 0.97, 0.96, 0.95, 0.93, 0.925, 0.95, 0.98, 1.01, 1.018, 1.01, 1.01, 0.995, 1, 0.995, 0.99, 0.985, 0.99, 0.98, 0.975, 0.99) @@ -120,7 +120,7 @@ final case class BMModel( * @return * factor k2 */ - private def calculateK2(time: ZonedDateTime): Double = { + def calculateK2(time: ZonedDateTime): Double = { time.getDayOfYear match { case x if x < 150 || x > 243 => 1.03 // correction factor in heating season @@ -138,7 +138,7 @@ final case class BMModel( * @return * heat demand in Megawatt */ - private def calculatePTh( + def calculatePTh( temp: Temperature, k1: Double, k2: Double, @@ -158,7 +158,7 @@ final case class BMModel( * @return * usage */ - private def calculateUsage(pTh: Power): Double = { + def calculateUsage(pTh: Power): Double = { // if demand exceeds capacity -> activate peak load boiler (no effect on electrical output) val maxHeat = Megawatts(43.14) val usageUnchecked = pTh / maxHeat @@ -173,7 +173,7 @@ final case class BMModel( * @return * efficiency */ - private def calculateEff(usage: Double): Double = + def calculateEff(usage: Double): Double = min(0.18 * pow(usage, 3) - 0.595 * pow(usage, 2) + 0.692 * usage + 0.724, 1) /** Calculates electrical output from usage and efficiency @@ -206,7 +206,7 @@ final case class BMModel( * @return * electrical output after load gradient has been applied */ - private def applyLoadGradient( + def applyLoadGradient( pEl: Power ): Power = { _lastPower match { diff --git a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala new file mode 100644 index 0000000000..c6a4578352 --- /dev/null +++ b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala @@ -0,0 +1,210 @@ +/* + * © 2020. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.model.participant + +import edu.ie3.datamodel.models.input.NodeInput +import edu.ie3.datamodel.models.input.system.`type`.BmTypeInput +import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed +import edu.ie3.simona.model.participant.control.QControl +import edu.ie3.util.scala.OperationInterval +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import squants.energy.{Kilowatts, Megawatts} +import squants.market.EUR +import squants.thermal.Celsius +import tech.units.indriya.quantity.Quantities + +import java.time.ZonedDateTime +import java.util.UUID + +/** + * Test class that tries to cover all special cases of the current implementation of the {@link BMModel} + * + * Test results have been calculated on paper using equations from wiki: https://wiki.ie3.e-technik.tu-dortmund.de/!simona/model:bm_model + */ +class BMModelSpec extends AnyFlatSpec with Matchers { + + val nodeInput: NodeInput = _ + val bmType: BmTypeInput = new BmTypeInput( + UUID.fromString("bc06e089-03cd-481e-9e28-228266a148a4"), + "BM Model Test Type 1", + Quantities.getQuantity(0, EUR), + Quantities.getQuantity(0.05, EuroPerKilowattHour), + Quantities.getQuantity(5, edu.ie3.util.quantities.PowerSystemUnits.PERCENT_PER_HOUR), + Quantities.getQuantity(190, edu.ie3.util.quantities.PowerSystemUnits.KILOVOLTAMPERE), + 1d, + Quantities.getQuantity(100d, tech.units.indriya.unit.Units.PERCENT) + ) + + def buildBmModel(): BMModel = { + new BMModel( + UUID.fromString("1b332f94-03e4-4abe-b142-8fceca689c53"), + "BM Model Test", + OperationInterval(0L, 86400L), + QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), + Kilowatts(190), + bmType.getCosPhiRated, + "MockNode", + isCostControlled = true, + EUR(bmType.getOpex.getValue.doubleValue()), + EuroPerKilowattHour(0.051d), + 0.05 + ) + } + + "BMModel" should "calculate K1 correctly" in { + val bmModel = buildBmModel() + + val testCases = Seq( + ("2019-01-04T05:15:00+01:00[Europe/Berlin]", 1d), // Friday + ("2019-01-07T05:15:00+01:00[Europe/Berlin]", 1d), // Monday + ("2019-01-05T05:15:00+01:00[Europe/Berlin]", 0.96d), // Saturday, 5:15AM + ("2019-01-05T15:59:00+01:00[Europe/Berlin]", 0.995d) // Sunday, 3:59PM + ) + + testCases.foreach { case (time, k1Sol) => + val k1Calc = bmModel.calculateK1(ZonedDateTime.parse(time)) + k1Calc shouldBe k1Sol + } + } + + it should "calculate K2 correctly" in { + val bmModel = buildBmModel() + + val testCases = Seq( + ("2019-05-29T05:15:00+02:00[Europe/Berlin]", 1.03d), // Day 149 of the year + ("2019-05-30T05:15:00+02:00[Europe/Berlin]", 0.61d), // Day 150 of the year + ("2019-08-31T05:15:00+02:00[Europe/Berlin]", 0.61d), // Day 243 of the year + ("2019-09-01T05:15:00+02:00[Europe/Berlin]", 1.03d) // Day 244 of the year + ) + + testCases.foreach { case (time, k2Sol) => + val k2Calc = bmModel.calculateK2(ZonedDateTime.parse(time)) + k2Calc shouldBe k2Sol + } + } + + it should "calculate PTh correctly" in { + val bmModel = buildBmModel() + + val testCases = Seq( + (19.28, 1d, 1d, 5.62d), // independent of temp + (30d, 2d, 3d, 33.72d), + (19.2799999d, 1d, 1d, 5.6147201076d), // dependent on temp + (15d, 1.01d, 0.61d, 6.296542d) // somewhat realistic + ) + + testCases.foreach { case (temp, k1, k2, pThSol) => + val pThCalc = bmModel.calculatePTh(Celsius(temp), k1, k2) + pThCalc should be (Megawatts(pThSol) +- Megawatts(0.0001)) + } + } + + it should "calculate usage correctly" in { + val bmModel = buildBmModel() + + val testCases = Seq( + (43.14d, 1d), // exactly maximum heat + (50d, 1d), // more than maximum, cap to 1 + (20d, 0.463606861382d), // less than max + (0d, 0d) // zero + ) + + testCases.foreach { case (pTh, usageSol) => + val usageCalc = bmModel.calculateUsage(Megawatts(pTh)) + usageCalc should be (usageSol +- 0.00000001) + } + } + + it should "calculate efficiency correctly" in { + val bmModel = buildBmModel() + + val testCases = Seq( + (1d, 1d), + (0d, 0.724d), + (0.75d, 0.98425d), + (0.86446317d, 0.993848918615d) + ) + + testCases.foreach { case (usage, effSol) => + val effCalc = bmModel.calculateEff(usage) + effCalc should be (effSol +- 0.000000001) + } + } + + it should "calculate electrical output correctly" in { + val bmModel = new BMModel( + UUID.fromString("8fbaf82d-5170-4636-bd7a-790eccbea880"), + "BM Model Test", + OperationInterval(0L, 86400L), + QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), + Kilowatts(190), + bmType.getCosPhiRated, + "MockNode", + isCostControlled = true, + EUR(bmType.getOpex.getValue.doubleValue()), + EuroPerKilowattHour(feedInTariff), + 0.05 + ) + + val testCases = Seq( + (0.051d, 1d, 1d, -190d), // tariff greater than opex => full power + (0.04d, 0.75d, 0.98425d, -140.255625d), // tariff too little, only serve heat demand + (0.04d, 1d, 1d, -190d) // tariff too little, but max heat demand + ) + + testCases.foreach { case (feedInTariff, usage, eff, pElSol) => + val pElCalc = bmModel.calculateElOutput(usage, eff) + pElCalc should be (Kilowatts(pElSol) +- Kilowatts(0.0001)) + } + } + + it should "apply load gradient correctly" in { + val bmModel = buildBmModel() + + val testCases = Seq( + (-100d, -120d, -109.5d), // increase of power, more than load gradient allows + (-50d, -55d, -55d), // increase, within load gradient + (-50d, -41d, -41d), // decrease, within load gradient + (-30d, -15d, -20.5d) // decrease, more than load gradient + ) + + testCases.foreach { case (lastPower, pEl, pElSol) => + bmModel._lastPower = Some(Kilowatts(lastPower)) + val pElCalc = bmModel.applyLoadGradient(Kilowatts(pEl)) + pElCalc should be (Kilowatts(pElSol)) + } + } + + it should "calculate P correctly" in { + val bmModel = new BMModel( + UUID.fromString("08e44067-5d1e-4a6e-97ef-d8bc9c8c256a"), + "BM Model Test", + OperationInterval(0L, 86400L), + QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), + Kilowatts(190), + bmType.getCosPhiRated, + "MockNode", + isCostControlled = true, + EUR(bmType.getOpex.getValue.doubleValue()), + EuroPerKilowattHour(feedInTariff), + 0.05 + ) + + val testCases = Seq( + (Megawatts(20), Megawatts(5), Megawatts(-15)), + (Megawatts(40), Megawatts(10), Megawatts(-30)), + (Megawatts(60), Megawatts(20), Megawatts(-40)), + (Megawatts(80), Megawatts(30), Megawatts(-50)) + ) + + testCases.foreach { case (heatDemand, power, pSol) => + val pCalc = bmModel.calculateP(heatDemand, power) + pCalc should be (pSol) + } + } +} \ No newline at end of file From b84cca15b09b16ef42768623467ae23cd44abb34 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier Date: Fri, 16 Aug 2024 15:05:37 +0200 Subject: [PATCH 02/21] Rewrote BMModelTest from groovy to scala. --- CHANGELOG.md | 1 + .../simona/model/participant/BMModel.scala | 4 +- .../model/participant/BMModelTest.groovy | 253 -------------- .../model/participant/BMModelSpec.scala | 322 ++++++++++++------ 4 files changed, 228 insertions(+), 352 deletions(-) delete mode 100644 src/test/groovy/edu/ie3/simona/model/participant/BMModelTest.groovy diff --git a/CHANGELOG.md b/CHANGELOG.md index 468de1d410..f26cd5a720 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Rewrote SystemComponentTest from groovy to scala [#646](https://github.com/ie3-institute/simona/issues/646) - Converting remaining rst files to markdown [#838](https://github.com/ie3-institute/simona/issues/838) - Merging both `FixedFeedInModelSpec` tests [#870](https://github.com/ie3-institute/simona/issues/870) +- Rewrote BMModelTest from groovy to scala [#646](https://github.com/ie3-institute/simona/issues/646) ### 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/model/participant/BMModel.scala b/src/main/scala/edu/ie3/simona/model/participant/BMModel.scala index 556fc67d64..19fbe3e601 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/BMModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/BMModel.scala @@ -73,7 +73,7 @@ final case class BMModel( * @return * Active power */ - override protected def calculateActivePower( + override def calculateActivePower( modelState: ConstantState.type, data: BMCalcRelevantData, ): Power = { @@ -184,7 +184,7 @@ final case class BMModel( * @return * electrical output as Power */ - private def calculateElOutput( + def calculateElOutput( usage: Double, eff: Double, ): Power = { diff --git a/src/test/groovy/edu/ie3/simona/model/participant/BMModelTest.groovy b/src/test/groovy/edu/ie3/simona/model/participant/BMModelTest.groovy deleted file mode 100644 index f6d83d770b..0000000000 --- a/src/test/groovy/edu/ie3/simona/model/participant/BMModelTest.groovy +++ /dev/null @@ -1,253 +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.model.participant - -import static edu.ie3.util.quantities.PowerSystemUnits.* -import static tech.units.indriya.unit.Units.PERCENT - -import edu.ie3.datamodel.models.input.NodeInput -import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed -import edu.ie3.datamodel.models.input.system.type.BmTypeInput -import edu.ie3.simona.model.participant.ModelState.ConstantState$ -import edu.ie3.simona.model.participant.control.QControl -import edu.ie3.util.scala.OperationInterval -import edu.ie3.util.scala.quantities.EuroPerKilowatthour$ -import edu.ie3.util.scala.quantities.Sq -import scala.Some -import spock.lang.Shared -import spock.lang.Specification -import squants.energy.Kilowatts$ -import squants.energy.Megawatts$ -import squants.market.EUR$ -import squants.thermal.Celsius$ -import tech.units.indriya.quantity.Quantities - -import java.time.ZonedDateTime - -/** - * Test class that tries to cover all special cases of the current implementation of the {@link BMModel} - * - * Test results have been calculated on paper using equations from wiki: https://wiki.ie3.e-technik.tu-dortmund.de/!simona/model:bm_model - */ -class BMModelTest extends Specification { - - @Shared - NodeInput nodeInput - @Shared - BmTypeInput bmType - - def setupSpec() { - // build the NodeInputModel - nodeInput = Mock(NodeInput) - - // build the BMTypesInputModel - bmType = new BmTypeInput( - UUID.fromString("bc06e089-03cd-481e-9e28-228266a148a4"), - "BM Model Test Type 1", - Quantities.getQuantity(0, EURO), - Quantities.getQuantity(0.05d, EURO_PER_KILOWATTHOUR), - Quantities.getQuantity(5d, PERCENT_PER_HOUR), - Quantities.getQuantity(190, KILOVOLTAMPERE), - 1d, - Quantities.getQuantity(100d, PERCENT) - ) - } - - def getStandardModel() { - return new BMModel( - UUID.fromString("1b332f94-03e4-4abe-b142-8fceca689c53"), - "BM Model Test", - OperationInterval.apply(0L, 86400L), - QControl.apply(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), - Sq.create(190, Kilowatts$.MODULE$), - bmType.getCosPhiRated(), - "MockNode", - true, - Sq.create(bmType.opex.value.doubleValue(), EUR$.MODULE$), - Sq.create(0.051d, EuroPerKilowatthour$.MODULE$), - 0.05) - } - - def "Test calculateK1"() { - given: - BMModel bmModel = getStandardModel() - - when: - def k1Calc = bmModel.calculateK1(ZonedDateTime.parse(time)) - - then: - k1Calc == k1Sol - - where: - time || k1Sol - '2019-01-04T05:15:00+01:00[Europe/Berlin]' || 1d // Friday - '2019-01-07T05:15:00+01:00[Europe/Berlin]' || 1d // Monday - '2019-01-05T05:15:00+01:00[Europe/Berlin]' || 0.96d // Saturday, 5:15AM - '2019-01-05T15:59:00+01:00[Europe/Berlin]' || 0.995d // Sunday, 3:59PM - } - - def "Test calculateK2"() { - given: - BMModel bmModel = getStandardModel() - - when: - def k2Calc = bmModel.calculateK2(ZonedDateTime.parse(time)) - - then: - k2Calc == k2Sol - - where: - time || k2Sol - '2019-05-29T05:15:00+02:00[Europe/Berlin]' || 1.03d // Day 149 of the year - '2019-05-30T05:15:00+02:00[Europe/Berlin]' || 0.61d // Day 150 of the year - '2019-08-31T05:15:00+02:00[Europe/Berlin]' || 0.61d // Day 243 of the year - '2019-09-01T05:15:00+02:00[Europe/Berlin]' || 1.03d // Day 244 of the year - } - - def "Test calculatePTh"() { - given: - BMModel bmModel = getStandardModel() - - when: - def pThCalc = bmModel.calculatePTh(Sq.create(temp, Celsius$.MODULE$), k1, k2) - - then: "compare in watts" - pThCalc - Sq.create(pThSol, Megawatts$.MODULE$) < Sq.create(0.0001d, Megawatts$.MODULE$) - - where: - temp | k1 | k2 || pThSol - 19.28d | 1d | 1d || 5.62d // independent of temp - 30d | 2d | 3d || 33.72d - 19.2799999d | 1d | 1d || 5.6147201076d // dependent on temp - 15d | 1.01d | 0.61d || 6.296542d // somewhat realistic - } - - def "Test calculateUsage"() { - given: - BMModel bmModel = getStandardModel() - - when: - def usageCalc = bmModel.calculateUsage(Sq.create(pTh, Megawatts$.MODULE$)) - - then: - Math.abs(usageCalc - usageSol) < 0.00000001 - - where: - pTh || usageSol - 43.14d || 1d // exactly maximum heat - 50d || 1d // more than maximum, cap to 1 - 20d || 0.463606861382d // less than max - 0d || 0d // zero - } - - def "Test calculateEff"() { - given: - BMModel bmModel = getStandardModel() - - when: - def effCalc = bmModel.calculateEff(usage) - - then: - Math.abs(effCalc - effSol) < 0.000000001 - - where: - usage || effSol - 1d || 1d - 0d || 0.724d - 0.75d || 0.98425d - 0.86446317d || 0.993848918615d - } - - def "Test calculateElOutput"() { - when: - BMModel bmModel = new BMModel( - UUID.fromString("8fbaf82d-5170-4636-bd7a-790eccbea880"), - "BM Model Test", - OperationInterval.apply(0L, 86400L), - QControl.apply(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), - Sq.create(190, Kilowatts$.MODULE$), - bmType.getCosPhiRated(), - "MockNode", - true, - Sq.create(bmType.opex.value.doubleValue(), EUR$.MODULE$), - Sq.create(feedInTariff, EuroPerKilowatthour$.MODULE$), - 0.05) - - def pElCalc = bmModel.calculateElOutput(usage, eff) - - then: "compare in watts" - pElCalc - Sq.create(pElSol, Kilowatts$.MODULE$) < Sq.create(0.0001d, Kilowatts$.MODULE$) - - where: - feedInTariff | usage | eff || pElSol - 0.051d | 1d | 1d || -190d // tariff greater than opex => full power - 0.04d | 0.75d | 0.98425d || -140.255625d // tariff too little, only serve heat demand - 0.04d | 1d | 1d || -190d // tariff too little, but max heat demand - } - - def "Test applyLoadGradient"() { - given: - BMModel bmModel = getStandardModel() - bmModel._lastPower = new Some(Sq.create(lastPower, Kilowatts$.MODULE$)) - - when: - def pElCalc = bmModel.applyLoadGradient(Sq.create(pEl, Kilowatts$.MODULE$)) - - then: - pElCalc == Sq.create(pElSol, Kilowatts$.MODULE$) - - where: - lastPower | pEl || pElSol - -100d | -120d || -109.5d // increase of power, more than load gradient allows - -50d | -55d || -55d // increase, within load gradient - -50d | -41d || -41d // decrease, within load gradient - -30d | -15 || -20.5d // decrease, more than load gradient - } - - def "Test calculateP"() { - given: "date, time, a temperature and last power output and the built model" - // construct date and time from string - ZonedDateTime dateTime = ZonedDateTime.parse(time) - - /* Prepare the calculation relevant data */ - BMModel.BMCalcRelevantData relevantData = new BMModel.BMCalcRelevantData(dateTime, Sq.create(temp, Celsius$.MODULE$)) - - BMModel bmModel = new BMModel( - UUID.fromString("08a8134d-04b7-45de-a937-9a55fab4e1af"), - "BM Model Test", - OperationInterval.apply(0L, 86400L), - QControl.apply(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), - Sq.create(190, Kilowatts$.MODULE$), - bmType.getCosPhiRated(), - "MockNode", - costControlled, - Sq.create(bmType.opex.value.doubleValue(), EUR$.MODULE$), - Sq.create(0.051d, EuroPerKilowatthour$.MODULE$), - 0.05) - - // modify data store: add last output power, one hour in the past - bmModel._lastPower = new Some(Sq.create(lastPower, Kilowatts$.MODULE$)) - - when: "the power from the grid is calculated" - def powerCalc = bmModel.calculateActivePower(ConstantState$.MODULE$, relevantData) - - then: "compare in kilowatts" - powerCalc - Sq.create(powerSol, Kilowatts$.MODULE$) < Sq.create(1e-12d, Kilowatts$.MODULE$) - - where: - time | temp | costControlled | lastPower || powerSol - '2019-01-05T05:15:00+01:00[Europe/Berlin]' | 10 | true | -40.0d || -49.5d // weekend day in heating season, power increase capped by load gradient - '2019-01-04T05:15:00+01:00[Europe/Berlin]' | 10 | true | -80.0d || -70.5d // working day in heating season, power decrease capped by load gradient - '2019-01-04T05:15:00+01:00[Europe/Berlin]' | -20 | true | -182.0d || -190d // peek load boiler activated, max output because cost < revenues - '2019-01-04T05:15:00+01:00[Europe/Berlin]' | -7 | true | -182.0d || -190d // close to peak load, max output because cost < revenues - '2019-01-04T05:15:00+01:00[Europe/Berlin]' | -7 | false | -150.0d || -152.16900643778735d // close to peak load, not cost controlled but just serving heat demand - '2019-07-07T10:15:00+02:00[Europe/Berlin]' | 19 | true | -10.0d || -12.099949463243976d // weekend day outside heating season, increase not capped - '2019-07-05T05:15:00+02:00[Europe/Berlin]' | 20 | true | -20.0d || -11.70638561892377d // working day outside heating season, decrease not capped - '2019-07-06T10:15:00+02:00[Europe/Berlin]' | 20 | true | -0.0d || -9.5d // weekend day outside heating season, increase capped - '2019-07-05T05:15:00+02:00[Europe/Berlin]' | 22 | true | -22.0d || -12.5d // working day outside heating season, decrease capped - } -} \ No newline at end of file diff --git a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala index c6a4578352..a7a021952e 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala @@ -6,38 +6,53 @@ package edu.ie3.simona.model.participant -import edu.ie3.datamodel.models.input.NodeInput import edu.ie3.datamodel.models.input.system.`type`.BmTypeInput import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed +import edu.ie3.simona.model.participant.ModelState.ConstantState import edu.ie3.simona.model.participant.control.QControl +import edu.ie3.simona.test.common.UnitSpec import edu.ie3.util.scala.OperationInterval -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers +import edu.ie3.util.scala.quantities.EuroPerKilowatthour import squants.energy.{Kilowatts, Megawatts} import squants.market.EUR import squants.thermal.Celsius +import squants.{Power, Temperature} import tech.units.indriya.quantity.Quantities import java.time.ZonedDateTime import java.util.UUID -/** - * Test class that tries to cover all special cases of the current implementation of the {@link BMModel} - * - * Test results have been calculated on paper using equations from wiki: https://wiki.ie3.e-technik.tu-dortmund.de/!simona/model:bm_model - */ -class BMModelSpec extends AnyFlatSpec with Matchers { +/** Test class that tries to cover all special cases of the current + * implementation of the {@link BMModel} + * + * Test results have been calculated on paper using equations from wiki: + * https://wiki.ie3.e-technik.tu-dortmund.de/!simona/model:bm_model + */ + +class BMModelSpec extends UnitSpec { + + implicit val powerTolerance: Power = Megawatts(1e-4) + implicit val power2Tolerance: Power = Kilowatts(1e-4) + implicit val usageTolerance: Double = 1e-12 - val nodeInput: NodeInput = _ val bmType: BmTypeInput = new BmTypeInput( UUID.fromString("bc06e089-03cd-481e-9e28-228266a148a4"), "BM Model Test Type 1", - Quantities.getQuantity(0, EUR), - Quantities.getQuantity(0.05, EuroPerKilowattHour), - Quantities.getQuantity(5, edu.ie3.util.quantities.PowerSystemUnits.PERCENT_PER_HOUR), - Quantities.getQuantity(190, edu.ie3.util.quantities.PowerSystemUnits.KILOVOLTAMPERE), + Quantities.getQuantity(0, edu.ie3.util.quantities.PowerSystemUnits.EURO), + Quantities.getQuantity( + 0.05d, + edu.ie3.util.quantities.PowerSystemUnits.EURO_PER_KILOWATTHOUR, + ), + Quantities.getQuantity( + 5, + edu.ie3.util.quantities.PowerSystemUnits.PERCENT_PER_HOUR, + ), + Quantities.getQuantity( + 190, + edu.ie3.util.quantities.PowerSystemUnits.KILOVOLTAMPERE, + ), 1d, - Quantities.getQuantity(100d, tech.units.indriya.unit.Units.PERCENT) + Quantities.getQuantity(100d, tech.units.indriya.unit.Units.PERCENT), ) def buildBmModel(): BMModel = { @@ -51,160 +66,273 @@ class BMModelSpec extends AnyFlatSpec with Matchers { "MockNode", isCostControlled = true, EUR(bmType.getOpex.getValue.doubleValue()), - EuroPerKilowattHour(0.051d), - 0.05 + EuroPerKilowatthour(0.51d), + 0.05, ) } - "BMModel" should "calculate K1 correctly" in { - val bmModel = buildBmModel() + "A BMModel" should { + "calculate K1 correctly" in { + val bmModel = buildBmModel() - val testCases = Seq( - ("2019-01-04T05:15:00+01:00[Europe/Berlin]", 1d), // Friday - ("2019-01-07T05:15:00+01:00[Europe/Berlin]", 1d), // Monday - ("2019-01-05T05:15:00+01:00[Europe/Berlin]", 0.96d), // Saturday, 5:15AM - ("2019-01-05T15:59:00+01:00[Europe/Berlin]", 0.995d) // Sunday, 3:59PM - ) + val testCases = Table( + ("Time", "K1 Solution"), + ("2019-01-04T05:15:00+01:00[Europe/Berlin]", 1d), // Friday + ("2019-01-07T05:15:00+01:00[Europe/Berlin]", 1d), // Monday + ("2019-01-05T05:15:00+01:00[Europe/Berlin]", 0.96d), // Saturday, 5:15AM + ("2019-01-05T15:59:00+01:00[Europe/Berlin]", 0.995d), // Sunday, 3:59PM + ) - testCases.foreach { case (time, k1Sol) => - val k1Calc = bmModel.calculateK1(ZonedDateTime.parse(time)) - k1Calc shouldBe k1Sol + testCases.foreach { case (time, k1Sol) => + val k1Calc = bmModel.calculateK1(ZonedDateTime.parse(time)) + k1Calc should be(k1Sol) + } } } - it should "calculate K2 correctly" in { + "calculate K2 correctly" in { val bmModel = buildBmModel() - val testCases = Seq( - ("2019-05-29T05:15:00+02:00[Europe/Berlin]", 1.03d), // Day 149 of the year - ("2019-05-30T05:15:00+02:00[Europe/Berlin]", 0.61d), // Day 150 of the year - ("2019-08-31T05:15:00+02:00[Europe/Berlin]", 0.61d), // Day 243 of the year - ("2019-09-01T05:15:00+02:00[Europe/Berlin]", 1.03d) // Day 244 of the year + val testCases = Table( + ("Time", "K2 Solution"), + ( + "2019-05-29T05:15:00+02:00[Europe/Berlin]", + 1.03d, + ), // Day 149 of the year + ( + "2019-05-30T05:15:00+02:00[Europe/Berlin]", + 0.61d, + ), // Day 150 of the year + ( + "2019-08-31T05:15:00+02:00[Europe/Berlin]", + 0.61d, + ), // Day 243 of the year + ("2019-09-01T05:15:00+02:00[Europe/Berlin]", 1.03d), // Day 244 of the year ) testCases.foreach { case (time, k2Sol) => val k2Calc = bmModel.calculateK2(ZonedDateTime.parse(time)) - k2Calc shouldBe k2Sol + k2Calc should be(k2Sol) } } - it should "calculate PTh correctly" in { + "calculate PTh correctly" in { val bmModel = buildBmModel() - val testCases = Seq( + val testCases = Table( + ("Temperature", "K1", "K2", "PTh Solution"), (19.28, 1d, 1d, 5.62d), // independent of temp (30d, 2d, 3d, 33.72d), (19.2799999d, 1d, 1d, 5.6147201076d), // dependent on temp - (15d, 1.01d, 0.61d, 6.296542d) // somewhat realistic + (15d, 1.01d, 0.61d, 6.296542d), // somewhat realistic ) testCases.foreach { case (temp, k1, k2, pThSol) => val pThCalc = bmModel.calculatePTh(Celsius(temp), k1, k2) - pThCalc should be (Megawatts(pThSol) +- Megawatts(0.0001)) + pThCalc should approximate(Megawatts(pThSol))(powerTolerance) } } - it should "calculate usage correctly" in { + "calculate usage correctly" in { val bmModel = buildBmModel() - val testCases = Seq( + val testCases = Table( + ("PTh", "Usage Solution"), (43.14d, 1d), // exactly maximum heat (50d, 1d), // more than maximum, cap to 1 (20d, 0.463606861382d), // less than max - (0d, 0d) // zero + (0d, 0d), // zero ) testCases.foreach { case (pTh, usageSol) => val usageCalc = bmModel.calculateUsage(Megawatts(pTh)) - usageCalc should be (usageSol +- 0.00000001) + usageCalc should be(usageSol +- usageTolerance) } } - it should "calculate efficiency correctly" in { + "calculate efficiency correctly" in { val bmModel = buildBmModel() - val testCases = Seq( + val testCases = Table( + ("Usage", "Efficiency Solution"), (1d, 1d), (0d, 0.724d), (0.75d, 0.98425d), - (0.86446317d, 0.993848918615d) + (0.86446317d, 0.993848918615d), ) testCases.foreach { case (usage, effSol) => val effCalc = bmModel.calculateEff(usage) - effCalc should be (effSol +- 0.000000001) + effCalc should be(effSol +- 0.000000001) } } - it should "calculate electrical output correctly" in { - val bmModel = new BMModel( - UUID.fromString("8fbaf82d-5170-4636-bd7a-790eccbea880"), - "BM Model Test", - OperationInterval(0L, 86400L), - QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), - Kilowatts(190), - bmType.getCosPhiRated, - "MockNode", - isCostControlled = true, - EUR(bmType.getOpex.getValue.doubleValue()), - EuroPerKilowattHour(feedInTariff), - 0.05 - ) + "calculate electrical output correctly" in { - val testCases = Seq( + val testCases = Table( + ("FeedInTariff", "Usage", "Efficiency", "PEl Solution"), (0.051d, 1d, 1d, -190d), // tariff greater than opex => full power - (0.04d, 0.75d, 0.98425d, -140.255625d), // tariff too little, only serve heat demand - (0.04d, 1d, 1d, -190d) // tariff too little, but max heat demand + ( + 0.04d, + 0.75d, + 0.98425d, + -140.255625d, + ), // tariff too little, only serve heat demand + (0.04d, 1d, 1d, -190d), // tariff too little, but max heat demand ) testCases.foreach { case (feedInTariff, usage, eff, pElSol) => + val bmModel = new BMModel( + UUID.fromString("8fbaf82d-5170-4636-bd7a-790eccbea880"), + "BM Model Test", + OperationInterval(0L, 86400L), + QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), + Kilowatts(190), + bmType.getCosPhiRated, + "MockNode", + isCostControlled = true, + EUR(bmType.getOpex.getValue.doubleValue()), + EuroPerKilowatthour(feedInTariff), + 0.05, + ) + val pElCalc = bmModel.calculateElOutput(usage, eff) - pElCalc should be (Kilowatts(pElSol) +- Kilowatts(0.0001)) + pElCalc.value should be(Kilowatts(pElSol).value +- 1e-4) } } - it should "apply load gradient correctly" in { + "apply load gradient correctly" in { val bmModel = buildBmModel() - val testCases = Seq( - (-100d, -120d, -109.5d), // increase of power, more than load gradient allows - (-50d, -55d, -55d), // increase, within load gradient - (-50d, -41d, -41d), // decrease, within load gradient - (-30d, -15d, -20.5d) // decrease, more than load gradient + val testCases = Table( + ("Last Power", "PEl", "PEl Solution"), + ( + Kilowatts(-100d), // Last Power + Kilowatts(-120d), // PEl + Kilowatts(-109.5d), // PEl Solution + ), // increase of power, more than load gradient allows + ( + Kilowatts(-50d), // Last Power + Kilowatts(-55d), // PEl + Kilowatts(-55d), // PEl Solution + ), // increase, within load gradient + ( + Kilowatts(-50d), // Last Power + Kilowatts(-41d), // PEl + Kilowatts(-41d), // PEl Solution + ), // decrease, within load gradient + ( + Kilowatts(-30d), // Last Power + Kilowatts(-15d), // PEl + Kilowatts(-20.5d), // PEl Solution + ), // decrease, more than load gradient ) testCases.foreach { case (lastPower, pEl, pElSol) => - bmModel._lastPower = Some(Kilowatts(lastPower)) - val pElCalc = bmModel.applyLoadGradient(Kilowatts(pEl)) - pElCalc should be (Kilowatts(pElSol)) + bmModel._lastPower = Some(lastPower) + val pElCalc = bmModel.applyLoadGradient(pEl) + pElCalc should approximate(pElSol)(power2Tolerance) } } - it should "calculate P correctly" in { - val bmModel = new BMModel( - UUID.fromString("08e44067-5d1e-4a6e-97ef-d8bc9c8c256a"), - "BM Model Test", - OperationInterval(0L, 86400L), - QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), - Kilowatts(190), - bmType.getCosPhiRated, - "MockNode", - isCostControlled = true, - EUR(bmType.getOpex.getValue.doubleValue()), - EuroPerKilowattHour(feedInTariff), - 0.05 - ) + "calculate P correctly" in { - val testCases = Seq( - (Megawatts(20), Megawatts(5), Megawatts(-15)), - (Megawatts(40), Megawatts(10), Megawatts(-30)), - (Megawatts(60), Megawatts(20), Megawatts(-40)), - (Megawatts(80), Megawatts(30), Megawatts(-50)) + val testCases = Table( + ("time", "temp", "costControlled", "lastPower", "powerSol"), + ( + "2019-01-05T05:15:00+01:00[Europe/Berlin]", + Celsius(10), + true, + Kilowatts(-40.0), + Kilowatts(-49.5), + ), + ( + "2019-01-04T05:15:00+01:00[Europe/Berlin]", + Celsius(10), + true, + Kilowatts(-80.0), + Kilowatts(-89.5), + ), + ( + "2019-01-04T05:15:00+01:00[Europe/Berlin]", + Celsius(-20), + true, + Kilowatts(-182.0), + Kilowatts(-190), + ), + ( + "2019-01-04T05:15:00+01:00[Europe/Berlin]", + Celsius(-7), + true, + Kilowatts(-182.0), + Kilowatts(-190), + ), + ( + "2019-01-04T05:15:00+01:00[Europe/Berlin]", + Celsius(-7), + false, + Kilowatts(-150.0), + Kilowatts(-152.16900643778735), + ), + ( + "2019-07-07T10:15:00+02:00[Europe/Berlin]", + Celsius(19), + true, + Kilowatts(-10.0), + Kilowatts(-19.5), + ), + ( + "2019-07-05T05:15:00+02:00[Europe/Berlin]", + Celsius(20), + true, + Kilowatts(-20.0), + Kilowatts(-29.5), + ), + ( + "2019-07-06T10:15:00+02:00[Europe/Berlin]", + Celsius(20), + true, + Kilowatts(0.0), + Kilowatts(-9.5), + ), + ( + "2019-07-05T05:15:00+02:00[Europe/Berlin]", + Celsius(22), + true, + Kilowatts(-22.0), + Kilowatts(-31.5), + ), ) - testCases.foreach { case (heatDemand, power, pSol) => - val pCalc = bmModel.calculateP(heatDemand, power) - pCalc should be (pSol) + forAll(testCases) { + ( + time: String, + temp: Temperature, + costControlled: Boolean, + lastPower: Power, + powerSol: Power, + ) => + val dateTime = ZonedDateTime.parse(time) + val relevantData = new BMModel.BMCalcRelevantData(dateTime, temp) + + val bmModel = new BMModel( + UUID.fromString("08a8134d-04b7-45de-a937-9a55fab4e1af"), + "BM Model Test", + OperationInterval(0L, 86400L), + QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), + Kilowatts(190), + bmType.getCosPhiRated(), + "MockNode", + costControlled, + EUR(bmType.getOpex.getValue.doubleValue()), + EuroPerKilowatthour(0.51d), + 0.05, + ) + + bmModel._lastPower = Some(lastPower) + val powerCalc = + bmModel.calculateActivePower(ConstantState, relevantData) + powerCalc should be(powerSol) } } -} \ No newline at end of file +} From 35350da91a2a5ccdb58d3cf39b6b69c3e7752c79 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier Date: Fri, 16 Aug 2024 15:23:36 +0200 Subject: [PATCH 03/21] fmt --- .../edu/ie3/simona/model/participant/BMModelSpec.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala index a7a021952e..12d3906425 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala @@ -120,7 +120,7 @@ class BMModelSpec extends UnitSpec { val bmModel = buildBmModel() val testCases = Table( - ("Temperature", "K1", "K2", "PTh Solution"), + ("Temperature", "K1", "K2", "PTh Sol"), (19.28, 1d, 1d, 5.62d), // independent of temp (30d, 2d, 3d, 33.72d), (19.2799999d, 1d, 1d, 5.6147201076d), // dependent on temp @@ -154,7 +154,7 @@ class BMModelSpec extends UnitSpec { val bmModel = buildBmModel() val testCases = Table( - ("Usage", "Efficiency Solution"), + ("Usage", "Efficiency Sol"), (1d, 1d), (0d, 0.724d), (0.75d, 0.98425d), @@ -170,7 +170,7 @@ class BMModelSpec extends UnitSpec { "calculate electrical output correctly" in { val testCases = Table( - ("FeedInTariff", "Usage", "Efficiency", "PEl Solution"), + ("FeedInTariff", "Usage", "Efficiency", "PEl Sol"), (0.051d, 1d, 1d, -190d), // tariff greater than opex => full power ( 0.04d, @@ -205,7 +205,7 @@ class BMModelSpec extends UnitSpec { val bmModel = buildBmModel() val testCases = Table( - ("Last Power", "PEl", "PEl Solution"), + ("Last Power", "PEl", "PEl Sol"), ( Kilowatts(-100d), // Last Power Kilowatts(-120d), // PEl From fd08c69c9a257f9ea674368e7e8dcb8f64e06496 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Thu, 22 Aug 2024 19:28:19 +0200 Subject: [PATCH 04/21] Update src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala Co-authored-by: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> --- .../scala/edu/ie3/simona/model/participant/BMModelSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala index 12d3906425..0ad4858497 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala @@ -313,7 +313,7 @@ class BMModelSpec extends UnitSpec { powerSol: Power, ) => val dateTime = ZonedDateTime.parse(time) - val relevantData = new BMModel.BMCalcRelevantData(dateTime, temp) + val relevantData = BMCalcRelevantData(dateTime, temp) val bmModel = new BMModel( UUID.fromString("08a8134d-04b7-45de-a937-9a55fab4e1af"), From 1236ebc6f42d272c90d323fe180de996d3fd1f96 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier Date: Thu, 22 Aug 2024 21:02:13 +0200 Subject: [PATCH 05/21] Improve Code Quality and fix test "calculate P correctly" --- .../model/participant/BMModelSpec.scala | 69 +++++++------------ 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala index 0ad4858497..f4efa251d6 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala @@ -6,7 +6,6 @@ package edu.ie3.simona.model.participant -import edu.ie3.datamodel.models.input.system.`type`.BmTypeInput import edu.ie3.datamodel.models.input.system.characteristic.CosPhiFixed import edu.ie3.simona.model.participant.ModelState.ConstantState import edu.ie3.simona.model.participant.control.QControl @@ -17,7 +16,6 @@ import squants.energy.{Kilowatts, Megawatts} import squants.market.EUR import squants.thermal.Celsius import squants.{Power, Temperature} -import tech.units.indriya.quantity.Quantities import java.time.ZonedDateTime import java.util.UUID @@ -32,29 +30,8 @@ import java.util.UUID class BMModelSpec extends UnitSpec { implicit val powerTolerance: Power = Megawatts(1e-4) - implicit val power2Tolerance: Power = Kilowatts(1e-4) implicit val usageTolerance: Double = 1e-12 - val bmType: BmTypeInput = new BmTypeInput( - UUID.fromString("bc06e089-03cd-481e-9e28-228266a148a4"), - "BM Model Test Type 1", - Quantities.getQuantity(0, edu.ie3.util.quantities.PowerSystemUnits.EURO), - Quantities.getQuantity( - 0.05d, - edu.ie3.util.quantities.PowerSystemUnits.EURO_PER_KILOWATTHOUR, - ), - Quantities.getQuantity( - 5, - edu.ie3.util.quantities.PowerSystemUnits.PERCENT_PER_HOUR, - ), - Quantities.getQuantity( - 190, - edu.ie3.util.quantities.PowerSystemUnits.KILOVOLTAMPERE, - ), - 1d, - Quantities.getQuantity(100d, tech.units.indriya.unit.Units.PERCENT), - ) - def buildBmModel(): BMModel = { new BMModel( UUID.fromString("1b332f94-03e4-4abe-b142-8fceca689c53"), @@ -62,10 +39,10 @@ class BMModelSpec extends UnitSpec { OperationInterval(0L, 86400L), QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), Kilowatts(190), - bmType.getCosPhiRated, + 1d, "MockNode", isCostControlled = true, - EUR(bmType.getOpex.getValue.doubleValue()), + EUR(0.05), EuroPerKilowatthour(0.51d), 0.05, ) @@ -129,7 +106,7 @@ class BMModelSpec extends UnitSpec { testCases.foreach { case (temp, k1, k2, pThSol) => val pThCalc = bmModel.calculatePTh(Celsius(temp), k1, k2) - pThCalc should approximate(Megawatts(pThSol))(powerTolerance) + pThCalc should approximate(Megawatts(pThSol)) } } @@ -176,7 +153,7 @@ class BMModelSpec extends UnitSpec { 0.04d, 0.75d, 0.98425d, - -140.255625d, + -140.25562499999998d, ), // tariff too little, only serve heat demand (0.04d, 1d, 1d, -190d), // tariff too little, but max heat demand ) @@ -188,10 +165,10 @@ class BMModelSpec extends UnitSpec { OperationInterval(0L, 86400L), QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), Kilowatts(190), - bmType.getCosPhiRated, + 1d, "MockNode", isCostControlled = true, - EUR(bmType.getOpex.getValue.doubleValue()), + EUR(0.05), EuroPerKilowatthour(feedInTariff), 0.05, ) @@ -207,31 +184,31 @@ class BMModelSpec extends UnitSpec { val testCases = Table( ("Last Power", "PEl", "PEl Sol"), ( - Kilowatts(-100d), // Last Power - Kilowatts(-120d), // PEl - Kilowatts(-109.5d), // PEl Solution + Kilowatts(-100d), + Kilowatts(-120d), + Kilowatts(-109.5d), ), // increase of power, more than load gradient allows ( - Kilowatts(-50d), // Last Power - Kilowatts(-55d), // PEl - Kilowatts(-55d), // PEl Solution + Kilowatts(-50d), + Kilowatts(-55d), + Kilowatts(-55d), ), // increase, within load gradient ( - Kilowatts(-50d), // Last Power - Kilowatts(-41d), // PEl - Kilowatts(-41d), // PEl Solution + Kilowatts(-50d), + Kilowatts(-41d), + Kilowatts(-41d), ), // decrease, within load gradient ( - Kilowatts(-30d), // Last Power - Kilowatts(-15d), // PEl - Kilowatts(-20.5d), // PEl Solution + Kilowatts(-30d), + Kilowatts(-15d), + Kilowatts(-20.5d), ), // decrease, more than load gradient ) testCases.foreach { case (lastPower, pEl, pElSol) => bmModel._lastPower = Some(lastPower) val pElCalc = bmModel.applyLoadGradient(pEl) - pElCalc should approximate(pElSol)(power2Tolerance) + pElCalc should approximate(pElSol) } } @@ -313,7 +290,7 @@ class BMModelSpec extends UnitSpec { powerSol: Power, ) => val dateTime = ZonedDateTime.parse(time) - val relevantData = BMCalcRelevantData(dateTime, temp) + val relevantData = BMModel.BMCalcRelevantData(dateTime, Celsius(temp)) val bmModel = new BMModel( UUID.fromString("08a8134d-04b7-45de-a937-9a55fab4e1af"), @@ -321,10 +298,10 @@ class BMModelSpec extends UnitSpec { OperationInterval(0L, 86400L), QControl(new CosPhiFixed("cosPhiFixed:{(0.0,1.0)}")), Kilowatts(190), - bmType.getCosPhiRated(), + 1d, "MockNode", costControlled, - EUR(bmType.getOpex.getValue.doubleValue()), + EUR(0.05), EuroPerKilowatthour(0.51d), 0.05, ) @@ -332,7 +309,7 @@ class BMModelSpec extends UnitSpec { bmModel._lastPower = Some(lastPower) val powerCalc = bmModel.calculateActivePower(ConstantState, relevantData) - powerCalc should be(powerSol) + powerCalc.value should be(powerSol.value) } } } From dfa3f2de96eed2de0e1c0e2a0dfaeb9149ef6134 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier Date: Sun, 25 Aug 2024 19:09:48 +0200 Subject: [PATCH 06/21] Fix test "calculate P correctly" --- .../model/participant/BMModelSpec.scala | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala index f4efa251d6..011dbb9567 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/BMModelSpec.scala @@ -29,7 +29,7 @@ import java.util.UUID class BMModelSpec extends UnitSpec { - implicit val powerTolerance: Power = Megawatts(1e-4) + implicit val powerTolerance: Power = Kilowatts(1e-4) implicit val usageTolerance: Double = 1e-12 def buildBmModel(): BMModel = { @@ -216,68 +216,77 @@ class BMModelSpec extends UnitSpec { val testCases = Table( ("time", "temp", "costControlled", "lastPower", "powerSol"), + // weekend day in heating season, power increase capped by load gradient ( "2019-01-05T05:15:00+01:00[Europe/Berlin]", - Celsius(10), + Celsius(10.0), true, Kilowatts(-40.0), Kilowatts(-49.5), ), + // working day in heating season, power decrease capped by load gradient ( "2019-01-04T05:15:00+01:00[Europe/Berlin]", - Celsius(10), + Celsius(10.0), true, Kilowatts(-80.0), - Kilowatts(-89.5), + Kilowatts(-70.5), ), + // peak load boiler activated, max output because cost < revenues ( "2019-01-04T05:15:00+01:00[Europe/Berlin]", - Celsius(-20), + Celsius(-20.0), true, Kilowatts(-182.0), - Kilowatts(-190), + Kilowatts(-190.0), ), + // close to peak load, max output because cost < revenues ( "2019-01-04T05:15:00+01:00[Europe/Berlin]", - Celsius(-7), + Celsius(-7.0), true, Kilowatts(-182.0), - Kilowatts(-190), + Kilowatts(-190.0), ), + // close to peak load, not cost controlled but just serving heat demand ( "2019-01-04T05:15:00+01:00[Europe/Berlin]", - Celsius(-7), + Celsius(-7.0), false, Kilowatts(-150.0), Kilowatts(-152.16900643778735), ), + // weekend day outside heating season, increase not capped ( "2019-07-07T10:15:00+02:00[Europe/Berlin]", - Celsius(19), + Celsius(19.0), true, Kilowatts(-10.0), - Kilowatts(-19.5), + Kilowatts(-12.099949463243976), ), + // working day outside heating season, decrease not capped ( "2019-07-05T05:15:00+02:00[Europe/Berlin]", - Celsius(20), + Celsius(20.0), true, Kilowatts(-20.0), - Kilowatts(-29.5), + Kilowatts(-11.70638561892377), ), + // weekend day outside heating season, increase capped ( "2019-07-06T10:15:00+02:00[Europe/Berlin]", - Celsius(20), + Celsius(20.0), true, Kilowatts(0.0), Kilowatts(-9.5), ), + // working day outside heating season, decrease capped ( "2019-07-05T05:15:00+02:00[Europe/Berlin]", - Celsius(22), + Celsius(22.0), true, Kilowatts(-22.0), - Kilowatts(-31.5), + Kilowatts(-12.5), ), ) @@ -302,14 +311,16 @@ class BMModelSpec extends UnitSpec { "MockNode", costControlled, EUR(0.05), - EuroPerKilowatthour(0.51d), + EuroPerKilowatthour(0.051d), 0.05, ) bmModel._lastPower = Some(lastPower) + val powerCalc = bmModel.calculateActivePower(ConstantState, relevantData) - powerCalc.value should be(powerSol.value) + + powerCalc should approximate(powerSol) } } } From 0445838ce24655d39d3bba2d0599a739b15384f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 05:47:39 +0000 Subject: [PATCH 07/21] Bump com.github.carueda:tscfg_2.13 from 1.0.0 to 1.1.3 (#936) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c123cf1e73..3e72aa1327 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ ext { pekkoVersion = '1.0.3' jtsVersion = '1.19.0' confluentKafkaVersion = '7.4.0' - tscfgVersion = '1.0.0' + tscfgVersion = '1.1.3' scapegoatVersion = '3.0.0' testContainerVersion = '0.41.4' From 51226842952bcea0253c2fb380865b65a0338e33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 07:21:51 +0000 Subject: [PATCH 08/21] Bump org.mockito:mockito-core from 5.12.0 to 5.13.0 (#937) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3e72aa1327..b17292a4cb 100644 --- a/build.gradle +++ b/build.gradle @@ -103,7 +103,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.12.0' // mocking framework + testImplementation 'org.mockito:mockito-core:5.13.0' // mocking framework testImplementation "org.scalatest:scalatest_${scalaVersion}:3.2.19" testRuntimeOnly 'com.vladsch.flexmark:flexmark-all:0.64.8' //scalatest html output testImplementation group: 'org.pegdown', name: 'pegdown', version: '1.6.0' From f1ef8ba8af511dd6a55fde89f4c6ec027dd55deb Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:31:41 +0200 Subject: [PATCH 09/21] Update src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index 286b0e829f..fb18a8276c 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -263,7 +263,7 @@ final case class ThermalGrid( * @param tick * Current tick * @param lastAmbientTemperature - * Ambient temperature until this tick + * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature * Actual ambient temperature * @param state From 35c358836574439e8b834a42a9805eb5b00d60e8 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:31:51 +0200 Subject: [PATCH 10/21] Update src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index fb18a8276c..376d1bec4d 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -138,7 +138,7 @@ final case class ThermalGrid( * @param lastAmbientTemperature * Ambient temperature until this tick * @param ambientTemperature - * Actual ambient temperature + * Current ambient temperature * @param state * Current state of the houses * @param qDot From d65d32efedab2cbc1b46d7598a60bab2e6ad4131 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:32:28 +0200 Subject: [PATCH 11/21] Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index 376d1bec4d..572fe5f862 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -136,7 +136,7 @@ final case class ThermalGrid( * @param tick * Current tick * @param lastAmbientTemperature - * Ambient temperature until this tick + * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature * Current ambient temperature * @param state From 4bc685e3f6de261fb06eae41f0102885bdfcc8ea Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:32:37 +0200 Subject: [PATCH 12/21] Update src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala index 0b8544fd67..ec3dd1a7a0 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala @@ -304,7 +304,7 @@ final case class ThermalHouse( * @param lastAmbientTemperature * Ambient temperature until this tick * @param ambientTemperature - * Actual ambient temperature + * Current ambient temperature * @param qDot * New thermal influx * @return From 77cd1718a5ae2812b56fdeee946cac9094a764ae Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:32:44 +0200 Subject: [PATCH 13/21] Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index 572fe5f862..0e77f808fa 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -339,7 +339,7 @@ final case class ThermalGrid( * @param formerStorageState * Previous thermal storage state before a first update was performed * @param lastAmbientTemperature - * Ambient temperature until this tick + * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature * Actual ambient temperature * @param qDot From 2591a3d4b31397894a948b2e0f3013bb7c3874b3 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:32:53 +0200 Subject: [PATCH 14/21] Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala index ec3dd1a7a0..547a639d08 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalHouse.scala @@ -302,7 +302,7 @@ final case class ThermalHouse( * @param state * Currently applicable state * @param lastAmbientTemperature - * Ambient temperature until this tick + * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature * Current ambient temperature * @param qDot From 16ecbb99f8dd0ae2df1a2cebd9363f315da29aa6 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:33:05 +0200 Subject: [PATCH 15/21] Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index 0e77f808fa..b9b71056d3 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -106,7 +106,7 @@ final case class ThermalGrid( * @param state * Currently applicable state * @param lastAmbientTemperature - * Ambient temperature until this tick + * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature * Actual ambient temperature * @param qDot From 8022318e1d3459fca28dd8ac82cf2537df7ca19c Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:33:13 +0200 Subject: [PATCH 16/21] Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index b9b71056d3..8cc3adafdf 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -341,7 +341,7 @@ final case class ThermalGrid( * @param lastAmbientTemperature * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature - * Actual ambient temperature + * Current ambient temperature * @param qDot * Thermal influx * @return From e81015f9f427f8bab795a426b7ea1f601f4a9146 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:33:20 +0200 Subject: [PATCH 17/21] Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index 8cc3adafdf..7d2a4b599d 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -108,7 +108,7 @@ final case class ThermalGrid( * @param lastAmbientTemperature * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature - * Actual ambient temperature + * Current ambient temperature * @param qDot * Thermal energy balance * @return From 4d0aaa808c38f1cd9f562ad5dced58696b44b706 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:33:28 +0200 Subject: [PATCH 18/21] Include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index 7d2a4b599d..325a90b316 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -265,7 +265,7 @@ final case class ThermalGrid( * @param lastAmbientTemperature * Ambient temperature valid up until (not including) the current tick * @param ambientTemperature - * Actual ambient temperature + * Current ambient temperature * @param state * Current state of the houses * @param qDot From 5e0f5131a0b6d8933ecdbb3676e38c934659b165 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Aug 2024 18:07:41 +0200 Subject: [PATCH 19/21] provide test for determining correct state and threshold of thermal house at temperature change --- .../model/thermal/ThermalHouseSpec.scala | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala index 56e1cac144..25c0af7301 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala @@ -6,8 +6,11 @@ package edu.ie3.simona.model.thermal +import edu.ie3.simona.model.thermal.ThermalHouse.ThermalHouseThreshold.HouseTemperatureLowerBoundaryReached +import edu.ie3.simona.model.thermal.ThermalHouse.{ThermalHouseState, startingState} import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.common.input.HpInputTestData +import edu.ie3.util.scala.quantities.DefaultQuantities.zeroKW import edu.ie3.util.scala.quantities.WattsPerKelvin import org.scalatest.prop.TableFor3 import squants.energy._ @@ -92,6 +95,33 @@ class ThermalHouseSpec extends UnitSpec with HpInputTestData { newInnerTemperature should approximate(Temperature(29, Celsius)) } + "Check for the correct state of house when ambient temperature changes" in { + val house = thermalHouse(18,22) + val initialHousestate = startingState(house) + val lastAmbientTemperature = Temperature(15, Celsius) + val ambientTemperature = Temperature(-20, Celsius) + + + val (thermalHouseState, threshold) = house.determineState( + 3600L, + initialHousestate, + lastAmbientTemperature, + ambientTemperature, + zeroKW, + ) + + thermalHouseState match { + case ThermalHouseState(tick, temperature, qDot) => { + tick shouldBe 3600L + temperature should approximate (Kelvin(292.64986111)) + qDot shouldBe zeroKW + } + case unexpected => + fail(s"Expected a thermalHouseState but got none $unexpected.") + } + threshold shouldBe Some(HouseTemperatureLowerBoundaryReached(4967)) + } + "Check build method" in { val thermalTestHouse = thermalHouse(18, 22) From 0e36a4f333e58888d8746b265d859c761fe7099a Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 28 Aug 2024 18:09:51 +0200 Subject: [PATCH 20/21] fmt --- .../ie3/simona/model/thermal/ThermalHouseSpec.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala index 25c0af7301..ff796ff1e8 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala @@ -7,7 +7,10 @@ package edu.ie3.simona.model.thermal import edu.ie3.simona.model.thermal.ThermalHouse.ThermalHouseThreshold.HouseTemperatureLowerBoundaryReached -import edu.ie3.simona.model.thermal.ThermalHouse.{ThermalHouseState, startingState} +import edu.ie3.simona.model.thermal.ThermalHouse.{ + ThermalHouseState, + startingState, +} import edu.ie3.simona.test.common.UnitSpec import edu.ie3.simona.test.common.input.HpInputTestData import edu.ie3.util.scala.quantities.DefaultQuantities.zeroKW @@ -96,12 +99,11 @@ class ThermalHouseSpec extends UnitSpec with HpInputTestData { } "Check for the correct state of house when ambient temperature changes" in { - val house = thermalHouse(18,22) + val house = thermalHouse(18, 22) val initialHousestate = startingState(house) - val lastAmbientTemperature = Temperature(15, Celsius) + val lastAmbientTemperature = Temperature(15, Celsius) val ambientTemperature = Temperature(-20, Celsius) - val (thermalHouseState, threshold) = house.determineState( 3600L, initialHousestate, @@ -113,7 +115,7 @@ class ThermalHouseSpec extends UnitSpec with HpInputTestData { thermalHouseState match { case ThermalHouseState(tick, temperature, qDot) => { tick shouldBe 3600L - temperature should approximate (Kelvin(292.64986111)) + temperature should approximate(Kelvin(292.64986111)) qDot shouldBe zeroKW } case unexpected => From 459f9efcbb30f330e324719ec67f7bbef1c35d91 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 28 Aug 2024 18:45:04 +0200 Subject: [PATCH 21/21] Removing redundant braces Signed-off-by: Sebastian Peter --- .../scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala index ff796ff1e8..20131046bf 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalHouseSpec.scala @@ -113,11 +113,10 @@ class ThermalHouseSpec extends UnitSpec with HpInputTestData { ) thermalHouseState match { - case ThermalHouseState(tick, temperature, qDot) => { + case ThermalHouseState(tick, temperature, qDot) => tick shouldBe 3600L temperature should approximate(Kelvin(292.64986111)) qDot shouldBe zeroKW - } case unexpected => fail(s"Expected a thermalHouseState but got none $unexpected.") }