From 64a67ecd5379a9d9d525902168d1ddebd499241c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 24 Aug 2024 10:32:58 +0200 Subject: [PATCH 01/44] Refactoring of ThermalGrid.handleInfeed to fix thermal storage recharge correctly when empty --- CHANGELOG.md | 1 + .../simona/model/participant/HpModel.scala | 7 + .../simona/model/thermal/ThermalGrid.scala | 334 ++++++++++++++---- .../edu/ie3/simona/agent/em/EmAgentIT.scala | 16 +- .../model/thermal/ThermalGridTestData.scala | 4 + .../ThermalGridWithHouseAndStorageSpec.scala | 8 +- .../ThermalGridWithHouseOnlySpec.scala | 12 + .../ThermalGridWithStorageOnlySpec.scala | 12 + .../test/common/input/EmInputTestData.scala | 2 +- 9 files changed, 317 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bc169d92..3f51e98bd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix activation of Hp when not under control of an EM [#922](https://github.com/ie3-institute/simona/issues/922) - Fixed ThermalStorageResults having multiple entries [#924](https://github.com/ie3-institute/simona/issues/924) - Fix determineState of ThermalHouse [#926](https://github.com/ie3-institute/simona/issues/926) +- Refactoring of `ThermalGrid.handleInfeed` to fix thermal storage recharge correctly when empty [#930](https://github.com/ie3-institute/simona/issues/930) ## [3.0.0] - 2023-08-07 diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 569bd48c10..7e2da343fe 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -217,6 +217,10 @@ final case class HpModel( * data of heat pump including state of the heat pump * @param isRunning * determines whether the heat pump is running or not + * @param houseDemand + * determines if the thermal house has heat demand + * @param storageDemand + * determines if the thermal storage has heat demand * @return * next [[HpState]] */ @@ -245,7 +249,10 @@ final case class HpModel( state.thermalGridState, state.ambientTemperature.getOrElse(relevantData.ambientTemperature), relevantData.ambientTemperature, + isRunning, newThermalPower, + houseDemand, + storageDemand, ) HpState( 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 28d299d67e..bd63a8030b 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -146,6 +146,7 @@ final case class ThermalGrid( } /** Update the current state of the grid + * * @param tick * Instance in time * @param state @@ -154,8 +155,14 @@ final case class ThermalGrid( * Ambient temperature until this tick * @param ambientTemperature * Actual ambient temperature + * @param isRunning + * determines whether the heat pump is running or not * @param qDot * Thermal energy balance + * @param houseDemand + * determines if the thermal house has heat demand + * @param storageDemand + * determines if the thermal storage has heat demand * @return * The updated state of the grid */ @@ -164,9 +171,21 @@ final case class ThermalGrid( state: ThermalGridState, lastAmbientTemperature: Temperature, ambientTemperature: Temperature, + isRunning: Boolean, qDot: Power, + houseDemand: Boolean, + storageDemand: Boolean, ): (ThermalGridState, Option[ThermalThreshold]) = if (qDot > zeroKW) - handleInfeed(tick, lastAmbientTemperature, ambientTemperature, state, qDot) + handleInfeed( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + isRunning, + qDot, + houseDemand, + storageDemand, + ) else handleConsumption( tick, @@ -176,8 +195,9 @@ final case class ThermalGrid( qDot, ) - /** Handles the case, when a grid has infeed. First, heat up all the houses to - * their maximum temperature, then fill up the storages + /** Handles the case, when a grid has infeed. Depending which entity has some + * heat demand the house or the storage will be heated up / filled up. + * * @param tick * Current tick * @param lastAmbientTemperature @@ -186,8 +206,14 @@ final case class ThermalGrid( * Actual ambient temperature * @param state * Current state of the houses + * @param isRunning + * determines whether the heat pump is running or not * @param qDot * Infeed to the grid + * @param houseDemand + * determines if the thermal house has heat demand + * @param storageDemand + * determines if the thermal storage has heat demand * @return * Updated thermal grid state */ @@ -196,41 +222,221 @@ final case class ThermalGrid( lastAmbientTemperature: Temperature, ambientTemperature: Temperature, state: ThermalGridState, + isRunning: Boolean, qDot: Power, - ): (ThermalGridState, Option[ThermalThreshold]) = - house.zip(state.houseState) match { - case Some((thermalHouse, lastHouseState)) => - /* Set thermal power exchange with storage to zero */ - // TODO: We would need to issue a storage result model here... - val updatedStorageState = storage.zip(state.storageState) match { - case Some((thermalStorage, storageState)) => - Some( - thermalStorage - .updateState( - tick, - zeroKW, - storageState, - ) - ._1 - ) - case _ => state.storageState + houseDemand: Boolean, + heatStorageDemand: Boolean, + ): (ThermalGridState, Option[ThermalThreshold]) = { + // TODO: We would need to issue a storage result model here... + + /* Consider the action in the last state */ + val (qDotHouseLastState, qDotStorageLastState) = state match { + case ThermalGridState(Some(houseState), Some(storageState)) => + (houseState.qDot, storageState.qDot) + case ThermalGridState(Some(houseState), None) => (houseState.qDot, zeroKW) + case ThermalGridState(None, Some(storageState)) => + (zeroKW, storageState.qDot) + case _ => + throw new InconsistentStateException( + "There should be at least a house or a storage state." + ) + } + + if ( + (qDotHouseLastState > zeroKW && !(qDotStorageLastState < zeroKW)) | (qDotStorageLastState > zeroKW & heatStorageDemand) + ) { + val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = + handleInfeedHouse( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDotHouseLastState, + ) + val (updatedStorageState, thermalStorageThreshold) = + if ( + qDotStorageLastState >= zeroKW && remainingQDotHouse > qDotStorageLastState + ) { + handleInfeedStorage( + tick, + state, + remainingQDotHouse, + ) + } else { + handleInfeedStorage( + tick, + state, + qDotStorageLastState, + ) } - val (updatedHouseState, maybeHouseThreshold) = - thermalHouse.determineState( + val nextThreshold = determineMostRecentThreshold( + thermalHouseThreshold, + thermalStorageThreshold, + ) + ( + state.copy( + houseState = updatedHouseState, + storageState = updatedStorageState, + ), + nextThreshold, + ) + } + // Handle edge case where house get heated from storage and HP will be activated in between + else if ((qDotHouseLastState > zeroKW && qDotStorageLastState < zeroKW)) { + if (isRunning) { + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDot, + zeroKW, + ) + } else { + + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDotHouseLastState, + qDotStorageLastState, + ) + } + } else { + + (houseDemand, heatStorageDemand) match { + + case (true, _) => + // house first then heatStorage after heating House + handleCases( tick, - lastHouseState, lastAmbientTemperature, ambientTemperature, + state, qDot, + zeroKW, ) + case (false, true) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + zeroKW, + qDot, + ) + + case (false, false) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + zeroKW, + zeroKW, + ) + case _ => + throw new InconsistentStateException( + "There should be at least a house or a storage state." + ) + } + } + } + + /** Handles the different cases, of thermal flows from and into the thermal + * grid. + * + * @param tick + * Current tick + * @param lastAmbientTemperature + * Ambient temperature until this tick + * @param ambientTemperature + * actual ambient temperature + * @param state + * Current state of the thermal grid + * @param qDotHouse + * Infeed to the house + * @param qDotStorage + * Infeed to the heat storage + * @return + * Updated thermal grid state and the next threshold if there is one + */ + private def handleCases( + tick: Long, + lastAmbientTemperature: Temperature, + ambientTemperature: Temperature, + state: ThermalGridState, + qDotHouse: Power, + qDotHeatStorage: Power, + ): (ThermalGridState, Option[ThermalThreshold]) = { + // FIXME: Is there any case where we get back some remainingQDotHouse? + val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = + handleInfeedHouse( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDotHouse, + ) + + val (updatedStorageState, thermalStorageThreshold) = + handleInfeedStorage(tick, state, qDotHeatStorage) + + val nextThreshold = determineMostRecentThreshold( + thermalHouseThreshold, + thermalStorageThreshold, + ) + + ( + state.copy( + houseState = updatedHouseState, + storageState = updatedStorageState, + ), + nextThreshold, + ) + } + + /** Handles the case, when the house has heat demand and will be heated up + * here. + * + * @param tick + * Current tick + * @param lastAmbientTemperature + * Ambient temperature until this tick + * @param ambientTemperature + * actual ambient temperature + * @param state + * Current state of the houses + * @param qDot + * Infeed to the grid + * @return + * Updated thermal house state, a ThermalThreshold and the remaining qDot + */ + private def handleInfeedHouse( + tick: Long, + lastAmbientTemperature: Temperature, + ambientTemperature: Temperature, + state: ThermalGridState, + qDot: Power, + ): (Option[ThermalHouseState], Option[ThermalThreshold], Power) = { + (house, state.houseState) match { + case (Some(thermalHouse), Some(lastHouseState)) => + val (newState, threshold) = thermalHouse.determineState( + tick, + lastHouseState, + lastAmbientTemperature, + ambientTemperature, + qDot, + ) + /* Check if house can handle the thermal feed in */ if ( thermalHouse.isInnerTemperatureTooHigh( - updatedHouseState.innerTemperature + newState.innerTemperature ) ) { - /* The house is already heated up fully, set back the infeed and put it into storage, if available */ val (fullHouseState, maybeFullHouseThreshold) = thermalHouse.determineState( tick, @@ -239,54 +445,44 @@ final case class ThermalGrid( ambientTemperature, zeroKW, ) - storage.zip(updatedStorageState) match { - case Some((thermalStorage, storageState)) => - val (updatedStorageState, maybeStorageThreshold) = - thermalStorage.updateState(tick, qDot, storageState) - - /* Both house and storage are updated. Determine what reaches the next threshold */ - val nextThreshold = determineMostRecentThreshold( - maybeFullHouseThreshold, - maybeStorageThreshold, - ) - - ( - state.copy( - houseState = Some(fullHouseState), - storageState = Some(updatedStorageState), - ), - nextThreshold, - ) - case None => - /* There is no storage, house determines the next activation */ - ( - state.copy(houseState = Some(fullHouseState)), - maybeFullHouseThreshold, - ) - } + (Some(fullHouseState), maybeFullHouseThreshold, qDot) } else { - /* The house can handle the infeed */ - ( - state.copy(houseState = Some(updatedHouseState)), - maybeHouseThreshold, - ) + (Some(newState), threshold, zeroKW) } + case _ => (None, None, zeroKW) + } + } - case None => - storage.zip(state.storageState) match { - case Some((thermalStorage, storageState)) => - val (updatedStorageState, maybeStorageThreshold) = - thermalStorage.updateState(tick, qDot, storageState) - ( - state.copy(storageState = Some(updatedStorageState)), - maybeStorageThreshold, - ) - case None => - throw new InconsistentStateException( - "A thermal grid has to contain either at least a house or a storage." - ) - } + /** Handles the cases, when the storage has heat demand and will be filled up + * here (positive qDot) or will be return its stored energy into the thermal + * grid (negative qDot). + * @param tick + * Current tick + * @param ambientTemperature + * Ambient temperature + * @param state + * Current state of the houses + * @param qDot + * Infeed to the grid + * @return + * Updated thermal grid state + */ + private def handleInfeedStorage( + tick: Long, + state: ThermalGridState, + qDot: Power, + ): (Option[ThermalStorageState], Option[ThermalThreshold]) = { + (storage, state.storageState) match { + case (Some(thermalStorage), Some(lastStorageState)) => + val (newState, threshold) = thermalStorage.updateState( + tick, + qDot, + lastStorageState, + ) + (Some(newState), threshold) + case _ => (None, None) } + } private def determineMostRecentThreshold( maybeHouseThreshold: Option[ThermalThreshold], diff --git a/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala b/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala index 09f6acb019..be1cee377f 100644 --- a/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala +++ b/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala @@ -680,7 +680,7 @@ class EmAgentIT Celsius(0d), MetersPerSecond(0d), ), - Some(28800), + Some(56000), ) } @@ -692,26 +692,26 @@ class EmAgentIT emResult.getQ should equalWithTolerance(0.000088285537.asMegaVar) } - scheduler.expectMessage(Completion(emAgentActivation, Some(28665))) + scheduler.expectMessage(Completion(emAgentActivation, Some(44398))) - /* TICK 28666 + /* TICK 44398 LOAD: 0.000269 MW (unchanged) PV: -0.000032 MW (unchanged) Heat pump: Is turned on again and cannot be turned off -> flex signal is no control -> 0.00485 MW */ - emAgentActivation ! Activation(28665) + emAgentActivation ! Activation(44398) resultListener.expectMessageType[ParticipantResultEvent] match { case ParticipantResultEvent(emResult: EmResult) => emResult.getInputModel shouldBe emInput.getUuid - emResult.getTime shouldBe 28665.toDateTime - emResult.getP should equalWithTolerance(0.0050867679996.asMegaWatt) - emResult.getQ should equalWithTolerance(0.001073120040.asMegaVar) + emResult.getTime shouldBe 44398.toDateTime + emResult.getP should equalWithTolerance(0.005086768.asMegaWatt) + emResult.getQ should equalWithTolerance(0.00107312004.asMegaVar) } - scheduler.expectMessage(Completion(emAgentActivation, Some(28800))) + scheduler.expectMessage(Completion(emAgentActivation, Some(56000))) } } diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala index 6011c6caf2..0a016d4566 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala @@ -25,4 +25,8 @@ trait ThermalGridTestData { protected val testGridQDotInfeed: Power = Kilowatts(15d) protected val testGridQDotConsumption: Power = Kilowatts(-42d) protected val testGridQDotConsumptionHigh: Power = Kilowatts(-200d) + protected val noThermalDemand: Boolean = false + protected val thermalDemand: Boolean = true + protected val isRunning: Boolean = true + protected val isNotRunning: Boolean = false } diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala index 1ea45a656d..b2b732ae0e 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala @@ -496,7 +496,10 @@ class ThermalGridWithHouseAndStorageSpec testGridAmbientTemperature, testGridAmbientTemperature, initialGridState, + isNotRunning, externalQDot, + thermalDemand, + noThermalDemand, ) updatedGridState match { @@ -510,7 +513,7 @@ class ThermalGridWithHouseAndStorageSpec innerTemperature should approximate(Celsius(18.9999d)) qDotHouse should approximate(externalQDot) - storageTick shouldBe -1L + storageTick shouldBe 0L storedEnergy should approximate( initialGridState.storageState .map(_.storedEnergy) @@ -542,7 +545,10 @@ class ThermalGridWithHouseAndStorageSpec testGridAmbientTemperature, testGridAmbientTemperature, gridState, + isNotRunning, externalQDot, + noThermalDemand, + thermalDemand, ) updatedGridState match { diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala index eb447d0fc4..4ecbfc819b 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala @@ -179,7 +179,10 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { testGridAmbientTemperature, testGridAmbientTemperature, gridState, + isNotRunning, testGridQDotInfeed, + thermalDemand, + noThermalDemand, ) updatedGridState match { @@ -205,7 +208,10 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ThermalGrid.startingState(thermalGrid), testGridAmbientTemperature, testGridAmbientTemperature, + isRunning, testGridQDotInfeed, + thermalDemand, + noThermalDemand, ) match { case ( ThermalGridState( @@ -228,7 +234,10 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ThermalGrid.startingState(thermalGrid), testGridAmbientTemperature, testGridAmbientTemperature, + isNotRunning, testGridQDotConsumption, + thermalDemand, + noThermalDemand, ) match { case ( ThermalGridState( @@ -251,7 +260,10 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ThermalGrid.startingState(thermalGrid), testGridAmbientTemperature, testGridAmbientTemperature, + isNotRunning, Megawatts(0d), + thermalDemand, + noThermalDemand, ) match { case ( ThermalGridState( diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala index 93a45e3180..c1ded4c6dc 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala @@ -182,7 +182,10 @@ class ThermalGridWithStorageOnlySpec testGridAmbientTemperature, testGridAmbientTemperature, gridState, + isNotRunning, testGridQDotInfeed, + noThermalDemand, + thermalDemand, ) updatedGridState match { @@ -206,7 +209,10 @@ class ThermalGridWithStorageOnlySpec ThermalGrid.startingState(thermalGrid), testGridAmbientTemperature, testGridAmbientTemperature, + isRunning, testGridQDotInfeed, + noThermalDemand, + thermalDemand, ) nextThreshold shouldBe Some(StorageFull(276000L)) @@ -239,7 +245,10 @@ class ThermalGridWithStorageOnlySpec ), testGridAmbientTemperature, testGridAmbientTemperature, + isRunning, testGridQDotConsumptionHigh, + thermalDemand, + noThermalDemand, ) match { case ( ThermalGridState( @@ -262,7 +271,10 @@ class ThermalGridWithStorageOnlySpec ThermalGrid.startingState(thermalGrid), testGridAmbientTemperature, testGridAmbientTemperature, + isRunning, Kilowatts(0d), + noThermalDemand, + noThermalDemand, ) updatedState match { case ( diff --git a/src/test/scala/edu/ie3/simona/test/common/input/EmInputTestData.scala b/src/test/scala/edu/ie3/simona/test/common/input/EmInputTestData.scala index c5f3cf8efe..9c5abd30de 100644 --- a/src/test/scala/edu/ie3/simona/test/common/input/EmInputTestData.scala +++ b/src/test/scala/edu/ie3/simona/test/common/input/EmInputTestData.scala @@ -140,7 +140,7 @@ trait EmInputTestData UUID.fromString("91940626-bdd0-41cf-96dd-47c94c86b20e"), "thermal house", thermalBusInput, - Quantities.getQuantity(0.325, StandardUnits.THERMAL_TRANSMISSION), + Quantities.getQuantity(0.15, StandardUnits.THERMAL_TRANSMISSION), Quantities.getQuantity(75, StandardUnits.HEAT_CAPACITY), Quantities.getQuantity(20.3, StandardUnits.TEMPERATURE), Quantities.getQuantity(22.0, StandardUnits.TEMPERATURE), From a669b5bb5caad4d0da12da3df0432c3ca7a0152f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 15:14:32 +0100 Subject: [PATCH 02/44] remove double entry in changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 201736009b..ae3049db15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,7 +130,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix power flow calculation with em agents [#962](https://github.com/ie3-institute/simona/issues/962) - Fix scheduling at Evcs with more than one Ev at a time without Em [#787](https://github.com/ie3-institute/simona/issues/787) - Fix CheckWindow duration [#921](https://github.com/ie3-institute/simona/issues/921) -- Fixed ThermalStorageResults having multiple entries [#924](https://github.com/ie3-institute/simona/issues/924) - Fix filter for thermal result checking for lastTick not for currentTick [#1008](https://github.com/ie3-institute/simona/issues/1008) - Fixed `CHANGELOG` entry for issue ([#103](https://github.com/ie3-institute/simona/issues/103)) [#941](https://github.com/ie3-institute/simona/issues/941) - Refactoring of `ThermalGrid.handleInfeed` to fix thermal storage recharge correctly when empty [#930](https://github.com/ie3-institute/simona/issues/930) From 78845417a5343532013e3f725ae4d2938de731d1 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 15:16:24 +0100 Subject: [PATCH 03/44] Revert "remove double entry in changelog" This reverts commit a669b5bb5caad4d0da12da3df0432c3ca7a0152f. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae3049db15..201736009b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,6 +130,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix power flow calculation with em agents [#962](https://github.com/ie3-institute/simona/issues/962) - Fix scheduling at Evcs with more than one Ev at a time without Em [#787](https://github.com/ie3-institute/simona/issues/787) - Fix CheckWindow duration [#921](https://github.com/ie3-institute/simona/issues/921) +- Fixed ThermalStorageResults having multiple entries [#924](https://github.com/ie3-institute/simona/issues/924) - Fix filter for thermal result checking for lastTick not for currentTick [#1008](https://github.com/ie3-institute/simona/issues/1008) - Fixed `CHANGELOG` entry for issue ([#103](https://github.com/ie3-institute/simona/issues/103)) [#941](https://github.com/ie3-institute/simona/issues/941) - Refactoring of `ThermalGrid.handleInfeed` to fix thermal storage recharge correctly when empty [#930](https://github.com/ie3-institute/simona/issues/930) From 86b3256c41ea8e140cccedd0684c7745fbade8c9 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 15:16:48 +0100 Subject: [PATCH 04/44] remove correct double entry in changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 201736009b..1c7137c826 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -122,7 +122,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed FixedFeedModelSpec [#861](https://github.com/ie3-institute/simona/issues/861) - Fixing duration calculation in result events [#801](https://github.com/ie3-institute/simona/issues/801) - Handle MobSim requests for current prices [#892](https://github.com/ie3-institute/simona/issues/892) -- Fixed ThermalStorageResults having multiple entries [#924](https://github.com/ie3-institute/simona/issues/924) - Fix determineState of ThermalHouse [#926](https://github.com/ie3-institute/simona/issues/926) - Fix activation of Hp when not under control of an EM [#922](https://github.com/ie3-institute/simona/issues/922) - Fix expected secondaryData in baseStateData [#955](https://github.com/ie3-institute/simona/issues/955) From f4fa8108db07bbfaf3cc68690d2cc5a53ba80c30 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 15:38:09 +0100 Subject: [PATCH 05/44] reintroduce demand booleans indicating demand when handle thermal infeed --- .../simona/model/participant/HpModel.scala | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index c64e677ad6..52e1462681 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -143,7 +143,7 @@ final case class HpModel( ) // Determining the operation point and limitations at this tick - val (turnOn, canOperate, canBeOutOfOperation) = + val (turnOn, canOperate, canBeOutOfOperation, houseDemand, storageDemand) = operatesInNextState( lastHpState, currentThermalGridState, @@ -154,7 +154,7 @@ final case class HpModel( // Updating the HpState val updatedState = - calcState(lastHpState, relevantData, turnOn) + calcState(lastHpState, relevantData, turnOn, houseDemand, storageDemand) (canOperate, canBeOutOfOperation, updatedState) } @@ -176,7 +176,8 @@ final case class HpModel( * ThermalEnergyDemand of the thermal storage * @return * boolean defining if heat pump runs in next time step, if it can be in - * operation and can be out of operation + * operation and can be out of operation plus the demand of house and + * storage */ private def operatesInNextState( lastState: HpState, @@ -184,7 +185,7 @@ final case class HpModel( relevantData: HpRelevantData, demandHouse: ThermalEnergyDemand, demandThermalStorage: ThermalEnergyDemand, - ): (Boolean, Boolean, Boolean) = { + ): (Boolean, Boolean, Boolean, Boolean, Boolean) = { val ( houseHasDemand, @@ -206,7 +207,13 @@ final case class HpModel( val canBeOutOfOperation = !(demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) - (turnHpOn, canOperate, canBeOutOfOperation) + ( + turnHpOn, + canOperate, + canBeOutOfOperation, + houseHasDemand, + heatStorageHasDemand, + ) } /** This method will return booleans whether there is a heat demand of house @@ -268,6 +275,8 @@ final case class HpModel( lastState: HpState, relevantData: HpRelevantData, isRunning: Boolean, + houseDemand: Boolean, + storageDemand: Boolean, ): HpState = { val lastStateStorageQDot = lastState.thermalGridState.storageState .map(_.qDot) @@ -353,13 +362,38 @@ final case class HpModel( lastState: HpState, setPower: Power, ): (HpState, FlexChangeIndicator) = { - /* If the setpoint value is above 50 % of the electrical power, turn on the heat pump otherwise turn it off */ + /* If the set point value is above 50 % of the electrical power, turn on the heat pump otherwise turn it off */ val turnOn = setPower > (sRated * cosPhiRated * 0.5) + val ( + thermalEnergyDemandHouse, + thermalEnergyDemandStorage, + updatedThermalGridState, + ) = + thermalGrid.energyDemandAndUpdatedState( + data.currentTick, + lastState.ambientTemperature.getOrElse(data.ambientTemperature), + data.ambientTemperature, + lastState.thermalGridState, + ) + + val ( + houseDemand, + heatStorageDemand, + _, + ) = determineDemandBooleans( + lastState, + updatedThermalGridState, + thermalEnergyDemandHouse, + thermalEnergyDemandStorage, + ) + val updatedHpState = calcState( lastState, data, turnOn, + houseDemand, + heatStorageDemand, ) ( From 963670c1013283559080bbc96256d9ff02a28cf0 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 15:49:21 +0100 Subject: [PATCH 06/44] add some scala doc --- .../edu/ie3/simona/model/thermal/ThermalGrid.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 cd2c19691c..b59663a783 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -485,6 +485,16 @@ final case class ThermalGrid( } } + /** Determines the most recent threshold of two given input thresholds + * + * @param maybeHouseThreshold + * Option of a possible next threshold of the thermal house + * @param maybeStorageThreshold + * Option of a possible next threshold of the thermal storage + * @return + * The next threshold + */ + private def determineMostRecentThreshold( maybeHouseThreshold: Option[ThermalThreshold], maybeStorageThreshold: Option[ThermalThreshold], From bfd633b6e7194f2ffe8de6f9ac59c3927d4e4a65 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 15:54:32 +0100 Subject: [PATCH 07/44] handle sonar code smell --- .../ie3/simona/model/thermal/ThermalGrid.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 b59663a783..82b9e9535c 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -244,7 +244,7 @@ final case class ThermalGrid( } if ( - (qDotHouseLastState > zeroKW && !(qDotStorageLastState < zeroKW)) | (qDotStorageLastState > zeroKW & heatStorageDemand) + (qDotHouseLastState >= zeroKW && !(qDotStorageLastState >= zeroKW)) | (qDotStorageLastState >= zeroKW & heatStorageDemand) ) { val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = handleInfeedHouse( @@ -486,14 +486,14 @@ final case class ThermalGrid( } /** Determines the most recent threshold of two given input thresholds - * - * @param maybeHouseThreshold - * Option of a possible next threshold of the thermal house - * @param maybeStorageThreshold - * Option of a possible next threshold of the thermal storage - * @return - * The next threshold - */ + * + * @param maybeHouseThreshold + * Option of a possible next threshold of the thermal house + * @param maybeStorageThreshold + * Option of a possible next threshold of the thermal storage + * @return + * The next threshold + */ private def determineMostRecentThreshold( maybeHouseThreshold: Option[ThermalThreshold], From 9eee88668b0bab34914708d075170411092faac9 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 16:07:48 +0100 Subject: [PATCH 08/44] Revert "handle sonar code smell" This reverts commit bfd633b6e7194f2ffe8de6f9ac59c3927d4e4a65. --- .../ie3/simona/model/thermal/ThermalGrid.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 82b9e9535c..b59663a783 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -244,7 +244,7 @@ final case class ThermalGrid( } if ( - (qDotHouseLastState >= zeroKW && !(qDotStorageLastState >= zeroKW)) | (qDotStorageLastState >= zeroKW & heatStorageDemand) + (qDotHouseLastState > zeroKW && !(qDotStorageLastState < zeroKW)) | (qDotStorageLastState > zeroKW & heatStorageDemand) ) { val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = handleInfeedHouse( @@ -486,14 +486,14 @@ final case class ThermalGrid( } /** Determines the most recent threshold of two given input thresholds - * - * @param maybeHouseThreshold - * Option of a possible next threshold of the thermal house - * @param maybeStorageThreshold - * Option of a possible next threshold of the thermal storage - * @return - * The next threshold - */ + * + * @param maybeHouseThreshold + * Option of a possible next threshold of the thermal house + * @param maybeStorageThreshold + * Option of a possible next threshold of the thermal storage + * @return + * The next threshold + */ private def determineMostRecentThreshold( maybeHouseThreshold: Option[ThermalThreshold], From 122cb6991bf069c948024c7ad330d2c1d93dc0fe Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 16:11:37 +0100 Subject: [PATCH 09/44] handle sonar code smell --- 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 b59663a783..6b1af8ac04 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -244,7 +244,7 @@ final case class ThermalGrid( } if ( - (qDotHouseLastState > zeroKW && !(qDotStorageLastState < zeroKW)) | (qDotStorageLastState > zeroKW & heatStorageDemand) + (qDotHouseLastState > zeroKW && (qDotStorageLastState >= zeroKW)) | (qDotStorageLastState > zeroKW & heatStorageDemand) ) { val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = handleInfeedHouse( From eba3b89c350226b3cb3df4492ee8c3cf189865c2 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 08:17:35 +0100 Subject: [PATCH 10/44] fmt --- .../ie3/simona/model/thermal/ThermalGrid.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 6b1af8ac04..fe90773420 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -486,14 +486,14 @@ final case class ThermalGrid( } /** Determines the most recent threshold of two given input thresholds - * - * @param maybeHouseThreshold - * Option of a possible next threshold of the thermal house - * @param maybeStorageThreshold - * Option of a possible next threshold of the thermal storage - * @return - * The next threshold - */ + * + * @param maybeHouseThreshold + * Option of a possible next threshold of the thermal house + * @param maybeStorageThreshold + * Option of a possible next threshold of the thermal storage + * @return + * The next threshold + */ private def determineMostRecentThreshold( maybeHouseThreshold: Option[ThermalThreshold], From 1f6311fe7f0a0da1434e8fd604a503bdfc2c821f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 08:26:51 +0100 Subject: [PATCH 11/44] fix scala doc --- .../scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 fe90773420..b20742d5b6 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -213,7 +213,7 @@ final case class ThermalGrid( * Infeed to the grid * @param houseDemand * determines if the thermal house has heat demand - * @param storageDemand + * @param heatStorageDemand * determines if the thermal storage has heat demand * @return * Updated thermal grid state @@ -360,7 +360,7 @@ final case class ThermalGrid( * Current state of the thermal grid * @param qDotHouse * Infeed to the house - * @param qDotStorage + * @param qDotHeatStorage * Infeed to the heat storage * @return * Updated thermal grid state and the next threshold if there is one @@ -459,8 +459,6 @@ final case class ThermalGrid( * grid (negative qDot). * @param tick * Current tick - * @param ambientTemperature - * Ambient temperature * @param state * Current state of the houses * @param qDot From 95d0562cb88694ba44145dd968307f7c5c850f8e Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 11:12:20 +0100 Subject: [PATCH 12/44] refactor demand booleans of thermal units into ThermalDemandIndicator class --- .../simona/model/participant/HpModel.scala | 46 +++++++++---------- .../simona/model/thermal/ThermalGrid.scala | 41 ++++++++++------- .../model/thermal/ThermalGridTestData.scala | 9 +++- .../ThermalGridWithHouseAndStorageSpec.scala | 6 +-- .../ThermalGridWithHouseOnlySpec.scala | 12 ++--- .../ThermalGridWithStorageOnlySpec.scala | 10 ++-- 6 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 52e1462681..a7a585820b 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -12,6 +12,7 @@ import edu.ie3.simona.model.SystemComponent import edu.ie3.simona.model.participant.HpModel.{HpRelevantData, HpState} import edu.ie3.simona.model.participant.control.QControl import edu.ie3.simona.model.thermal.ThermalGrid.{ + ThermalDemandIndicator, ThermalEnergyDemand, ThermalGridState, } @@ -143,7 +144,7 @@ final case class HpModel( ) // Determining the operation point and limitations at this tick - val (turnOn, canOperate, canBeOutOfOperation, houseDemand, storageDemand) = + val (turnOn, canOperate, canBeOutOfOperation, demandIndicator) = operatesInNextState( lastHpState, currentThermalGridState, @@ -154,7 +155,7 @@ final case class HpModel( // Updating the HpState val updatedState = - calcState(lastHpState, relevantData, turnOn, houseDemand, storageDemand) + calcState(lastHpState, relevantData, turnOn, demandIndicator) (canOperate, canBeOutOfOperation, updatedState) } @@ -176,8 +177,8 @@ final case class HpModel( * ThermalEnergyDemand of the thermal storage * @return * boolean defining if heat pump runs in next time step, if it can be in - * operation and can be out of operation plus the demand of house and - * storage + * operation and can be out of operation plus the + * [[ThermalDemandIndicator]] of the thermal units */ private def operatesInNextState( lastState: HpState, @@ -185,11 +186,10 @@ final case class HpModel( relevantData: HpRelevantData, demandHouse: ThermalEnergyDemand, demandThermalStorage: ThermalEnergyDemand, - ): (Boolean, Boolean, Boolean, Boolean, Boolean) = { + ): (Boolean, Boolean, Boolean, ThermalDemandIndicator) = { val ( - houseHasDemand, - heatStorageHasDemand, + demandIndicator, noThermalStorageOrThermalStorageIsEmpty, ) = determineDemandBooleans( lastState, @@ -198,8 +198,8 @@ final case class HpModel( demandThermalStorage, ) - val turnHpOn: Boolean = - houseHasDemand || heatStorageHasDemand + val turnHpOn = + demandIndicator.houseDemand || demandIndicator.heatStorageDemand val canOperate = demandHouse.hasRequiredDemand || demandHouse.hasAdditionalDemand || @@ -211,8 +211,7 @@ final case class HpModel( turnHpOn, canOperate, canBeOutOfOperation, - houseHasDemand, - heatStorageHasDemand, + demandIndicator, ) } @@ -239,7 +238,7 @@ final case class HpModel( updatedGridState: ThermalGridState, demandHouse: ThermalEnergyDemand, demandThermalStorage: ThermalEnergyDemand, - ): (Boolean, Boolean, Boolean) = { + ): (ThermalDemandIndicator, Boolean) = { implicit val tolerance: Energy = KilowattHours(1e-3) val noThermalStorageOrThermalStorageIsEmpty: Boolean = updatedGridState.storageState.isEmpty || updatedGridState.storageState @@ -251,7 +250,9 @@ final case class HpModel( (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || (lastHpState.isRunning && demandHouse.hasAdditionalDemand) val heatStorageDemand = demandThermalStorage.hasRequiredDemand || (lastHpState.isRunning && demandThermalStorage.hasAdditionalDemand) - (houseDemand, heatStorageDemand, noThermalStorageOrThermalStorageIsEmpty) + + val demandIndicator = ThermalDemandIndicator(houseDemand, heatStorageDemand) + (demandIndicator, noThermalStorageOrThermalStorageIsEmpty) } /** Calculate state depending on whether heat pump is needed or not. Also @@ -264,10 +265,9 @@ final case class HpModel( * data of heat pump including state of the heat pump * @param isRunning * determines whether the heat pump is running or not - * @param houseDemand - * determines if the thermal house has heat demand - * @param storageDemand - * determines if the thermal storage has heat demand + * @param demandIndicator + * determines if the thermal units (house, storage) having some heat demand + * or not * @return * next [[HpState]] */ @@ -275,8 +275,7 @@ final case class HpModel( lastState: HpState, relevantData: HpRelevantData, isRunning: Boolean, - houseDemand: Boolean, - storageDemand: Boolean, + demandIndicator: ThermalDemandIndicator, ): HpState = { val lastStateStorageQDot = lastState.thermalGridState.storageState .map(_.qDot) @@ -298,8 +297,7 @@ final case class HpModel( relevantData.ambientTemperature, isRunning, newThermalPower, - houseDemand, - storageDemand, + demandIndicator, ) HpState( @@ -378,8 +376,7 @@ final case class HpModel( ) val ( - houseDemand, - heatStorageDemand, + demandIndicator, _, ) = determineDemandBooleans( lastState, @@ -392,8 +389,7 @@ final case class HpModel( lastState, data, turnOn, - houseDemand, - heatStorageDemand, + demandIndicator, ) ( 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 b20742d5b6..8e603fe512 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -15,6 +15,7 @@ import edu.ie3.datamodel.models.result.thermal.{ } import edu.ie3.simona.exceptions.agent.InconsistentStateException import edu.ie3.simona.model.thermal.ThermalGrid.{ + ThermalDemandIndicator, ThermalEnergyDemand, ThermalGridState, } @@ -160,10 +161,9 @@ final case class ThermalGrid( * determines whether the heat pump is running or not * @param qDot * Thermal energy balance - * @param houseDemand - * determines if the thermal house has heat demand - * @param storageDemand - * determines if the thermal storage has heat demand + * @param demandIndicator + * determines if the thermal units (house, storage) having some heat demand + * or not * @return * The updated state of the grid */ @@ -174,8 +174,7 @@ final case class ThermalGrid( ambientTemperature: Temperature, isRunning: Boolean, qDot: Power, - houseDemand: Boolean, - storageDemand: Boolean, + demandIndicator: ThermalDemandIndicator, ): (ThermalGridState, Option[ThermalThreshold]) = if (qDot > zeroKW) handleInfeed( tick, @@ -184,8 +183,7 @@ final case class ThermalGrid( state, isRunning, qDot, - houseDemand, - storageDemand, + demandIndicator, ) else handleConsumption( @@ -211,10 +209,9 @@ final case class ThermalGrid( * determines whether the heat pump is running or not * @param qDot * Infeed to the grid - * @param houseDemand - * determines if the thermal house has heat demand - * @param heatStorageDemand - * determines if the thermal storage has heat demand + * @param demandIndicator + * determines if the thermal units (house, storage) having some heat demand + * or not * @return * Updated thermal grid state */ @@ -225,8 +222,7 @@ final case class ThermalGrid( state: ThermalGridState, isRunning: Boolean, qDot: Power, - houseDemand: Boolean, - heatStorageDemand: Boolean, + demandIndicator: ThermalDemandIndicator, ): (ThermalGridState, Option[ThermalThreshold]) = { // TODO: We would need to issue a storage result model here... @@ -244,7 +240,7 @@ final case class ThermalGrid( } if ( - (qDotHouseLastState > zeroKW && (qDotStorageLastState >= zeroKW)) | (qDotStorageLastState > zeroKW & heatStorageDemand) + (qDotHouseLastState > zeroKW && (qDotStorageLastState >= zeroKW)) | (qDotStorageLastState > zeroKW & demandIndicator.heatStorageDemand) ) { val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = handleInfeedHouse( @@ -307,7 +303,7 @@ final case class ThermalGrid( } } else { - (houseDemand, heatStorageDemand) match { + (demandIndicator.houseDemand, demandIndicator.heatStorageDemand) match { case (true, _) => // house first then heatStorage after heating House @@ -742,6 +738,19 @@ object ThermalGrid { thermalGrid.storage.map(_.startingState), ) + /** Wraps booleans indicating the demand of thermal units (thermal house, + * thermal storage). + * + * @param houseDemand + * Boolean indicating the demand of the thermal house + * @param heatStorageDemand + * Boolean indicating the demand of the thermal heat storage + */ + final case class ThermalDemandIndicator private ( + houseDemand: Boolean, + heatStorageDemand: Boolean, + ) + /** Defines the thermal energy demand of a thermal grid. It comprises the * absolutely required energy demand to reach the target state as well as an * energy, that can be handled. The possible energy always has to be greater diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala index 0a016d4566..21f27b1892 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala @@ -9,6 +9,7 @@ package edu.ie3.simona.model.thermal import edu.ie3.datamodel.models.OperationTime import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput +import edu.ie3.simona.model.thermal.ThermalGrid.ThermalDemandIndicator import squants.energy.{Kilowatts, Power} import squants.thermal.{Celsius, Temperature} @@ -25,8 +26,12 @@ trait ThermalGridTestData { protected val testGridQDotInfeed: Power = Kilowatts(15d) protected val testGridQDotConsumption: Power = Kilowatts(-42d) protected val testGridQDotConsumptionHigh: Power = Kilowatts(-200d) - protected val noThermalDemand: Boolean = false - protected val thermalDemand: Boolean = true + protected val noThermalDemand: ThermalDemandIndicator = + ThermalDemandIndicator(false, false) + protected val onlyThermalDemandOfHouse: ThermalDemandIndicator = + ThermalDemandIndicator(true, false) + protected val onlyThermalDemandOfHeatStorage: ThermalDemandIndicator = + ThermalDemandIndicator(false, true) protected val isRunning: Boolean = true protected val isNotRunning: Boolean = false } diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala index b2b732ae0e..ce58b6a52a 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala @@ -498,8 +498,7 @@ class ThermalGridWithHouseAndStorageSpec initialGridState, isNotRunning, externalQDot, - thermalDemand, - noThermalDemand, + onlyThermalDemandOfHouse, ) updatedGridState match { @@ -547,8 +546,7 @@ class ThermalGridWithHouseAndStorageSpec gridState, isNotRunning, externalQDot, - noThermalDemand, - thermalDemand, + onlyThermalDemandOfHeatStorage, ) updatedGridState match { diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala index 4ecbfc819b..39a614e92c 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala @@ -181,8 +181,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { gridState, isNotRunning, testGridQDotInfeed, - thermalDemand, - noThermalDemand, + onlyThermalDemandOfHouse, ) updatedGridState match { @@ -210,8 +209,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { testGridAmbientTemperature, isRunning, testGridQDotInfeed, - thermalDemand, - noThermalDemand, + onlyThermalDemandOfHouse, ) match { case ( ThermalGridState( @@ -236,8 +234,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { testGridAmbientTemperature, isNotRunning, testGridQDotConsumption, - thermalDemand, - noThermalDemand, + onlyThermalDemandOfHouse, ) match { case ( ThermalGridState( @@ -262,8 +259,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { testGridAmbientTemperature, isNotRunning, Megawatts(0d), - thermalDemand, - noThermalDemand, + onlyThermalDemandOfHouse, ) match { case ( ThermalGridState( diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala index c1ded4c6dc..c2c1880fef 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala @@ -184,8 +184,7 @@ class ThermalGridWithStorageOnlySpec gridState, isNotRunning, testGridQDotInfeed, - noThermalDemand, - thermalDemand, + onlyThermalDemandOfHeatStorage, ) updatedGridState match { @@ -211,8 +210,7 @@ class ThermalGridWithStorageOnlySpec testGridAmbientTemperature, isRunning, testGridQDotInfeed, - noThermalDemand, - thermalDemand, + onlyThermalDemandOfHeatStorage, ) nextThreshold shouldBe Some(StorageFull(276000L)) @@ -247,8 +245,7 @@ class ThermalGridWithStorageOnlySpec testGridAmbientTemperature, isRunning, testGridQDotConsumptionHigh, - thermalDemand, - noThermalDemand, + onlyThermalDemandOfHouse, ) match { case ( ThermalGridState( @@ -274,7 +271,6 @@ class ThermalGridWithStorageOnlySpec isRunning, Kilowatts(0d), noThermalDemand, - noThermalDemand, ) updatedState match { case ( From 7341e10ac9e99eb80fb765ce6424be51557a13d5 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 14:09:46 +0100 Subject: [PATCH 13/44] remove unnecessary value --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 b74c8ffa04..f50b493b9c 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -369,8 +369,7 @@ final case class ThermalGrid( qDotHouse: Power, qDotHeatStorage: Power, ): (ThermalGridState, Option[ThermalThreshold]) = { - // FIXME: Is there any case where we get back some remainingQDotHouse? - val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = + val (updatedHouseState, thermalHouseThreshold, _) = handleInfeedHouse( tick, lastAmbientTemperature, From debae480c15738ce24e34f4f5d72c82e0c96742c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 22 Nov 2024 17:01:34 +0100 Subject: [PATCH 14/44] refactoring thermal demand indicators --- .../simona/model/participant/HpModel.scala | 88 ++++++------------- .../simona/model/thermal/ThermalGrid.scala | 62 ++++++------- .../model/participant/HpModelSpec.scala | 2 +- .../model/thermal/ThermalGridTestData.scala | 29 ++++-- .../ThermalGridWithHouseAndStorageSpec.scala | 11 ++- .../ThermalGridWithHouseOnlySpec.scala | 7 +- .../ThermalGridWithStorageOnlySpec.scala | 8 +- 7 files changed, 100 insertions(+), 107 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 3400fa15c8..76e9f24651 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -12,8 +12,7 @@ import edu.ie3.simona.model.SystemComponent import edu.ie3.simona.model.participant.HpModel.{HpRelevantData, HpState} import edu.ie3.simona.model.participant.control.QControl import edu.ie3.simona.model.thermal.ThermalGrid.{ - ThermalDemandIndicator, - ThermalEnergyDemand, + ThermalDemandWrapper, ThermalGridState, } import edu.ie3.simona.model.thermal.{ThermalGrid, ThermalThreshold} @@ -133,7 +132,7 @@ final case class HpModel( ): (Boolean, Boolean, HpState) = { // Use lastHpState and relevantData to update state of thermalGrid to the current tick - val (demandHouse, demandThermalStorage, currentThermalGridState) = + val (thermalDemandWrapper, currentThermalGridState) = thermalGrid.energyDemandAndUpdatedState( relevantData.currentTick, lastHpState.ambientTemperature.getOrElse( @@ -144,18 +143,17 @@ final case class HpModel( ) // Determining the operation point and limitations at this tick - val (turnOn, canOperate, canBeOutOfOperation, demandIndicator) = + val (turnOn, canOperate, canBeOutOfOperation) = operatesInNextState( lastHpState, currentThermalGridState, relevantData, - demandHouse, - demandThermalStorage, + thermalDemandWrapper, ) // Updating the HpState val updatedState = - calcState(lastHpState, relevantData, turnOn, demandIndicator) + calcState(lastHpState, relevantData, turnOn, thermalDemandWrapper) (canOperate, canBeOutOfOperation, updatedState) } @@ -171,35 +169,30 @@ final case class HpModel( * to current tick updated state of the thermalGrid * @param relevantData * Relevant (external) data - * @param demandHouse - * ThermalEnergyDemand of the house - * @param demandThermalStorage - * ThermalEnergyDemand of the thermal storage + * @param thermalDemands + * ThermalEnergyDemand of the house and the thermal storage * @return * boolean defining if heat pump runs in next time step, if it can be in - * operation and can be out of operation plus the - * [[ThermalDemandIndicator]] of the thermal units + * operation and can be out of operation */ private def operatesInNextState( lastState: HpState, currentThermalGridState: ThermalGridState, relevantData: HpRelevantData, - demandHouse: ThermalEnergyDemand, - demandThermalStorage: ThermalEnergyDemand, - ): (Boolean, Boolean, Boolean, ThermalDemandIndicator) = { + thermalDemands: ThermalDemandWrapper, + ): (Boolean, Boolean, Boolean) = { - val ( - demandIndicator, - noThermalStorageOrThermalStorageIsEmpty, - ) = determineDemandBooleans( + val demandHouse = thermalDemands.houseDemand + val demandThermalStorage = thermalDemands.heatStorageDemand + + val noThermalStorageOrThermalStorageIsEmpty = determineThermalStorageStatus( lastState, currentThermalGridState, - demandHouse, - demandThermalStorage, ) val turnHpOn = - demandIndicator.houseDemand || demandIndicator.heatStorageDemand + (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || + demandThermalStorage.hasRequiredDemand || (demandThermalStorage.hasAdditionalDemand && lastState.isRunning) val canOperate = demandHouse.hasRequiredDemand || demandHouse.hasAdditionalDemand || @@ -211,7 +204,6 @@ final case class HpModel( turnHpOn, canOperate, canBeOutOfOperation, - demandIndicator, ) } @@ -223,22 +215,14 @@ final case class HpModel( * Current state of the heat pump * @param updatedGridState * The updated state of the [[ThermalGrid]] - * @param demandHouse - * heat demand of the thermal house - * @param demandThermalStorage - * heat demand of the thermal storage * @return - * First boolean is true, if house has heat demand. Second boolean is true, - * if thermalStorage has heat demand. Third boolean is true, if there is no - * thermalStorage, or it's empty. + * boolean which is true, if there is no thermalStorage, or it's empty. */ - private def determineDemandBooleans( + private def determineThermalStorageStatus( lastHpState: HpState, updatedGridState: ThermalGridState, - demandHouse: ThermalEnergyDemand, - demandThermalStorage: ThermalEnergyDemand, - ): (ThermalDemandIndicator, Boolean) = { + ): Boolean = { implicit val tolerance: Energy = KilowattHours(1e-3) val noThermalStorageOrThermalStorageIsEmpty: Boolean = updatedGridState.storageState.isEmpty || updatedGridState.storageState @@ -246,13 +230,7 @@ final case class HpModel( _.storedEnergy =~ zeroKWh ) - val houseDemand = - (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || (lastHpState.isRunning && demandHouse.hasAdditionalDemand) - val heatStorageDemand = - demandThermalStorage.hasRequiredDemand || (lastHpState.isRunning && demandThermalStorage.hasAdditionalDemand) - - val demandIndicator = ThermalDemandIndicator(houseDemand, heatStorageDemand) - (demandIndicator, noThermalStorageOrThermalStorageIsEmpty) + noThermalStorageOrThermalStorageIsEmpty } /** Calculate state depending on whether heat pump is needed or not. Also @@ -265,9 +243,8 @@ final case class HpModel( * data of heat pump including state of the heat pump * @param isRunning * determines whether the heat pump is running or not - * @param demandIndicator - * determines if the thermal units (house, storage) having some heat demand - * or not + * @param demandWrapper + * holds the thermal demands of the thermal units (house, storage) * @return * next [[HpState]] */ @@ -275,7 +252,7 @@ final case class HpModel( lastState: HpState, relevantData: HpRelevantData, isRunning: Boolean, - demandIndicator: ThermalDemandIndicator, + demandWrapper: ThermalDemandWrapper, ): HpState = { val lastStateStorageQDot = lastState.thermalGridState.storageState .map(_.qDot) @@ -297,7 +274,7 @@ final case class HpModel( relevantData.ambientTemperature, isRunning, newThermalPower, - demandIndicator, + demandWrapper, ) HpState( @@ -364,9 +341,8 @@ final case class HpModel( val turnOn = setPower > (sRated.toActivePower(cosPhiRated) * 0.5) val ( - thermalEnergyDemandHouse, - thermalEnergyDemandStorage, - updatedThermalGridState, + thermalDemandWrapper, + _, ) = thermalGrid.energyDemandAndUpdatedState( data.currentTick, @@ -375,21 +351,11 @@ final case class HpModel( lastState.thermalGridState, ) - val ( - demandIndicator, - _, - ) = determineDemandBooleans( - lastState, - updatedThermalGridState, - thermalEnergyDemandHouse, - thermalEnergyDemandStorage, - ) - val updatedHpState = calcState( lastState, data, turnOn, - demandIndicator, + thermalDemandWrapper, ) ( 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 033f84e532..4e7b99ddc1 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -15,7 +15,7 @@ import edu.ie3.datamodel.models.result.thermal.{ } import edu.ie3.simona.exceptions.agent.InconsistentStateException import edu.ie3.simona.model.thermal.ThermalGrid.{ - ThermalDemandIndicator, + ThermalDemandWrapper, ThermalEnergyDemand, ThermalGridState, } @@ -64,7 +64,7 @@ final case class ThermalGrid( lastAmbientTemperature: Temperature, ambientTemperature: Temperature, state: ThermalGridState, - ): (ThermalEnergyDemand, ThermalEnergyDemand, ThermalGridState) = { + ): (ThermalDemandWrapper, ThermalGridState) = { /* First get the energy demand of the houses but only if inner temperature is below target temperature */ val (houseDemand, updatedHouseState) = @@ -135,13 +135,15 @@ final case class ThermalGrid( } ( - ThermalEnergyDemand( - houseDemand.required, - houseDemand.possible, - ), - ThermalEnergyDemand( - storageDemand.required, - storageDemand.possible, + ThermalDemandWrapper( + ThermalEnergyDemand( + houseDemand.required, + houseDemand.possible, + ), + ThermalEnergyDemand( + storageDemand.required, + storageDemand.possible, + ), ), ThermalGridState(updatedHouseState, updatedStorageState), ) @@ -161,9 +163,8 @@ final case class ThermalGrid( * determines whether the heat pump is running or not * @param qDot * Thermal energy balance - * @param demandIndicator - * determines if the thermal units (house, storage) having some heat demand - * or not + * @param thermalDemands + * holds the thermal demands of the thermal units (house, storage) * @return * The updated state of the grid */ @@ -174,7 +175,7 @@ final case class ThermalGrid( ambientTemperature: Temperature, isRunning: Boolean, qDot: Power, - demandIndicator: ThermalDemandIndicator, + thermalDemands: ThermalDemandWrapper, ): (ThermalGridState, Option[ThermalThreshold]) = if (qDot > zeroKW) handleInfeed( tick, @@ -183,7 +184,7 @@ final case class ThermalGrid( state, isRunning, qDot, - demandIndicator, + thermalDemands, ) else handleConsumption( @@ -209,9 +210,8 @@ final case class ThermalGrid( * determines whether the heat pump is running or not * @param qDot * Infeed to the grid - * @param demandIndicator - * determines if the thermal units (house, storage) having some heat demand - * or not + * @param thermalDemands + * holds the thermal demands of the thermal units (house, storage) * @return * Updated thermal grid state */ @@ -222,7 +222,7 @@ final case class ThermalGrid( state: ThermalGridState, isRunning: Boolean, qDot: Power, - demandIndicator: ThermalDemandIndicator, + thermalDemands: ThermalDemandWrapper, ): (ThermalGridState, Option[ThermalThreshold]) = { // TODO: We would need to issue a storage result model here... @@ -240,7 +240,8 @@ final case class ThermalGrid( } if ( - (qDotHouseLastState > zeroKW && (qDotStorageLastState >= zeroKW)) | (qDotStorageLastState > zeroKW & demandIndicator.heatStorageDemand) + // todo: Check if it has to be hasRequiredDemand or hasAdditionalDemand + (qDotHouseLastState > zeroKW && (qDotStorageLastState >= zeroKW)) | (qDotStorageLastState > zeroKW & thermalDemands.heatStorageDemand.hasAdditionalDemand) ) { val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = handleInfeedHouse( @@ -302,8 +303,11 @@ final case class ThermalGrid( ) } } else { - - (demandIndicator.houseDemand, demandIndicator.heatStorageDemand) match { + // todo: Check if it has to be hasRequiredDemand or hasAdditionalDemand + ( + thermalDemands.houseDemand.hasRequiredDemand, + thermalDemands.heatStorageDemand.hasRequiredDemand, + ) match { case (true, _) => // house first then heatStorage after heating House @@ -737,17 +741,16 @@ object ThermalGrid { thermalGrid.storage.map(_.startingState), ) - /** Wraps booleans indicating the demand of thermal units (thermal house, - * thermal storage). + /** Wraps the demand of thermal units (thermal house, thermal storage). * * @param houseDemand - * Boolean indicating the demand of the thermal house + * the demand of the thermal house * @param heatStorageDemand - * Boolean indicating the demand of the thermal heat storage + * the demand of the thermal heat storage */ - final case class ThermalDemandIndicator private ( - houseDemand: Boolean, - heatStorageDemand: Boolean, + final case class ThermalDemandWrapper private ( + houseDemand: ThermalEnergyDemand, + heatStorageDemand: ThermalEnergyDemand, ) /** Defines the thermal energy demand of a thermal grid. It comprises the @@ -776,8 +779,7 @@ object ThermalGrid { object ThermalEnergyDemand { /** Builds a new instance of [[ThermalEnergyDemand]]. If the possible energy - * is less than the required energy, this is considered to be a bad state - * and the required energy is curtailed to the possible energy. + * is less than the required energy, this is considered to be a bad state. * @param required * The absolutely required energy to reach target state * @param possible diff --git a/src/test/scala/edu/ie3/simona/model/participant/HpModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/HpModelSpec.scala index 81c62e549d..7080cac327 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/HpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/HpModelSpec.scala @@ -265,7 +265,7 @@ class HpModelSpec (95.0, 95.0, 95.0), ), // 2. Same as before but heat storage is NOT empty - // should be possible to keep hp off + // should be possible to turn hp on ( ThermalGridState( Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala index 21f27b1892..df410786c5 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridTestData.scala @@ -9,8 +9,12 @@ package edu.ie3.simona.model.thermal import edu.ie3.datamodel.models.OperationTime import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput -import edu.ie3.simona.model.thermal.ThermalGrid.ThermalDemandIndicator -import squants.energy.{Kilowatts, Power} +import edu.ie3.simona.model.thermal.ThermalGrid.{ + ThermalDemandWrapper, + ThermalEnergyDemand, +} +import edu.ie3.util.scala.quantities.DefaultQuantities.zeroKWh +import squants.energy.{KilowattHours, Kilowatts, Power} import squants.thermal.{Celsius, Temperature} import java.util.UUID @@ -26,12 +30,21 @@ trait ThermalGridTestData { protected val testGridQDotInfeed: Power = Kilowatts(15d) protected val testGridQDotConsumption: Power = Kilowatts(-42d) protected val testGridQDotConsumptionHigh: Power = Kilowatts(-200d) - protected val noThermalDemand: ThermalDemandIndicator = - ThermalDemandIndicator(false, false) - protected val onlyThermalDemandOfHouse: ThermalDemandIndicator = - ThermalDemandIndicator(true, false) - protected val onlyThermalDemandOfHeatStorage: ThermalDemandIndicator = - ThermalDemandIndicator(false, true) + protected val noThermalDemand: ThermalDemandWrapper = + ThermalDemandWrapper( + ThermalEnergyDemand(zeroKWh, zeroKWh), + ThermalEnergyDemand(zeroKWh, zeroKWh), + ) + protected val onlyThermalDemandOfHouse: ThermalDemandWrapper = + ThermalDemandWrapper( + ThermalEnergyDemand(KilowattHours(1), KilowattHours(2)), + ThermalEnergyDemand(zeroKWh, zeroKWh), + ) + protected val onlyThermalDemandOfHeatStorage: ThermalDemandWrapper = + ThermalDemandWrapper( + ThermalEnergyDemand(zeroKWh, zeroKWh), + ThermalEnergyDemand(KilowattHours(1), KilowattHours(2)), + ) protected val isRunning: Boolean = true protected val isNotRunning: Boolean = false } diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala index 2351774f20..6cd7558e3d 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala @@ -13,13 +13,13 @@ import edu.ie3.simona.model.thermal.ThermalHouse.ThermalHouseThreshold.{ HouseTemperatureLowerBoundaryReached, HouseTemperatureUpperBoundaryReached, } -import edu.ie3.util.scala.quantities.DefaultQuantities.{zeroKW, zeroKWh} import edu.ie3.simona.model.thermal.ThermalStorage.ThermalStorageState import edu.ie3.simona.model.thermal.ThermalStorage.ThermalStorageThreshold.{ StorageEmpty, StorageFull, } import edu.ie3.simona.test.common.UnitSpec +import edu.ie3.util.scala.quantities.DefaultQuantities.{zeroKW, zeroKWh} import squants.energy._ import squants.thermal.Celsius import squants.{Energy, Kelvin, Power, Temperature} @@ -97,13 +97,16 @@ class ThermalGridWithHouseAndStorageSpec "deliver the house demand (no demand) with added flexibility by storage" in { val tick = 10800 // after three hours - val (houseDemand, storageDemand, updatedThermalGridState) = + val (thermalDemands, updatedThermalGridState) = thermalGrid.energyDemandAndUpdatedState( tick, testGridAmbientTemperature, testGridAmbientTemperature, ThermalGrid.startingState(thermalGrid), ) + val houseDemand = thermalDemands.houseDemand + val storageDemand = thermalDemands.heatStorageDemand + houseDemand.required should approximate(zeroKWh) houseDemand.possible should approximate(KilowattHours(31.05009722d)) storageDemand.required should approximate(KilowattHours(1150d)) @@ -120,7 +123,7 @@ class ThermalGridWithHouseAndStorageSpec val tick = 10800 // after three hours val startingState = ThermalGrid.startingState(thermalGrid) - val (houseDemand, storageDemand, updatedThermalGridState) = + val (thermalDemands, updatedThermalGridState) = thermalGrid.energyDemandAndUpdatedState( tick, testGridAmbientTemperature, @@ -131,6 +134,8 @@ class ThermalGridWithHouseAndStorageSpec ) ), ) + val houseDemand = thermalDemands.houseDemand + val storageDemand = thermalDemands.heatStorageDemand houseDemand.required should approximate(KilowattHours(45.6000555)) houseDemand.possible should approximate(KilowattHours(75.600055555)) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala index 0c61b79ba8..34b37c2e03 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala @@ -13,8 +13,8 @@ import edu.ie3.simona.model.thermal.ThermalHouse.ThermalHouseThreshold.{ HouseTemperatureLowerBoundaryReached, HouseTemperatureUpperBoundaryReached, } -import edu.ie3.util.scala.quantities.DefaultQuantities.{zeroKW, zeroKWh} import edu.ie3.simona.test.common.UnitSpec +import edu.ie3.util.scala.quantities.DefaultQuantities.{zeroKW, zeroKWh} import squants.energy._ import squants.thermal.Celsius import squants.{Energy, Kelvin, Power, Temperature} @@ -81,7 +81,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { expectedHouseStartingState, ) - val (houseDemand, storageDemand, updatedThermalGridState) = + val (thermalDemands, updatedThermalGridState) = thermalGrid.energyDemandAndUpdatedState( tick, testGridAmbientTemperature, @@ -89,6 +89,9 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ThermalGrid.startingState(thermalGrid), ) + val houseDemand = thermalDemands.houseDemand + val storageDemand = thermalDemands.heatStorageDemand + houseDemand.required should approximate(expectedHouseDemand.required) houseDemand.possible should approximate(expectedHouseDemand.possible) storageDemand.required should approximate(zeroKWh) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala index d8b622e78c..c4e5339a54 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala @@ -81,13 +81,15 @@ class ThermalGridWithStorageOnlySpec "deliver the capabilities of the storage" in { val tick = 10800 // after three hours - val (houseDemand, storageDemand, updatedThermalGridState) = + val (thermalDemands, updatedThermalGridState) = thermalGrid.energyDemandAndUpdatedState( tick, testGridAmbientTemperature, testGridAmbientTemperature, ThermalGrid.startingState(thermalGrid), ) + val houseDemand = thermalDemands.houseDemand + val storageDemand = thermalDemands.heatStorageDemand houseDemand.required should approximate(zeroKWh) houseDemand.possible should approximate(zeroKWh) @@ -102,7 +104,7 @@ class ThermalGridWithStorageOnlySpec "deliver the capabilities of a half full storage" in { val tick = 10800 // after three hours - val (houseDemand, storageDemand, updatedThermalGridState) = + val (thermalDemands, updatedThermalGridState) = thermalGrid.energyDemandAndUpdatedState( tick, testGridAmbientTemperature, @@ -112,6 +114,8 @@ class ThermalGridWithStorageOnlySpec Some(ThermalStorageState(0L, KilowattHours(575d), zeroKW)), ), ) + val houseDemand = thermalDemands.houseDemand + val storageDemand = thermalDemands.heatStorageDemand houseDemand.required should approximate(zeroKWh) houseDemand.possible should approximate(zeroKWh) From 5c00a896c5ca9e086fa82e5384073e96a519482f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 22 Nov 2024 17:02:32 +0100 Subject: [PATCH 15/44] fix thermalPower determination in calcState of HpModel --- .../edu/ie3/simona/model/participant/HpModel.scala | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 76e9f24651..3e5c8f4cd1 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -258,12 +258,20 @@ final case class HpModel( .map(_.qDot) .getOrElse(zeroKW) - val (newActivePower, newThermalPower) = + val (newActivePower, newThermalPower) = { if (isRunning) (pRated, pThermal) else if (lastStateStorageQDot < zeroKW) (zeroKW, lastStateStorageQDot * -1) + else if ( + lastStateStorageQDot == zeroKW && (demandWrapper.houseDemand.hasRequiredDemand || demandWrapper.heatStorageDemand.hasRequiredDemand) + ) + ( + zeroKW, + thermalGrid.storage.map(_.getChargingPower: squants.Power).get * -1, + ) else (zeroKW, zeroKW) + } /* Push thermal energy to the thermal grid and get its updated state in return */ val (thermalGridState, maybeThreshold) = From cbd997ebc8ef6f86d87e5653b08c528710d29d56 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 22 Nov 2024 23:39:58 +0100 Subject: [PATCH 16/44] fix EmAgentIT --- .../scala/edu/ie3/simona/agent/em/EmAgentIT.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala b/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala index be1cee377f..b43b73f129 100644 --- a/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala +++ b/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala @@ -680,7 +680,7 @@ class EmAgentIT Celsius(0d), MetersPerSecond(0d), ), - Some(56000), + Some(28800), ) } @@ -692,26 +692,26 @@ class EmAgentIT emResult.getQ should equalWithTolerance(0.000088285537.asMegaVar) } - scheduler.expectMessage(Completion(emAgentActivation, Some(44398))) + scheduler.expectMessage(Completion(emAgentActivation, Some(26748))) - /* TICK 44398 + /* TICK 26748 LOAD: 0.000269 MW (unchanged) PV: -0.000032 MW (unchanged) Heat pump: Is turned on again and cannot be turned off -> flex signal is no control -> 0.00485 MW */ - emAgentActivation ! Activation(44398) + emAgentActivation ! Activation(26748) resultListener.expectMessageType[ParticipantResultEvent] match { case ParticipantResultEvent(emResult: EmResult) => emResult.getInputModel shouldBe emInput.getUuid - emResult.getTime shouldBe 44398.toDateTime + emResult.getTime shouldBe 26748.toDateTime emResult.getP should equalWithTolerance(0.005086768.asMegaWatt) emResult.getQ should equalWithTolerance(0.00107312004.asMegaVar) } - scheduler.expectMessage(Completion(emAgentActivation, Some(56000))) + scheduler.expectMessage(Completion(emAgentActivation, Some(28800))) } } From a07b6262cd8753532aebfcb6fdd9d0b5cd870e36 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 22 Nov 2024 23:51:58 +0100 Subject: [PATCH 17/44] also turn Hp on in case house has additional demand and the Hp was running in the last state --- src/main/scala/edu/ie3/simona/model/participant/HpModel.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 3e5c8f4cd1..74f80350d5 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -192,7 +192,9 @@ final case class HpModel( val turnHpOn = (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || - demandThermalStorage.hasRequiredDemand || (demandThermalStorage.hasAdditionalDemand && lastState.isRunning) + (demandHouse.hasAdditionalDemand && lastState.isRunning) || + demandThermalStorage.hasRequiredDemand || + (demandThermalStorage.hasAdditionalDemand && lastState.isRunning) val canOperate = demandHouse.hasRequiredDemand || demandHouse.hasAdditionalDemand || From 92e6c512f88c261af1e3216c4115f5512b7eeb7c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 23 Nov 2024 09:56:34 +0100 Subject: [PATCH 18/44] fix EmAgentIT --- .../edu/ie3/simona/agent/em/EmAgentIT.scala | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala b/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala index b43b73f129..37155b6cba 100644 --- a/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala +++ b/src/test/scala/edu/ie3/simona/agent/em/EmAgentIT.scala @@ -692,25 +692,6 @@ class EmAgentIT emResult.getQ should equalWithTolerance(0.000088285537.asMegaVar) } - scheduler.expectMessage(Completion(emAgentActivation, Some(26748))) - - /* TICK 26748 - LOAD: 0.000269 MW (unchanged) - PV: -0.000032 MW (unchanged) - Heat pump: Is turned on again and cannot be turned off - -> flex signal is no control -> 0.00485 MW - */ - - emAgentActivation ! Activation(26748) - - resultListener.expectMessageType[ParticipantResultEvent] match { - case ParticipantResultEvent(emResult: EmResult) => - emResult.getInputModel shouldBe emInput.getUuid - emResult.getTime shouldBe 26748.toDateTime - emResult.getP should equalWithTolerance(0.005086768.asMegaWatt) - emResult.getQ should equalWithTolerance(0.00107312004.asMegaVar) - } - scheduler.expectMessage(Completion(emAgentActivation, Some(28800))) } } From 481da32d59444f6eaf29b229db02a684f8996150 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 23 Nov 2024 09:56:57 +0100 Subject: [PATCH 19/44] fmt --- src/main/scala/edu/ie3/simona/model/participant/HpModel.scala | 2 +- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 74f80350d5..e32757d767 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -264,7 +264,7 @@ final case class HpModel( if (isRunning) (pRated, pThermal) else if (lastStateStorageQDot < zeroKW) - (zeroKW, lastStateStorageQDot * -1) + (zeroKW, lastStateStorageQDot * (-1)) else if ( lastStateStorageQDot == zeroKW && (demandWrapper.houseDemand.hasRequiredDemand || demandWrapper.heatStorageDemand.hasRequiredDemand) ) 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 4e7b99ddc1..08b48eda2b 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -51,7 +51,7 @@ final case class ThermalGrid( * @param lastAmbientTemperature * Ambient temperature until this tick * @param ambientTemperature - * Ambient temperature in the instance in question + * Current ambient temperature in the instance in question * @param state * Currently applicable state of the thermal grid * @return From b03b5760daacd16a9d15a9de0192565b0f0d853d Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 23 Nov 2024 09:57:56 +0100 Subject: [PATCH 20/44] correct direction of thermal power of thermal heat storage --- src/main/scala/edu/ie3/simona/model/participant/HpModel.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index e32757d767..92ad195af9 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -270,7 +270,7 @@ final case class HpModel( ) ( zeroKW, - thermalGrid.storage.map(_.getChargingPower: squants.Power).get * -1, + thermalGrid.storage.map(_.getChargingPower: squants.Power).get, ) else (zeroKW, zeroKW) } From 7b58297793ec0b70fc5e3ad41bde132d703064a0 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 23 Nov 2024 09:59:05 +0100 Subject: [PATCH 21/44] fix handleInfeed of thermal energy --- .../simona/model/thermal/ThermalGrid.scala | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) 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 08b48eda2b..d94cf89d2c 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -240,8 +240,7 @@ final case class ThermalGrid( } if ( - // todo: Check if it has to be hasRequiredDemand or hasAdditionalDemand - (qDotHouseLastState > zeroKW && (qDotStorageLastState >= zeroKW)) | (qDotStorageLastState > zeroKW & thermalDemands.heatStorageDemand.hasAdditionalDemand) + (qDotHouseLastState > zeroKW && (qDotStorageLastState >= zeroKW)) | (qDotStorageLastState > zeroKW && thermalDemands.heatStorageDemand.hasAdditionalDemand) ) { val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = handleInfeedHouse( @@ -280,7 +279,7 @@ final case class ThermalGrid( nextThreshold, ) } - // Handle edge case where house get heated from storage and HP will be activated in between + // Handle edge case where house was heated from storage and HP will be activated in between else if ((qDotHouseLastState > zeroKW && qDotStorageLastState < zeroKW)) { if (isRunning) { handleCases( @@ -302,14 +301,25 @@ final case class ThermalGrid( qDotStorageLastState, ) } + } + // Handle edge case where house should be heated from storage + else if ((!isRunning && qDot > zeroKW)) { + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDot, + -qDot, + ) } else { - // todo: Check if it has to be hasRequiredDemand or hasAdditionalDemand ( thermalDemands.houseDemand.hasRequiredDemand, - thermalDemands.heatStorageDemand.hasRequiredDemand, + thermalDemands.houseDemand.hasAdditionalDemand, + thermalDemands.heatStorageDemand.hasAdditionalDemand, ) match { - case (true, _) => + case (true, _, _) => // house first then heatStorage after heating House handleCases( tick, @@ -320,7 +330,7 @@ final case class ThermalGrid( zeroKW, ) - case (false, true) => + case (false, _, true) => handleCases( tick, lastAmbientTemperature, @@ -330,7 +340,17 @@ final case class ThermalGrid( qDot, ) - case (false, false) => + case (false, true, false) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDot, + zeroKW, + ) + + case (false, false, false) => handleCases( tick, lastAmbientTemperature, From 8d452ece6d9990b127edabfb254c355988168d4b Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 23 Nov 2024 10:11:26 +0100 Subject: [PATCH 22/44] enhance ThermalGridSpec when checking for required and additional demand --- .../edu/ie3/simona/model/thermal/ThermalGridSpec.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridSpec.scala index e4c1c14c70..1a59aede8b 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridSpec.scala @@ -51,6 +51,15 @@ class ThermalGridSpec extends UnitSpec { } "checking for required and additional demand" should { + "return proper information, if no required and no additional demand is apparent" in { + val required = MegawattHours(0d) + val possible = MegawattHours(0d) + + val energyDemand = ThermalEnergyDemand(required, possible) + energyDemand.hasRequiredDemand shouldBe false + energyDemand.hasAdditionalDemand shouldBe false + } + "return proper information, if no required but additional demand is apparent" in { val required = MegawattHours(0d) val possible = MegawattHours(45d) From 07746a48d067c7ab5ca49fabbfcf071e5386f65c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 23 Nov 2024 10:12:29 +0100 Subject: [PATCH 23/44] fix inputs for thermalGridWith specs plus add another test case --- .../ThermalGridWithHouseAndStorageSpec.scala | 4 +- .../ThermalGridWithStorageOnlySpec.scala | 41 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala index 6cd7558e3d..39bc5e6c18 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala @@ -502,7 +502,7 @@ class ThermalGridWithHouseAndStorageSpec testGridAmbientTemperature, testGridAmbientTemperature, initialGridState, - isNotRunning, + isRunning, externalQDot, onlyThermalDemandOfHouse, ) @@ -550,7 +550,7 @@ class ThermalGridWithHouseAndStorageSpec testGridAmbientTemperature, testGridAmbientTemperature, gridState, - isNotRunning, + isRunning, externalQDot, onlyThermalDemandOfHeatStorage, ) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala index c4e5339a54..8f0ba6cdfe 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala @@ -187,7 +187,7 @@ class ThermalGridWithStorageOnlySpec testGridAmbientTemperature, testGridAmbientTemperature, gridState, - isNotRunning, + isRunning, testGridQDotInfeed, onlyThermalDemandOfHeatStorage, ) @@ -204,6 +204,45 @@ class ThermalGridWithStorageOnlySpec } reachedThreshold shouldBe Some(StorageFull(276000L)) } + + "properly take energy from storage" in { + val tick = 0L + val gridState = ThermalGrid + .startingState(thermalGrid) + .copy(storageState = + Some( + ThermalStorageState( + 0L, + KilowattHours(150d), + zeroKW, + ) + ) + ) + + val (updatedGridState, reachedThreshold) = + thermalGrid invokePrivate handleInfeed( + tick, + testGridAmbientTemperature, + testGridAmbientTemperature, + gridState, + isNotRunning, + testGridQDotInfeed, + onlyThermalDemandOfHeatStorage, + ) + + updatedGridState match { + case ThermalGridState( + None, + Some(ThermalStorageState(tick, storedEnergy, qDot)), + ) => + tick shouldBe 0L + storedEnergy should approximate(KilowattHours(150d)) + qDot should approximate(testGridQDotInfeed * (-1)) + case _ => fail("Thermal grid state has been calculated wrong.") + } + reachedThreshold shouldBe Some(StorageEmpty(36000L)) + } + } "updating the grid state dependent on the given thermal infeed" should { From aa9ffc97391a56ecdb8a200fa46a6323eee66ad8 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 23 Nov 2024 10:23:10 +0100 Subject: [PATCH 24/44] remove unused parameter --- .../scala/edu/ie3/simona/model/participant/HpModel.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 92ad195af9..39b4eb4b75 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -186,8 +186,7 @@ final case class HpModel( val demandThermalStorage = thermalDemands.heatStorageDemand val noThermalStorageOrThermalStorageIsEmpty = determineThermalStorageStatus( - lastState, - currentThermalGridState, + currentThermalGridState ) val turnHpOn = @@ -213,8 +212,6 @@ final case class HpModel( * or thermal storage as well as a boolean indicating if there is no thermal * storage, or it is empty. * - * @param lastHpState - * Current state of the heat pump * @param updatedGridState * The updated state of the [[ThermalGrid]] * @return @@ -222,8 +219,7 @@ final case class HpModel( */ private def determineThermalStorageStatus( - lastHpState: HpState, - updatedGridState: ThermalGridState, + updatedGridState: ThermalGridState ): Boolean = { implicit val tolerance: Energy = KilowattHours(1e-3) val noThermalStorageOrThermalStorageIsEmpty: Boolean = From 0d157db2654ab4e97aa15983e10f14722b2987b1 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 25 Nov 2024 15:47:44 +0100 Subject: [PATCH 25/44] fix after merging --- .../edu/ie3/simona/model/participant/HpModel.scala | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 6c2bc6a540..c6bb721d01 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -302,7 +302,7 @@ final case class HpModel( * operating state and give back the next tick in which something will * change. * - * @param data + * @param relevantData * Relevant data for model calculation * @param lastState * The last known model state @@ -313,7 +313,7 @@ final case class HpModel( * options will change next */ override def handleControlledPowerChange( - data: HpRelevantData, + relevantData: HpRelevantData, lastState: HpState, setPower: Power, ): (HpState, FlexChangeIndicator) = { @@ -325,15 +325,13 @@ final case class HpModel( _, ) = thermalGrid.energyDemandAndUpdatedState( - data.currentTick, - lastState.ambientTemperature.getOrElse(data.ambientTemperature), - data.ambientTemperature, - lastState.thermalGridState, + relevantData, + lastState, ) val updatedHpState = calcState( lastState, - data, + relevantData, turnOn, thermalDemandWrapper, ) From 9a9096d8ad38dea4c64d4e67eb9e47195d26163f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 25 Nov 2024 17:26:07 +0100 Subject: [PATCH 26/44] fmt --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 1 - 1 file changed, 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 227701f729..a379510533 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -507,7 +507,6 @@ final case class ThermalGrid( * @return * The next threshold */ - private def determineMostRecentThreshold( maybeHouseThreshold: Option[ThermalThreshold], maybeStorageThreshold: Option[ThermalThreshold], From 81694cc6156c2494070fe0a213a4797cf947a63c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 25 Nov 2024 22:19:56 +0100 Subject: [PATCH 27/44] hard fix for zero values as minimum storage volume level to prevent non-plausible behaviour till psdm release --- .../simona/model/thermal/CylindricalThermalStorage.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala b/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala index e49dde2633..101e9b056b 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala @@ -187,8 +187,10 @@ object CylindricalThermalStorage { input: CylindricalStorageInput, initialStoredEnergy: Energy = DefaultQuantities.zeroKWh, ): CylindricalThermalStorage = { - val minEnergyThreshold: Energy = - CylindricalThermalStorage.volumeToEnergy( + val minEnergyThreshold: Energy = { + //Temporary fix until changes in PSDM are released, Some minimumEnergyThreshold would lead to non-plausible behaviour + zeroKWh + /*CylindricalThermalStorage.volumeToEnergy( CubicMeters( input.getStorageVolumeLvlMin .to(Units.CUBIC_METRE) @@ -204,6 +206,8 @@ object CylindricalThermalStorage { Celsius(input.getInletTemp.to(Units.CELSIUS).getValue.doubleValue()), Celsius(input.getReturnTemp.to(Units.CELSIUS).getValue.doubleValue()), ) + */ + } val maxEnergyThreshold: Energy = CylindricalThermalStorage.volumeToEnergy( From d9f859c3f14bc90dc81426421dea6f244be55f16 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 25 Nov 2024 22:18:57 +0100 Subject: [PATCH 28/44] adapt ChpModelSpec and CylindricalThermalStorageSpec to zero for minimum storage volume level --- .../model/participant/ChpModelSpec.scala | 14 ++++++------- .../CylindricalThermalStorageSpec.scala | 20 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala index 91a72ddd63..57c0dd6725 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala @@ -62,7 +62,7 @@ class ChpModelSpec "ThermalStorage", thermalBus, getQuantity(100, StandardUnits.VOLUME), - getQuantity(20, StandardUnits.VOLUME), + getQuantity(0, StandardUnits.VOLUME), getQuantity(30, StandardUnits.TEMPERATURE), getQuantity(40, StandardUnits.TEMPERATURE), getQuantity(1.15, StandardUnits.SPECIFIC_HEAT_CAPACITY), @@ -149,7 +149,7 @@ class ChpModelSpec ( chpStateNotRunning, 90, - 8 * 115, + 8 * 115 + 230, 95, ), // tests case (false, true, false) (chpStateNotRunning, 90, 10, 0), // tests case (false, true, true) @@ -194,7 +194,7 @@ class ChpModelSpec ( chpStateNotRunning, 90, - 8 * 115, + 8 * 115 + 230, 100, ), // tests case (false, true, false) (chpStateNotRunning, 90, 10, 0), // tests case (false, true, true) @@ -241,11 +241,11 @@ class ChpModelSpec chpStateNotRunning, 90, 8 * 115, - 230, + 115, ), // tests case (false, true, false) (chpStateNotRunning, 90, 10, 1025), // tests case (false, true, true) (chpStateRunning, 90, 0, 1135), // tests case (true, false, true) - (chpStateRunning, 90, 8 * 115, 230), // tests case (true, true, false) + (chpStateRunning, 90, 8 * 115, 215), // tests case (true, true, false) (chpStateRunning, 90, 10, 1125), // tests case (true, true, true) ( chpStateRunning, @@ -257,7 +257,7 @@ class ChpModelSpec chpStateRunning, 90, 9 * 115, - 230, + 100, ), // test case (_, true, false) and demand not covered together with chp ( chpStateRunning, @@ -293,7 +293,7 @@ class ChpModelSpec ( chpStateNotRunning, 90, - 8 * 115, + 8 * 115 + 230, 7200, true, ), // Test case (false, true, false) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorageSpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorageSpec.scala index 52cbb30f79..d2c2a15ee7 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorageSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorageSpec.scala @@ -34,7 +34,7 @@ class CylindricalThermalStorageSpec "ThermalStorage", null, getQuantity(100, StandardUnits.VOLUME), - getQuantity(20, StandardUnits.VOLUME), + getQuantity(0, StandardUnits.VOLUME), getQuantity(30, StandardUnits.TEMPERATURE), getQuantity(40, StandardUnits.TEMPERATURE), getQuantity(1.15, StandardUnits.SPECIFIC_HEAT_CAPACITY), @@ -92,7 +92,7 @@ class CylindricalThermalStorageSpec storage.tryToStoreAndReturnRemainder(vol2Energy(CubicMeters(55))) val newLevel2 = storage._storedEnergy val isCovering = storage.isDemandCoveredByStorage(KilowattHours(5)) - val lack = storage.tryToTakeAndReturnLack(vol2Energy(CubicMeters(95))) + val lack = storage.tryToTakeAndReturnLack(vol2Energy(CubicMeters(115))) val newLevel3 = storage._storedEnergy val notCovering = storage.isDemandCoveredByStorage(KilowattHours(1)) @@ -101,7 +101,7 @@ class CylindricalThermalStorageSpec surplus.value shouldBe vol2Energy(CubicMeters(5)) newLevel2 should approximate(vol2Energy(CubicMeters(100))) lack.value shouldBe vol2Energy(CubicMeters(15)) - newLevel3 should approximate(vol2Energy(CubicMeters(20))) + newLevel3 should approximate(vol2Energy(CubicMeters(0))) isCovering shouldBe true notCovering shouldBe false } @@ -110,7 +110,7 @@ class CylindricalThermalStorageSpec val storage = buildThermalStorage(storageInput, CubicMeters(70)) val usableThermalEnergy = storage.usableThermalEnergy - usableThermalEnergy should approximate(KilowattHours(5 * 115)) + usableThermalEnergy should approximate(KilowattHours(5 * 115 + 230)) } "Apply, validation, and build method work correctly" in { @@ -145,11 +145,11 @@ class CylindricalThermalStorageSpec ), ( 0L, - 250.0, + 20.0, 10.0, 3600L, -42.0, - 260.0, + 30.0, ThermalStorage.ThermalStorageThreshold.StorageEmpty(6171L), ), ( @@ -163,11 +163,11 @@ class CylindricalThermalStorageSpec ), ( 0L, - 250.0, + 20.0, -10.0, 3600L, -42.0, - 240.0, + 10.0, ThermalStorage.ThermalStorageThreshold.StorageEmpty(4457L), ), ( @@ -181,11 +181,11 @@ class CylindricalThermalStorageSpec ), ( 0L, - 240.0, + 10.0, -9.0, 3600L, -5000.0, - 231.0, + 1.0, ThermalStorage.ThermalStorageThreshold.StorageEmpty(3601L), ), ) From bed4f7b926d6bdd8316b6ce1a05b21904895e2c2 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 25 Nov 2024 22:29:51 +0100 Subject: [PATCH 29/44] adapt cases for handling thermal infeed into ThermalGrid --- .../simona/model/thermal/ThermalGrid.scala | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) 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 f9d353fe40..ae843cb306 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -312,10 +312,11 @@ final case class ThermalGrid( ( thermalDemands.houseDemand.hasRequiredDemand, thermalDemands.houseDemand.hasAdditionalDemand, + thermalDemands.heatStorageDemand.hasRequiredDemand, thermalDemands.heatStorageDemand.hasAdditionalDemand, ) match { - case (true, _, _) => + case (true,_, _, _) => // house first then heatStorage after heating House handleCases( tick, @@ -326,7 +327,7 @@ final case class ThermalGrid( zeroKW, ) - case (false, _, true) => + case (_,_, true, _) => handleCases( tick, lastAmbientTemperature, @@ -336,7 +337,17 @@ final case class ThermalGrid( qDot, ) - case (false, true, false) => + case (_, false, false, true) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + zeroKW, + qDot, + ) + + case (_, true, false, false) => handleCases( tick, lastAmbientTemperature, @@ -346,7 +357,7 @@ final case class ThermalGrid( zeroKW, ) - case (false, false, false) => + case (false, false, false, false) => handleCases( tick, lastAmbientTemperature, From badd6d9160315db83b40fa0aa6778b7445aff8d1 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 25 Nov 2024 23:07:19 +0100 Subject: [PATCH 30/44] fix consider qDot as heat result of hp only when hp is running --- .../scala/edu/ie3/simona/model/participant/HpModel.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala index 947076e17c..93a788d5e9 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -112,7 +112,12 @@ final case class HpModel( tick: Long, currentState: HpState, data: HpRelevantData, - ): Power = currentState.qDot + ): Power = + // only if Hp is running qDot will be from Hp, else qDot results from other source, e.g. some storage + if (currentState.isRunning) + currentState.qDot + else + zeroKW /** Given a [[HpRelevantData]] object and the last [[HpState]], this function * calculates the heat pump's next state to get the actual active power of From ae84f160aba579322b99c10bf77e0dfef67e2217 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 25 Nov 2024 23:07:39 +0100 Subject: [PATCH 31/44] fmt --- .../ie3/simona/model/thermal/CylindricalThermalStorage.scala | 2 +- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala b/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala index 101e9b056b..13145f2c7a 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala @@ -188,7 +188,7 @@ object CylindricalThermalStorage { initialStoredEnergy: Energy = DefaultQuantities.zeroKWh, ): CylindricalThermalStorage = { val minEnergyThreshold: Energy = { - //Temporary fix until changes in PSDM are released, Some minimumEnergyThreshold would lead to non-plausible behaviour + // Temporary fix until changes in PSDM are released, Some minimumEnergyThreshold would lead to non-plausible behaviour zeroKWh /*CylindricalThermalStorage.volumeToEnergy( CubicMeters( 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 ae843cb306..7eac95583b 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -316,7 +316,7 @@ final case class ThermalGrid( thermalDemands.heatStorageDemand.hasAdditionalDemand, ) match { - case (true,_, _, _) => + case (true, _, _, _) => // house first then heatStorage after heating House handleCases( tick, @@ -327,7 +327,7 @@ final case class ThermalGrid( zeroKW, ) - case (_,_, true, _) => + case (_, _, true, _) => handleCases( tick, lastAmbientTemperature, From dab5a85eee66d15adf51c26211d1e23c384b4eb7 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 26 Nov 2024 09:36:42 +0100 Subject: [PATCH 32/44] fix wrong case within thermalGrid --- .../ie3/simona/model/thermal/ThermalGrid.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 7eac95583b..ee426a5e00 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -337,15 +337,15 @@ final case class ThermalGrid( qDot, ) - case (_, false, false, true) => - handleCases( - tick, - lastAmbientTemperature, - ambientTemperature, - state, - zeroKW, - qDot, - ) + case (false, _, false, true) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + zeroKW, + qDot, + ) case (_, true, false, false) => handleCases( From 0adc6c9921ef3c4c85ab0360c01d980467dc12e1 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 26 Nov 2024 09:38:00 +0100 Subject: [PATCH 33/44] split handleInfeed method a tiny bit --- .../simona/model/thermal/ThermalGrid.scala | 140 +++++++++++------- 1 file changed, 90 insertions(+), 50 deletions(-) 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 ee426a5e00..9326dec16c 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -308,34 +308,75 @@ final case class ThermalGrid( qDot, -qDot, ) - } else { - ( - thermalDemands.houseDemand.hasRequiredDemand, - thermalDemands.houseDemand.hasAdditionalDemand, - thermalDemands.heatStorageDemand.hasRequiredDemand, - thermalDemands.heatStorageDemand.hasAdditionalDemand, - ) match { - - case (true, _, _, _) => - // house first then heatStorage after heating House - handleCases( - tick, - lastAmbientTemperature, - ambientTemperature, - state, - qDot, - zeroKW, - ) + } else handleFinaleInfeedCases(thermalDemands, tick, lastAmbientTemperature, ambientTemperature, state, qDot) + } - case (_, _, true, _) => - handleCases( - tick, - lastAmbientTemperature, - ambientTemperature, - state, - zeroKW, - qDot, - ) + /** Handles the last cases of [[ThermalGrid.handleInfeed]], where the thermal + * infeed should be determined. + * + * | house req. demand | house add. demand | storage req. demand | storage add. demand | qDot to house | qDot to storage | + * |:------------------|:------------------|:--------------------|:--------------------|:--------------|:----------------| + * | true | true | true | true | true | false | + * | true | true | true | false | true | false | + * | true | true | false | true | true | false | + * | true | true | false | false | true | false | + * | true | false | true | true | true | false | + * | true | false | true | false | true | false | + * | true | false | false | true | true | false | + * | true | false | false | false | true | false | + * | false | true | true | true | false | true | + * | false | true | true | false | false | true | + * | false | true | false | true | false | true | + * | false | true | false | false | true | false | + * | false | false | true | true | false | true | + * | false | false | true | false | false | true | + * | false | false | false | true | false | true | + * | false | false | false | false | false | false | + * + * This can be simplified to five cases + * | No | Conditions | Result | + * |:---|:-------------------------------------------------------------------------|:----------| + * | 1 | if(house.reqD) => house | house | + * | 2 | if(!house.reqD && !storage.reqD) => storage | storage | + * | 3 | if(!house.reqD && !storage.reqD && storage.addD) => storage | storage | + * | 4 | if(!house.reqD && house.addD && !storage.reqD && !storage.addD) => house | house | + * | 5 | if(all == false) => no output | no output | + */ + def handleFinaleInfeedCases( + thermalDemands: ThermalDemandWrapper, + tick: Long, + lastAmbientTemperature: Temperature, + ambientTemperature: Temperature, + state: ThermalGridState, + qDot: Power, + ) = { + ( + thermalDemands.houseDemand.hasRequiredDemand, + thermalDemands.houseDemand.hasAdditionalDemand, + thermalDemands.heatStorageDemand.hasRequiredDemand, + thermalDemands.heatStorageDemand.hasAdditionalDemand, + ) match { + + case (true, _, _, _) => + // house first then heatStorage after heating House + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDot, + zeroKW, + ) + + case (_, _, true, _) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + zeroKW, + qDot, + ) case (false, _, false, true) => handleCases( @@ -347,30 +388,29 @@ final case class ThermalGrid( qDot, ) - case (_, true, false, false) => - handleCases( - tick, - lastAmbientTemperature, - ambientTemperature, - state, - qDot, - zeroKW, - ) + case (_, true, false, false) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDot, + zeroKW, + ) - case (false, false, false, false) => - handleCases( - tick, - lastAmbientTemperature, - ambientTemperature, - state, - zeroKW, - zeroKW, - ) - case _ => - throw new InconsistentStateException( - "There should be at least a house or a storage state." - ) - } + case (false, false, false, false) => + handleCases( + tick, + lastAmbientTemperature, + ambientTemperature, + state, + zeroKW, + zeroKW, + ) + case _ => + throw new InconsistentStateException( + "There should be at least a house or a storage state." + ) } } From 1586bd3ca3ba730c641d5c3ec2e0dd5c6bce8d39 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 26 Nov 2024 09:41:24 +0100 Subject: [PATCH 34/44] fmt --- .../ie3/simona/model/thermal/ThermalGrid.scala | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) 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 9326dec16c..0521c2531f 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -276,7 +276,7 @@ final case class ThermalGrid( ) } // Handle edge case where house was heated from storage and HP will be activated in between - else if ((qDotHouseLastState > zeroKW && qDotStorageLastState < zeroKW)) { + else if (qDotHouseLastState > zeroKW && qDotStorageLastState < zeroKW) { if (isRunning) { handleCases( tick, @@ -299,7 +299,7 @@ final case class ThermalGrid( } } // Handle edge case where house should be heated from storage - else if ((!isRunning && qDot > zeroKW)) { + else if (!isRunning && qDot > zeroKW) { handleCases( tick, lastAmbientTemperature, @@ -308,7 +308,15 @@ final case class ThermalGrid( qDot, -qDot, ) - } else handleFinaleInfeedCases(thermalDemands, tick, lastAmbientTemperature, ambientTemperature, state, qDot) + } else + handleFinaleInfeedCases( + thermalDemands, + tick, + lastAmbientTemperature, + ambientTemperature, + state, + qDot, + ) } /** Handles the last cases of [[ThermalGrid.handleInfeed]], where the thermal @@ -342,14 +350,14 @@ final case class ThermalGrid( * | 4 | if(!house.reqD && house.addD && !storage.reqD && !storage.addD) => house | house | * | 5 | if(all == false) => no output | no output | */ - def handleFinaleInfeedCases( + private def handleFinaleInfeedCases( thermalDemands: ThermalDemandWrapper, tick: Long, lastAmbientTemperature: Temperature, ambientTemperature: Temperature, state: ThermalGridState, qDot: Power, - ) = { + ): (ThermalGridState, Option[ThermalThreshold]) = { ( thermalDemands.houseDemand.hasRequiredDemand, thermalDemands.houseDemand.hasAdditionalDemand, From be3b094f652a35cc73ed7faf60df19df52f06d07 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 26 Nov 2024 11:51:08 +0100 Subject: [PATCH 35/44] fix after merging dev --- .../simona/model/thermal/ThermalGrid.scala | 72 ++++++++----------- 1 file changed, 30 insertions(+), 42 deletions(-) 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 235de1e084..1850ba27ec 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -168,7 +168,14 @@ final case class ThermalGrid( qDot: Power, thermalDemands: ThermalDemandWrapper, ): (ThermalGridState, Option[ThermalThreshold]) = if (qDot > zeroKW) - handleInfeed(relevantData, lastAmbientTemperature, state, isRunning, qDot, thermalDemands) + handleInfeed( + relevantData, + lastAmbientTemperature, + state, + isRunning, + qDot, + thermalDemands, + ) else handleConsumption( relevantData, @@ -223,9 +230,8 @@ final case class ThermalGrid( ) { val (updatedHouseState, thermalHouseThreshold, remainingQDotHouse) = handleInfeedHouse( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDotHouseLastState, ) @@ -234,13 +240,13 @@ final case class ThermalGrid( qDotStorageLastState >= zeroKW && remainingQDotHouse > qDotStorageLastState ) { handleInfeedStorage( - tick, + relevantData.currentTick, state, remainingQDotHouse, ) } else { handleInfeedStorage( - tick, + relevantData.currentTick, state, qDotStorageLastState, ) @@ -262,9 +268,8 @@ final case class ThermalGrid( else if (qDotHouseLastState > zeroKW && qDotStorageLastState < zeroKW) { if (isRunning) { handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDot, zeroKW, @@ -272,9 +277,8 @@ final case class ThermalGrid( } else { handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDotHouseLastState, qDotStorageLastState, @@ -284,9 +288,8 @@ final case class ThermalGrid( // Handle edge case where house should be heated from storage else if (!isRunning && qDot > zeroKW) { handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDot, -qDot, @@ -294,9 +297,8 @@ final case class ThermalGrid( } else handleFinaleInfeedCases( thermalDemands, - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDot, ) @@ -335,9 +337,8 @@ final case class ThermalGrid( */ private def handleFinaleInfeedCases( thermalDemands: ThermalDemandWrapper, - tick: Long, + relevantData: HpRelevantData, lastAmbientTemperature: Temperature, - ambientTemperature: Temperature, state: ThermalGridState, qDot: Power, ): (ThermalGridState, Option[ThermalThreshold]) = { @@ -351,9 +352,8 @@ final case class ThermalGrid( case (true, _, _, _) => // house first then heatStorage after heating House handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDot, zeroKW, @@ -361,9 +361,8 @@ final case class ThermalGrid( case (_, _, true, _) => handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, zeroKW, qDot, @@ -371,9 +370,8 @@ final case class ThermalGrid( case (false, _, false, true) => handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, zeroKW, qDot, @@ -381,9 +379,8 @@ final case class ThermalGrid( case (_, true, false, false) => handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDot, zeroKW, @@ -391,9 +388,8 @@ final case class ThermalGrid( case (false, false, false, false) => handleCases( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, zeroKW, zeroKW, @@ -408,12 +404,10 @@ final case class ThermalGrid( /** Handles the different cases, of thermal flows from and into the thermal * grid. * - * @param tick - * Current tick + * @param relevantData + * data of heat pump including state of the heat pump * @param lastAmbientTemperature * Ambient temperature until this tick - * @param ambientTemperature - * actual ambient temperature * @param state * Current state of the thermal grid * @param qDotHouse @@ -424,24 +418,22 @@ final case class ThermalGrid( * Updated thermal grid state and the next threshold if there is one */ private def handleCases( - tick: Long, + relevantData: HpRelevantData, lastAmbientTemperature: Temperature, - ambientTemperature: Temperature, state: ThermalGridState, qDotHouse: Power, qDotHeatStorage: Power, ): (ThermalGridState, Option[ThermalThreshold]) = { val (updatedHouseState, thermalHouseThreshold, _) = handleInfeedHouse( - tick, + relevantData, lastAmbientTemperature, - ambientTemperature, state, qDotHouse, ) val (updatedStorageState, thermalStorageThreshold) = - handleInfeedStorage(tick, state, qDotHeatStorage) + handleInfeedStorage(relevantData.currentTick, state, qDotHeatStorage) val nextThreshold = determineMostRecentThreshold( thermalHouseThreshold, @@ -460,12 +452,10 @@ final case class ThermalGrid( /** Handles the case, when the house has heat demand and will be heated up * here. * - * @param tick - * Current tick + * @param relevantData + * data of heat pump including state of the heat pump * @param lastAmbientTemperature * Ambient temperature until this tick - * @param ambientTemperature - * actual ambient temperature * @param state * Current state of the houses * @param qDot @@ -474,19 +464,17 @@ final case class ThermalGrid( * Updated thermal house state, a ThermalThreshold and the remaining qDot */ private def handleInfeedHouse( - tick: Long, + relevantData: HpRelevantData, lastAmbientTemperature: Temperature, - ambientTemperature: Temperature, state: ThermalGridState, qDot: Power, ): (Option[ThermalHouseState], Option[ThermalThreshold], Power) = { (house, state.houseState) match { case (Some(thermalHouse), Some(lastHouseState)) => val (newState, threshold) = thermalHouse.determineState( - tick, + relevantData, lastHouseState, lastAmbientTemperature, - ambientTemperature, qDot, ) /* Check if house can handle the thermal feed in */ From 6163afd4ec2d827ba210670d52a623baa701d63a Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 26 Nov 2024 11:53:41 +0100 Subject: [PATCH 36/44] fix tests after merging dev --- .../model/thermal/ThermalGridWithStorageOnlySpec.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala index c20fb8ce07..2c0b6b0771 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala @@ -231,7 +231,7 @@ class ThermalGridWithStorageOnlySpec } "properly take energy from storage" in { - val tick = 0L + val relevantData = HpRelevantData(0, testGridAmbientTemperature) val gridState = ThermalGrid .startingState(thermalGrid) .copy(storageState = @@ -246,8 +246,7 @@ class ThermalGridWithStorageOnlySpec val (updatedGridState, reachedThreshold) = thermalGrid invokePrivate handleInfeed( - tick, - testGridAmbientTemperature, + relevantData, testGridAmbientTemperature, gridState, isNotRunning, From 634fbf4bbf13e45e9fbe54c8139cc2c7cb04471b Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 26 Nov 2024 13:36:19 +0100 Subject: [PATCH 37/44] fmt --- .../simona/model/thermal/ThermalGrid.scala | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) 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 1850ba27ec..773d862982 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -191,8 +191,8 @@ final case class ThermalGrid( * data of heat pump including state of the heat pump * @param lastAmbientTemperature * Ambient temperature valid up until (not including) the current tick - * @param state - * Current state of the houses + * @param thermalGridState + * Current state of the thermal Grid * @param isRunning * determines whether the heat pump is running or not * @param qDot @@ -200,12 +200,12 @@ final case class ThermalGrid( * @param thermalDemands * holds the thermal demands of the thermal units (house, storage) * @return - * Updated thermal grid state + * Updated thermal grid state and the thermalThreshold if there is one */ private def handleInfeed( relevantData: HpRelevantData, lastAmbientTemperature: Temperature, - state: ThermalGridState, + thermalGridState: ThermalGridState, isRunning: Boolean, qDot: Power, thermalDemands: ThermalDemandWrapper, @@ -213,7 +213,7 @@ final case class ThermalGrid( // TODO: We would need to issue a storage result model here... /* Consider the action in the last state */ - val (qDotHouseLastState, qDotStorageLastState) = state match { + val (qDotHouseLastState, qDotStorageLastState) = thermalGridState match { case ThermalGridState(Some(houseState), Some(storageState)) => (houseState.qDot, storageState.qDot) case ThermalGridState(Some(houseState), None) => (houseState.qDot, zeroKW) @@ -232,7 +232,7 @@ final case class ThermalGrid( handleInfeedHouse( relevantData, lastAmbientTemperature, - state, + thermalGridState, qDotHouseLastState, ) val (updatedStorageState, thermalStorageThreshold) = @@ -241,13 +241,13 @@ final case class ThermalGrid( ) { handleInfeedStorage( relevantData.currentTick, - state, + thermalGridState, remainingQDotHouse, ) } else { handleInfeedStorage( relevantData.currentTick, - state, + thermalGridState, qDotStorageLastState, ) } @@ -257,7 +257,7 @@ final case class ThermalGrid( thermalStorageThreshold, ) ( - state.copy( + thermalGridState.copy( houseState = updatedHouseState, storageState = updatedStorageState, ), @@ -270,7 +270,7 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + thermalGridState, qDot, zeroKW, ) @@ -279,7 +279,7 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + thermalGridState, qDotHouseLastState, qDotStorageLastState, ) @@ -290,16 +290,16 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + thermalGridState, qDot, -qDot, ) } else - handleFinaleInfeedCases( + handleFinalInfeedCases( thermalDemands, relevantData, lastAmbientTemperature, - state, + thermalGridState, qDot, ) } @@ -334,12 +334,25 @@ final case class ThermalGrid( * | 3 | if(!house.reqD && !storage.reqD && storage.addD) => storage | storage | * | 4 | if(!house.reqD && house.addD && !storage.reqD && !storage.addD) => house | house | * | 5 | if(all == false) => no output | no output | + * + * @param thermalDemands + * holds the thermal demands of the thermal units (house, storage) + * @param relevantData + * data of heat pump including state of the heat pump + * @param lastAmbientTemperature + * Ambient temperature valid up until (not including) the current tick + * @param gridState + * Current state of the thermalGrid + * @param qDot + * Infeed to the grid + * @return + * Updated thermal grid state and the thermalThreshold if there is one */ - private def handleFinaleInfeedCases( + private def handleFinalInfeedCases( thermalDemands: ThermalDemandWrapper, relevantData: HpRelevantData, lastAmbientTemperature: Temperature, - state: ThermalGridState, + gridState: ThermalGridState, qDot: Power, ): (ThermalGridState, Option[ThermalThreshold]) = { ( @@ -354,7 +367,7 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + gridState, qDot, zeroKW, ) @@ -363,7 +376,7 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + gridState, zeroKW, qDot, ) @@ -372,7 +385,7 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + gridState, zeroKW, qDot, ) @@ -381,7 +394,7 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + gridState, qDot, zeroKW, ) @@ -390,7 +403,7 @@ final case class ThermalGrid( handleCases( relevantData, lastAmbientTemperature, - state, + gridState, zeroKW, zeroKW, ) @@ -745,7 +758,7 @@ object ThermalGrid { ): ThermalGrid = { val houses = input.houses().asScala.map(ThermalHouse(_)).toSet val storages: Set[ThermalStorage] = input - .storages() + .heatStorages() .asScala .flatMap { case cylindricalInput: CylindricalStorageInput => From 6b97e8e37b8208d30b5d504b5fc896ea48bf5a6b Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 26 Nov 2024 13:38:01 +0100 Subject: [PATCH 38/44] fmt --- 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 773d862982..0aa6a7c979 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -758,7 +758,7 @@ object ThermalGrid { ): ThermalGrid = { val houses = input.houses().asScala.map(ThermalHouse(_)).toSet val storages: Set[ThermalStorage] = input - .heatStorages() + .storages() .asScala .flatMap { case cylindricalInput: CylindricalStorageInput => From 0e484c41b12037e053c1feecbbd3bd06498180d0 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Nov 2024 13:24:06 +0100 Subject: [PATCH 39/44] remove commented-out code --- .../thermal/CylindricalThermalStorage.scala | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala b/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala index 13145f2c7a..9694672907 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/CylindricalThermalStorage.scala @@ -190,23 +190,6 @@ object CylindricalThermalStorage { val minEnergyThreshold: Energy = { // Temporary fix until changes in PSDM are released, Some minimumEnergyThreshold would lead to non-plausible behaviour zeroKWh - /*CylindricalThermalStorage.volumeToEnergy( - CubicMeters( - input.getStorageVolumeLvlMin - .to(Units.CUBIC_METRE) - .getValue - .doubleValue - ), - KilowattHoursPerKelvinCubicMeters( - input.getC - .to(PowerSystemUnits.KILOWATTHOUR_PER_KELVIN_TIMES_CUBICMETRE) - .getValue - .doubleValue - ), - Celsius(input.getInletTemp.to(Units.CELSIUS).getValue.doubleValue()), - Celsius(input.getReturnTemp.to(Units.CELSIUS).getValue.doubleValue()), - ) - */ } val maxEnergyThreshold: Energy = From be33961708b59151d95bce69c16eef541a5b0726 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Nov 2024 18:31:26 +0100 Subject: [PATCH 40/44] fix chp storage level check --- .../model/participant/ChpModelSpec.scala | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala index 57c0dd6725..26ea85895f 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala @@ -236,34 +236,34 @@ class ChpModelSpec "Check storage level after calculating next state with #chpState and heat demand #heatDemand kWh:" in { val testCases = Table( ("chpState", "storageLvl", "heatDemand", "expectedStoredEnergy"), - (chpStateNotRunning, 90, 0, 1035), // tests case (false, false, true) + (chpStateNotRunning, 70, 0, 805), // tests case (false, false, true) ( chpStateNotRunning, - 90, + 70, 8 * 115, - 115, + 0, ), // tests case (false, true, false) - (chpStateNotRunning, 90, 10, 1025), // tests case (false, true, true) - (chpStateRunning, 90, 0, 1135), // tests case (true, false, true) - (chpStateRunning, 90, 8 * 115, 215), // tests case (true, true, false) - (chpStateRunning, 90, 10, 1125), // tests case (true, true, true) + (chpStateNotRunning, 70, 10, 795), // tests case (false, true, true) + (chpStateRunning, 70, 0, 905), // tests case (true, false, true) + (chpStateRunning, 70, 8 * 115, 0), // tests case (true, true, false) + (chpStateRunning, 70, 10, 895), // tests case (true, true, true) ( chpStateRunning, - 90, + 70, 806, - 329, + 99, ), // test case (_, true, false) and demand covered together with chp ( chpStateRunning, - 90, + 70, 9 * 115, - 100, + 0, ), // test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 92, + 72, 1, - 1150, + 927, ), // test case (true, true, true) and storage volume exceeds maximum ) From 88c4e24bf28e75ee37bbb059456a7ab2f0803fe4 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Nov 2024 18:59:03 +0100 Subject: [PATCH 41/44] use table for testing purposes --- .../model/participant/ChpModelSpec.scala | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala index 26ea85895f..818d62d7a3 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala @@ -281,8 +281,14 @@ class ChpModelSpec } "Check time tick and running status after calculating next state with #chpState and heat demand #heatDemand kWh:" in { - val testCases = Seq( - // (ChpState, Storage Level, Heat Demand, Expected Time Tick, Expected Running Status) + val testCases = Table( + ( + "chpState", + "storageLvl", + "heatDemand", + "expectedTick", + "expectedRunningStatus", + ), ( chpStateNotRunning, 90, @@ -336,23 +342,22 @@ class ChpModelSpec ), // Test case (true, true, true) and storage volume exceeds maximum ) - for ( + forAll(testCases) { ( - chpState, - storageLvl, - heatDemand, - expectedTimeTick, - expectedRunningStatus, - ) <- testCases - ) { - val chpData = buildChpRelevantData(chpState, heatDemand) - val thermalStorage = buildThermalStorage(storageInput, storageLvl) - val chpModel = buildChpModel(thermalStorage) + chpState, + storageLvl, + heatDemand, + expectedTick, + expectedRunningStatus, + ) => + val chpData = buildChpRelevantData(chpState, heatDemand) + val thermalStorage = buildThermalStorage(storageInput, storageLvl) + val chpModel = buildChpModel(thermalStorage) - val nextState = chpModel.calculateNextState(chpData) + val nextState = chpModel.calculateNextState(chpData) - nextState.lastTimeTick shouldEqual expectedTimeTick - nextState.isRunning shouldEqual expectedRunningStatus + nextState.lastTimeTick shouldEqual expectedTick + nextState.isRunning shouldEqual expectedRunningStatus } } From 51fa462eb82489367b864f69444852239073a4c1 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Nov 2024 18:59:28 +0100 Subject: [PATCH 42/44] fix ChpModelSpec --- .../model/participant/ChpModelSpec.scala | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala index 818d62d7a3..348be8b7a4 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala @@ -50,7 +50,7 @@ class ChpModelSpec val chpStateNotRunning: ChpState = ChpState(isRunning = false, 0, Kilowatts(0), KilowattHours(0)) val chpStateRunning: ChpState = - ChpState(isRunning = true, 0, Kilowatts(0), KilowattHours(0)) + ChpState(isRunning = true, 0, Kilowatts(42), KilowattHours(42)) val (storageInput, chpInput) = setupSpec() @@ -145,32 +145,32 @@ class ChpModelSpec "Check active power after calculating next state with #chpState and heat demand #heatDemand kWh:" in { val testCases = Table( ("chpState", "storageLvl", "heatDemand", "expectedActivePower"), - (chpStateNotRunning, 90, 0, 0), // tests case (false, false, true) + (chpStateNotRunning, 70, 0, 0), // tests case (false, false, true) ( chpStateNotRunning, - 90, - 8 * 115 + 230, + 70, + 8 * 115, 95, ), // tests case (false, true, false) - (chpStateNotRunning, 90, 10, 0), // tests case (false, true, true) - (chpStateRunning, 90, 0, 95), // tests case (true, false, true) - (chpStateRunning, 90, 8 * 115, 95), // tests case (true, true, false) - (chpStateRunning, 90, 10, 95), // tests case (true, true, true) + (chpStateNotRunning, 70, 10, 0), // tests case (false, true, true) + (chpStateRunning, 70, 0, 95), // tests case (true, false, true) + (chpStateRunning, 70, 8 * 115, 95), // tests case (true, true, false) + (chpStateRunning, 70, 10, 95), // tests case (true, true, true) ( chpStateRunning, - 90, + 70, 7 * 115 + 1, 95, ), // test case (_, true, false) and demand covered together with chp ( chpStateRunning, - 90, + 70, 9 * 115, 95, ), // test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 92, + 72, 1, 95, ), // test case (true, true, true) and storage volume exceeds maximum @@ -190,34 +190,34 @@ class ChpModelSpec "Check total energy after calculating next state with #chpState and heat demand #heatDemand kWh:" in { val testCases = Table( ("chpState", "storageLvl", "heatDemand", "expectedTotalEnergy"), - (chpStateNotRunning, 90, 0, 0), // tests case (false, false, true) + (chpStateNotRunning, 70, 0, 0), // tests case (false, false, true) ( chpStateNotRunning, - 90, - 8 * 115 + 230, + 70, + 8 * 115, 100, ), // tests case (false, true, false) - (chpStateNotRunning, 90, 10, 0), // tests case (false, true, true) - (chpStateRunning, 90, 0, 100), // tests case (true, false, true) - (chpStateRunning, 90, 8 * 115, 100), // tests case (true, true, false) - (chpStateRunning, 90, 10, 100), // tests case (true, true, true) + (chpStateNotRunning, 70, 10, 0), // tests case (false, true, true) + (chpStateRunning, 70, 0, 100), // tests case (true, false, true) + (chpStateRunning, 70, 8 * 115, 100), // tests case (true, true, false) + (chpStateRunning, 70, 10, 100), // tests case (true, true, true) ( chpStateRunning, - 90, + 70, 7 * 115 + 1, 100, ), // test case (_, true, false) and demand covered together with chp ( chpStateRunning, - 90, + 70, 9 * 115, 100, ), // test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 92, + 72, 1, - 93, + 100, ), // test case (true, true, true) and storage volume exceeds maximum ) @@ -291,51 +291,51 @@ class ChpModelSpec ), ( chpStateNotRunning, - 90, + 70, 0, 7200, false, ), // Test case (false, false, true) ( chpStateNotRunning, - 90, - 8 * 115 + 230, + 70, + 8 * 115, 7200, true, ), // Test case (false, true, false) ( chpStateNotRunning, - 90, + 70, 10, 7200, false, ), // Test case (false, true, true) - (chpStateRunning, 90, 0, 7200, true), // Test case (true, false, true) + (chpStateRunning, 70, 0, 7200, true), // Test case (true, false, true) ( chpStateRunning, - 90, + 70, 8 * 115, 7200, true, ), // Test case (true, true, false) - (chpStateRunning, 90, 10, 7200, true), // Test case (true, true, true) + (chpStateRunning, 70, 10, 7200, true), // Test case (true, true, true) ( chpStateRunning, - 90, + 70, 806, 7200, true, ), // Test case (_, true, false) and demand covered together with chp ( chpStateRunning, - 90, + 70, 9 * 115, 7200, true, ), // Test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 92, + 72, 1, 7200, false, From 42105bd106a9c76b36a15531a0bdd513619b8430 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 27 Nov 2024 19:11:32 +0100 Subject: [PATCH 43/44] hopefully final fix for ChpModelSpec --- .../simona/model/participant/ChpModelSpec.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala index 348be8b7a4..c664788dae 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala @@ -170,7 +170,7 @@ class ChpModelSpec ), // test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 72, + 92, 1, 95, ), // test case (true, true, true) and storage volume exceeds maximum @@ -215,9 +215,9 @@ class ChpModelSpec ), // test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 72, + 92, 1, - 100, + 93, ), // test case (true, true, true) and storage volume exceeds maximum ) @@ -261,9 +261,9 @@ class ChpModelSpec ), // test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 72, + 92, 1, - 927, + 1150, ), // test case (true, true, true) and storage volume exceeds maximum ) @@ -289,7 +289,7 @@ class ChpModelSpec "expectedTick", "expectedRunningStatus", ), - ( + ( chpStateNotRunning, 70, 0, @@ -335,7 +335,7 @@ class ChpModelSpec ), // Test case (_, true, false) and demand not covered together with chp ( chpStateRunning, - 72, + 92, 1, 7200, false, From ef8556b96e954ef5b2d8626cac6a0e50326cae85 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Wed, 11 Dec 2024 15:57:25 +0100 Subject: [PATCH 44/44] fmt --- .../scala/edu/ie3/simona/model/participant/ChpModelSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala index 26eb66e314..8a43b3c6ff 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/ChpModelSpec.scala @@ -289,7 +289,7 @@ class ChpModelSpec "expectedTick", "expectedRunningStatus", ), - ( + ( chpStateNotRunning, 70, 0,