From 6e9b40f1c004020a54500edc5dccc408e88c318b Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 24 Aug 2024 09:56:41 +0200 Subject: [PATCH 01/27] Refactoring of ThermalGrid.energyGrid to distinguish between demand of house and storage --- CHANGELOG.md | 1 + .../participant/hp/HpAgentFundamentals.scala | 6 +- .../simona/model/participant/HpModel.scala | 148 +++-- .../simona/model/thermal/ThermalGrid.scala | 105 +++- .../model/participant/HpModelSpec.scala | 537 ++++++++++++++---- .../ThermalGridWithHouseAndStorageSpec.scala | 72 ++- .../ThermalGridWithHouseOnlySpec.scala | 32 +- .../ThermalGridWithStorageOnlySpec.scala | 51 +- 8 files changed, 693 insertions(+), 259 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b25a5dbf..b1de2d3306 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated `Gradle` to version V8.10 [#829](https://github.com/ie3-institute/simona/issues/829) - Updated AUTHORS.md [#905](https://github.com/ie3-institute/simona/issues/905) - Prepare ThermalStorageTestData for Storage without storageVolumeLvlMin [#894](https://github.com/ie3-institute/simona/issues/894) +- Refactoring of `ThermalGrid.energyGrid` to distinguish between demand of house and storage [#928](https://github.com/ie3-institute/simona/issues/928) ### Fixed - Removed a repeated line in the documentation of vn_simona config [#658](https://github.com/ie3-institute/simona/issues/658) diff --git a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala index 9add5d8ddc..7940120b4c 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala @@ -293,7 +293,11 @@ trait HpAgentFundamentals calcRelevantData: HpRelevantData, nodalVoltage: squants.Dimensionless, model: HpModel, - ): HpState = model.determineState(modelState, calcRelevantData) + ): HpState = { + val (_, _, state) = + model.determineState(modelState, calcRelevantData) + state + } /** Abstract definition, individual implementations found in individual agent * fundamental classes 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 4d9fc68899..ad512a75e0 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -11,16 +11,15 @@ import edu.ie3.simona.agent.participant.data.Data.PrimaryData.ApparentPowerAndHe 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.ThermalGridState +import edu.ie3.simona.model.thermal.ThermalGrid.{ThermalEnergyDemand, ThermalGridState} import edu.ie3.simona.model.thermal.{ThermalGrid, ThermalThreshold} import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage.ProvideFlexOptions import edu.ie3.simona.ontology.messages.flex.MinMaxFlexibilityMessage.ProvideMinMaxFlexOptions import edu.ie3.util.quantities.PowerSystemUnits import edu.ie3.util.scala.OperationInterval -import edu.ie3.util.scala.quantities.DefaultQuantities import edu.ie3.util.scala.quantities.DefaultQuantities._ -import squants.energy.Kilowatts -import squants.{Power, Temperature} +import squants.energy.{KilowattHours, Kilowatts} +import squants.{Energy, Power, Temperature} import java.time.ZonedDateTime import java.util.UUID @@ -116,19 +115,23 @@ final case class HpModel( * function calculates the heat pump's next state to get the actual active * power of this state use [[calculateActivePower]] with the generated state * - * @param state - * Current state of the heat pump + * @param lastState + * Last state of the heat pump * @param relevantData * data of heat pump including * @return - * next [[HpState]] + * Booleans if Hp can operate and can be out of operation plus next + * [[HpState]] */ def determineState( - state: HpState, + lastState: HpState, relevantData: HpRelevantData, - ): HpState = { - val turnOn = operatesInNextState(state, relevantData) - calcState(state, relevantData, turnOn) + ): (Boolean, Boolean, HpState) = { + val (turnOn, canOperate, canBeOutOfOperation, houseDemand, storageDemand) = + operatesInNextState(lastState, relevantData) + val updatedState = + calcState(lastState, relevantData, turnOn, houseDemand, storageDemand) + (canOperate, canBeOutOfOperation, updatedState) } /** Depending on the input, this function decides whether the heat pump will @@ -142,18 +145,63 @@ final case class HpModel( * @param relevantData * Relevant (external) data * @return - * boolean defining if heat pump runs in next time step + * boolean defining if heat pump runs in next time step, if it can be in + * operation and out of operation plus the demand of house and storage */ private def operatesInNextState( state: HpState, relevantData: HpRelevantData, - ): Boolean = { - val demand = thermalGrid.energyDemand( - relevantData.currentTick, - relevantData.ambientTemperature, - state.thermalGridState, + ): (Boolean, Boolean, Boolean, Boolean, Boolean) = { + val (demandHouse, demandThermalStorage, updatedState) = + thermalGrid.energyDemandAndUpdatedState( + relevantData.currentTick, + state.ambientTemperature.getOrElse(relevantData.ambientTemperature), + relevantData.ambientTemperature, + state.thermalGridState, + ) + + val ( + houseDemand, + heatStorageDemand, + noThermalStorageOrThermalStorageIsEmpty, + ) = determineDemandBooleans( + state, + updatedState, + demandHouse, + demandThermalStorage, ) - demand.hasRequiredDemand || (state.isRunning && demand.hasAdditionalDemand) + + val turnHpOn: Boolean = + houseDemand || heatStorageDemand + + val canOperate = + demandHouse.hasRequiredDemand || demandHouse.hasAdditionalDemand || + demandThermalStorage.hasRequiredDemand || demandThermalStorage.hasAdditionalDemand + val canBeOutOfOperation = + !(demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) + + (turnHpOn, canOperate, canBeOutOfOperation, houseDemand, heatStorageDemand) + } + + def determineDemandBooleans( + hpState: HpState, + updatedGridState: ThermalGridState, + demandHouse: ThermalEnergyDemand, + demandThermalStorage: ThermalEnergyDemand, + ): (Boolean, Boolean, Boolean) = { + implicit val tolerance: Energy = KilowattHours(1e-3) + val noThermalStorageOrThermalStorageIsEmpty: Boolean = + updatedGridState.storageState.isEmpty || updatedGridState.storageState + .exists( + _.storedEnergy =~ zeroKWH + ) + + val houseDemand = + (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || (hpState.isRunning && demandHouse.hasAdditionalDemand) + val heatStorageDemand = { + (demandThermalStorage.hasRequiredDemand) || (hpState.isRunning && demandThermalStorage.hasAdditionalDemand) + } + (houseDemand, heatStorageDemand, noThermalStorageOrThermalStorageIsEmpty) } /** Calculate state depending on whether heat pump is needed or not. Also @@ -173,11 +221,19 @@ final case class HpModel( state: HpState, relevantData: HpRelevantData, isRunning: Boolean, + houseDemand: Boolean, + storageDemand: Boolean, ): HpState = { + val lastStateStorageqDot = state.thermalGridState.storageState + .map(_.qDot) + .getOrElse(zeroKW) + val (newActivePower, newThermalPower) = if (isRunning) (pRated, pThermal) - else (DefaultQuantities.zeroKW, DefaultQuantities.zeroKW) + else if (lastStateStorageqDot < zeroKW) + (zeroKW, lastStateStorageqDot * (-1)) + else (zeroKW, zeroKW) /* Push thermal energy to the thermal grid and get its updated state in return */ val (thermalGridState, maybeThreshold) = @@ -205,23 +261,14 @@ final case class HpModel( lastState: HpState, ): ProvideFlexOptions = { /* Determine the operating state in the given tick */ - val updatedState = determineState(lastState, data) - - /* Determine the options we have */ - val thermalEnergyDemand = thermalGrid.energyDemand( - data.currentTick, - data.ambientTemperature, - lastState.thermalGridState, - ) - val canOperate = - thermalEnergyDemand.hasRequiredDemand || thermalEnergyDemand.hasAdditionalDemand - val canBeOutOfOperation = !thermalEnergyDemand.hasRequiredDemand + val (canOperate, canBeOutOfOperation, updatedHpState) + : (Boolean, Boolean, HpState) = determineState(lastState, data) val lowerBoundary = if (canBeOutOfOperation) zeroKW else - updatedState.activePower + updatedHpState.activePower val upperBoundary = if (canOperate) sRated * cosPhiRated @@ -230,7 +277,7 @@ final case class HpModel( ProvideMinMaxFlexOptions( uuid, - updatedState.activePower, + updatedHpState.activePower, lowerBoundary, upperBoundary, ) @@ -260,13 +307,44 @@ final case class HpModel( ): (HpState, FlexChangeIndicator) = { /* If the setpoint 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 updatedState = calcState(lastState, data, turnOn) + + val ( + thermalEnergyDemandHouse, + thermalEnergyDemandStorage, + updatedThermalGridState, + ) = + thermalGrid.energyDemandAndUpdatedState( + data.currentTick, + lastState.ambientTemperature.getOrElse(data.ambientTemperature), + data.ambientTemperature, + lastState.thermalGridState, + ) + + val ( + houseDemand, + heatStorageDemand, + noThermalStorageOrThermalStorageIsEmpty, + ) = determineDemandBooleans( + lastState, + updatedThermalGridState, + thermalEnergyDemandHouse, + thermalEnergyDemandStorage, + ) + + val updatedHpState: HpState = + calcState( + lastState, + data, + turnOn, + houseDemand, + heatStorageDemand, + ) ( - updatedState, + updatedHpState, FlexChangeIndicator( changesAtNextActivation = true, - updatedState.maybeThermalThreshold.map(_.tick), + updatedHpState.maybeThermalThreshold.map(_.tick), ), ) } diff --git a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala index 286b0e829f..3e983b6abe 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -43,60 +43,105 @@ final case class ThermalGrid( ) extends LazyLogging { /** Determine the energy demand of the total grid at the given instance in - * time + * time and returns it including the updatedState + * * @param tick * Questioned instance in time + * @param lastAmbientTemperature + * Ambient temperature until this tick * @param ambientTemperature * Ambient temperature in the instance in question * @param state * Currently applicable state of the thermal grid * @return - * The total energy demand of the grid + * The total energy demand of the house and the storage and an updated + * [[ThermalGridState]] */ - def energyDemand( + def energyDemandAndUpdatedState( tick: Long, + // FIXME this is also in state + lastAmbientTemperature: Temperature, ambientTemperature: Temperature, state: ThermalGridState, - ): ThermalEnergyDemand = { - /* First get the energy demand of the houses */ - val houseDemand = house - .zip(state.houseState) - .map { case (house, state) => - house.energyDemand( - tick, - ambientTemperature, - state, - ) + ): (ThermalEnergyDemand, ThermalEnergyDemand, ThermalGridState) = { + /* First get the energy demand of the houses but only if inner temperature is below target temperature */ + + val (houseDemand, updatedHouseState) = + house.zip(state.houseState).headOption match { + case Some((thermalHouse, lastHouseState)) => + val (updatedHouseState, updatedStorageState) = + thermalHouse.determineState( + tick, + lastHouseState, + lastAmbientTemperature, + ambientTemperature, + lastHouseState.qDot, + ) + if ( + updatedHouseState.innerTemperature < thermalHouse.targetTemperature | (lastHouseState.qDot > zeroKW && updatedHouseState.innerTemperature < thermalHouse.upperBoundaryTemperature) + ) { + ( + thermalHouse.energyDemand( + tick, + ambientTemperature, + updatedHouseState, + ), + Some(updatedHouseState), + ) + + } else { + (ThermalEnergyDemand.noDemand, Some(updatedHouseState)) + } + + case None => + (ThermalEnergyDemand.noDemand, None) } - .getOrElse(ThermalEnergyDemand.noDemand) /* Then go over the storages, see what they can provide and what they might be able to charge */ - val (storedEnergy, remainingCapacity) = { + val (storageDemand, updatedStorageState) = { + storage .zip(state.storageState) .map { case (storage, state) => - val usableEnergy = state.storedEnergy - val remaining = storage.getMaxEnergyThreshold - usableEnergy + val (updatedStorageState, _) = + storage.updateState(tick, state.qDot, state) + val storedEnergy = updatedStorageState.storedEnergy + val soc = storedEnergy / storage.getMaxEnergyThreshold + val storageRequired = { + if (soc == 0d) { + storage.getMaxEnergyThreshold - storedEnergy + + } else { + zeroMWH + } + } + + val storagePossible = storage.getMaxEnergyThreshold - storedEnergy ( - usableEnergy, - remaining, + ThermalEnergyDemand( + storageRequired, + storagePossible, + ), + Some(updatedStorageState), ) + } .getOrElse( - (zeroMWH, zeroMWH) + ThermalEnergyDemand(zeroMWH, zeroMWH), + None, ) } - val usedEnergy = - if (storedEnergy >= houseDemand.required) - houseDemand.required - else - storedEnergy - val finallyRemaining = remainingCapacity + usedEnergy - - ThermalEnergyDemand( - houseDemand.required - usedEnergy, - houseDemand.possible + finallyRemaining, + ( + ThermalEnergyDemand( + houseDemand.required, + houseDemand.possible, + ), + ThermalEnergyDemand( + storageDemand.required, + storageDemand.possible, + ), + ThermalGridState(updatedHouseState, updatedStorageState), ) } 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 e99a5c8c26..81c62e549d 100644 --- a/src/test/scala/edu/ie3/simona/model/participant/HpModelSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/participant/HpModelSpec.scala @@ -208,14 +208,18 @@ class HpModelSpec val hp = hpModel(grid) hp.determineState(state, data) match { - case HpState( - isRunning, + case ( _, _, - activePower, - _, - ThermalGridState(Some(thermalHouseState), _), - maybeThreshold, + HpState( + isRunning, + _, + _, + activePower, + _, + ThermalGridState(Some(thermalHouseState), _), + maybeThreshold, + ), ) => isRunning shouldBe expectedRunningState activePower should approximate(Kilowatts(expectedActivePower)) @@ -234,166 +238,447 @@ class HpModelSpec "determining the flexibility options for different states" should { "deliver correct flexibility options" in { - val testCases = Table( - ("thermalState", "lastState", "expectedValues"), - // House is below lower temperature boundary - ( - ThermalGridState( - Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), - Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + val testCases = + Table( + ("thermalState", "lastState", "expectedValues"), + // 1. Hp actually not running + // House is below lower temperature boundary + // Heat storage is empty + // hp must be turned on + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(0.0), + Kilowatts(0.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + None, + ), + (95.0, 95.0, 95.0), ), - HpState( - isRunning = false, - 0, - Some(hpData.ambientTemperature), - Kilowatts(0.0), - Kilowatts(0.0), + // 2. Same as before but heat storage is NOT empty + // should be possible to keep hp off + ( ThermalGridState( Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), - Some( - ThermalStorageState(0L, KilowattHours(20), Kilowatts(0)) + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(0.0), + Kilowatts(0.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(20), Kilowatts(0)) + ), ), + None, ), - None, + (0.0, 0.0, 95.0), ), - (95.0, 95.0, 95.0), - ), - // House is between target temperature and lower temperature boundary, Hp actually running - ( - ThermalGridState( - Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), - Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + // 3. Hp actually running + // House is below lower temperature boundary + // Heat storage is empty + // Hp must run because of house and storage + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(0.0), + Kilowatts(0.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(0), Kilowatts(0)) + ), + ), + None, + ), + (95.0, 95.0, 95.0), ), - HpState( - isRunning = true, - 0, - Some(hpData.ambientTemperature), - Kilowatts(95.0), - Kilowatts(80.0), + // 4. Same as before but heat storage is NOT empty + // Hp should not run because of storage but can be turned on + ( ThermalGridState( - Some(ThermalHouseState(0L, Celsius(19), Kilowatts(80))), - Some( - ThermalStorageState(0L, KilowattHours(20), Kilowatts(0)) + Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(0.0), + Kilowatts(0.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(15), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(20), Kilowatts(0)) + ), ), + None, ), - None, + (0.0, 0.0, 95.0), ), - (95.0, 0.0, 95.0), - ), - - // House is between target temperature and lower temperature boundary, Hp actually not running - ( - ThermalGridState( - Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), - Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + // 5. Hp actually running + // House is between target temperature and lower temperature boundary + // Heat storage is empty + // Hp runs but can be turned off + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(0), Kilowatts(0)) + ), + ), + None, + ), + (95.0, 0.0, 95.0), ), - HpState( - isRunning = false, - 0, - Some(hpData.ambientTemperature), - Kilowatts(0.0), - Kilowatts(0.0), + // 6. Same as before but heat storage is NOT empty + // should be possible to keep hp off + ( ThermalGridState( Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), - Some( - ThermalStorageState(0L, KilowattHours(20), Kilowatts(0)) + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(20), Kilowatts(0)) + ), ), + None, ), - None, + (95.0, 0.0, 95.0), ), - (0.0, 0.0, 95.0), - ), - // Storage and house have remaining capacity - ( - ThermalGridState( - Some(ThermalHouseState(0L, Celsius(21), Kilowatts(80))), - Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + // 7. Hp actually NOT running + // House is between target temperature and lower temperature boundary + // Heat storage is empty + // Hp should run because of storage but can be turned off + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(0), Kilowatts(0)) + ), + ), + None, + ), + (95.0, 0.0, 95.0), ), - HpState( - isRunning = true, - 0, - Some(hpData.ambientTemperature), - Kilowatts(95.0), - Kilowatts(80.0), + // 8. Same as before but heat storage is NOT empty + // Hp should be off but able to turn on + ( ThermalGridState( - Some(ThermalHouseState(0L, Celsius(21), Kilowatts(80))), + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), ), - Some(HouseTemperatureUpperBoundaryReached(0L)), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(20), Kilowatts(0)) + ), + ), + None, + ), + (0.0, 0.0, 95.0), ), - (95.0, 0.0, 95.0), - ), - - // Storage is full, House has capacity till upper boundary - ( - ThermalGridState( - Some(ThermalHouseState(0L, Celsius(21), Kilowatts(80))), - Some(ThermalStorageState(0L, KilowattHours(500), Kilowatts(0))), + // 9. Hp actually running + // House is between target temperature and upper temperature boundary + // Heat storage is empty + // Hp will run because of storage but can be turned off + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (95.0, 0.0, 95.0), ), - HpState( - isRunning = false, - 0, - Some(hpData.ambientTemperature), - Kilowatts(0.0), - Kilowatts(0.0), + // 10. Same as before but storage is NOT empty + // Hp should run but can be turned off + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (95.0, 0.0, 95.0), + ), + // 11. Hp actually not running + // House is between target temperature and upper temperature boundary + // Heat storage is empty + // Hp should run because of storage but can be turned off + ( ThermalGridState( - Some(ThermalHouseState(0L, Celsius(21), Kilowatts(80))), - Some( - ThermalStorageState(0L, KilowattHours(500), Kilowatts(0)) + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), ), + Some(HouseTemperatureUpperBoundaryReached(0L)), ), - Some(HouseTemperatureUpperBoundaryReached(0L)), + (95.0, 0.0, 95.0), + ), + // 12. Same as before but storage is NOT empty + // Hp should not run but can be turned on for storage or house + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (0.0, 0.0, 95.0), ), - (0.0, 0.0, 95.0), - ), - // No capacity for flexibility at all because house is - // at upperTempBoundary and storage is at max capacity - ( - ThermalGridState( - Some(ThermalHouseState(0L, Celsius(22), Kilowatts(80))), - Some(ThermalStorageState(0L, KilowattHours(500), Kilowatts(0))), + // 13. Hp actually running + // House is at upper temperature boundary + // Heat storage is empty + // Hp should run because of storage but can be turned off + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(22), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (95.0, 0.0, 95.0), ), - HpState( - isRunning = true, - 0, - Some(hpData.ambientTemperature), - Kilowatts(95.0), - Kilowatts(80.0), + // 14. Same as before but storage is NOT empty + // Hp should run but can be turned off + ( ThermalGridState( - Some(ThermalHouseState(0L, Celsius(22), Kilowatts(80))), - Some( - ThermalStorageState(0L, KilowattHours(500), Kilowatts(0)) + Some(ThermalHouseState(0L, Celsius(22), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), ), + Some(HouseTemperatureUpperBoundaryReached(0L)), ), - Some(HouseTemperatureUpperBoundaryReached(0L)), + (95.0, 0.0, 95.0), + ), + // 15. Hp actually not running + // House is at upper temperature boundary + // Heat storage is empty + // Hp should run because of storage but can be turned off + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(22), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(0), Kilowatts(0))), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (95.0, 0.0, 95.0), ), - (0.0, 0.0, 0.0), - ), - // No capacity for flexibility at all when storage is full and house has been (externally) heated up above upperTemperatureBoundary - ( - ThermalGridState( - Some(ThermalHouseState(0L, Celsius(25), Kilowatts(0))), - Some(ThermalStorageState(0L, KilowattHours(500), Kilowatts(0))), + // 16. Same as before but storage is NOT empty + // Hp should not run but can be turned on for storage + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(22), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(20), Kilowatts(0))), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (0.0, 0.0, 95.0), ), - HpState( - isRunning = false, - 0, - Some(hpData.ambientTemperature), - Kilowatts(95.0), - Kilowatts(80.0), + + // Storage is full, House has capacity till upper boundary + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(21), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(500), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(0.0), + Kilowatts(0.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(19), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(500), Kilowatts(0)) + ), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (0.0, 0.0, 95.0), + ), + // No capacity for flexibility at all because house is + // at upperTempBoundary and storage is at max capacity + ( + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(22), Kilowatts(0))), + Some(ThermalStorageState(0L, KilowattHours(500), Kilowatts(0))), + ), + HpState( + isRunning = true, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(22), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(500), Kilowatts(0)) + ), + ), + Some(HouseTemperatureUpperBoundaryReached(0L)), + ), + (0.0, 0.0, 0.0), + ), + + // No capacity for flexibility at all when storage is full and house has been (externally) heated up above upperTemperatureBoundary + ( ThermalGridState( Some(ThermalHouseState(0L, Celsius(25), Kilowatts(0))), - Some( - ThermalStorageState(0L, KilowattHours(500), Kilowatts(0)) + Some(ThermalStorageState(0L, KilowattHours(500), Kilowatts(0))), + ), + HpState( + isRunning = false, + 0, + Some(hpData.ambientTemperature), + Kilowatts(95.0), + Kilowatts(80.0), + ThermalGridState( + Some(ThermalHouseState(0L, Celsius(25), Kilowatts(0))), + Some( + ThermalStorageState(0L, KilowattHours(500), Kilowatts(0)) + ), ), + None, ), - None, + (0.0, 0.0, 0.0), ), - (0.0, 0.0, 0.0), - ), - ) + ) // Run the test cases forAll(testCases) { 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 5d4fe69d88..1ea45a656d 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala @@ -96,53 +96,51 @@ class ThermalGridWithHouseAndStorageSpec "deliver the house demand (no demand) with added flexibility by storage" in { val tick = 10800 // after three hours - val gridDemand = thermalGrid.energyDemand( - tick, - testGridAmbientTemperature, - ThermalGrid.startingState(thermalGrid), + val (houseDemand, storageDemand, updatedThermalGridState) = + thermalGrid.energyDemandAndUpdatedState( + tick, + testGridAmbientTemperature, + testGridAmbientTemperature, + ThermalGrid.startingState(thermalGrid), + ) + houseDemand.required should approximate(KilowattHours(0d)) + houseDemand.possible should approximate(KilowattHours(31.05009722d)) + storageDemand.required should approximate(KilowattHours(1150d)) + storageDemand.possible should approximate(KilowattHours(1150d)) + updatedThermalGridState.houseState shouldBe Some( + ThermalHouseState(10800, Kelvin(292.0799935185185), Kilowatts(0d)) ) - - gridDemand.required should approximate(KilowattHours(0d)) - gridDemand.possible should approximate( - KilowattHours(31.05009722 + 1150) + updatedThermalGridState.storageState shouldBe Some( + ThermalStorageState(10800, KilowattHours(0d), Kilowatts(0d)) ) } - "consider stored energy to reduce house demand" in { + "deliver the correct house and storage demand" in { val tick = 10800 // after three hours val startingState = ThermalGrid.startingState(thermalGrid) - val gridDemand = thermalGrid.energyDemand( - tick, - testGridAmbientTemperature, - startingState.copy(houseState = - startingState.houseState.map( - _.copy(innerTemperature = Celsius(16d)) - ) - ), - ) - - gridDemand.required should approximate(KilowattHours(45.60005555555534)) - gridDemand.possible should approximate(KilowattHours(1225.600055555)) - } - - "consider stored energy to reduce house demand if stored energy is not enough" in { - val tick = 10800 // after three hours + val (houseDemand, storageDemand, updatedThermalGridState) = + thermalGrid.energyDemandAndUpdatedState( + tick, + testGridAmbientTemperature, + testGridAmbientTemperature, + startingState.copy(houseState = + startingState.houseState.map( + _.copy(innerTemperature = Celsius(16d)) + ) + ), + ) - val startingState = ThermalGrid.startingState(thermalGrid) - val gridDemand = thermalGrid.energyDemand( - tick, - testGridAmbientTemperature, - startingState.copy(houseState = - startingState.houseState.map( - _.copy(innerTemperature = Celsius(3d)) - ) - ), + houseDemand.required should approximate(KilowattHours(45.6000555)) + houseDemand.possible should approximate(KilowattHours(75.600055555)) + storageDemand.required should approximate(KilowattHours(1150d)) + storageDemand.possible should approximate(KilowattHours(1150d)) + updatedThermalGridState.houseState shouldBe Some( + ThermalHouseState(10800, Celsius(15.959996296296296), Kilowatts(0d)) ) - gridDemand.required should approximate( - KilowattHours(238.64987499999984) + updatedThermalGridState.storageState shouldBe Some( + ThermalStorageState(10800, KilowattHours(0d), Kilowatts(0d)) ) - gridDemand.possible should approximate(KilowattHours(1418.64987499999)) } } 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 d2b48ff3b3..eb447d0fc4 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala @@ -14,9 +14,9 @@ import edu.ie3.simona.model.thermal.ThermalHouse.ThermalHouseThreshold.{ HouseTemperatureUpperBoundaryReached, } import edu.ie3.simona.test.common.UnitSpec -import squants.energy.{Kilowatts, Megawatts, WattHours, Watts} +import squants.energy._ import squants.thermal.Celsius -import squants.{Energy, Power, Temperature} +import squants.{Energy, Kelvin, Power, Temperature} import scala.jdk.CollectionConverters._ @@ -73,21 +73,29 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { "determining the energy demand" should { "exactly be the demand of the house" in { - val tick = 10800 // after three house - val houseDemand = thermalHouse.energyDemand( + val tick = 10800 // after three hours + val expectedHouseDemand = thermalHouse.energyDemand( tick, testGridAmbientTemperature, expectedHouseStartingState, ) - val gridDemand = thermalGrid.energyDemand( - tick, - testGridAmbientTemperature, - ThermalGrid.startingState(thermalGrid), - ) + val (houseDemand, storageDemand, updatedThermalGridState) = + thermalGrid.energyDemandAndUpdatedState( + tick, + testGridAmbientTemperature, + testGridAmbientTemperature, + ThermalGrid.startingState(thermalGrid), + ) - gridDemand.required should approximate(houseDemand.required) - gridDemand.possible should approximate(houseDemand.possible) + houseDemand.required should approximate(expectedHouseDemand.required) + houseDemand.possible should approximate(expectedHouseDemand.possible) + storageDemand.required should approximate(KilowattHours(0d)) + storageDemand.possible should approximate(KilowattHours(0d)) + updatedThermalGridState.houseState shouldBe Some( + ThermalHouseState(10800, Kelvin(292.0799935185185), Kilowatts(0d)) + ) + updatedThermalGridState.storageState shouldBe None } } @@ -127,7 +135,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { } "not withdraw energy from the house, if actual consumption is given" in { - val tick = 0L // after three house + val tick = 0L // after three hours val gridState = ThermalGrid.startingState(thermalGrid) val (updatedGridState, reachedThreshold) = 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 bbb804c35f..93a45e3180 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala @@ -80,31 +80,46 @@ class ThermalGridWithStorageOnlySpec "deliver the capabilities of the storage" in { val tick = 10800 // after three hours - val gridDemand = thermalGrid.energyDemand( - tick, - testGridAmbientTemperature, - ThermalGrid.startingState(thermalGrid), - ) - - gridDemand.required should approximate(KilowattHours(0d)) - gridDemand.possible should approximate(KilowattHours(1150d)) + val (houseDemand, storageDemand, updatedThermalGridState) = + thermalGrid.energyDemandAndUpdatedState( + tick, + testGridAmbientTemperature, + testGridAmbientTemperature, + ThermalGrid.startingState(thermalGrid), + ) + houseDemand.required should approximate(KilowattHours(0d)) + houseDemand.possible should approximate(KilowattHours(0d)) + storageDemand.required should approximate(KilowattHours(1150d)) + storageDemand.possible should approximate(KilowattHours(1150d)) + updatedThermalGridState.houseState shouldBe None + updatedThermalGridState.storageState shouldBe Some( + ThermalStorageState(10800, KilowattHours(0d), Kilowatts(0d)) + ) } "deliver the capabilities of a half full storage" in { val tick = 10800 // after three hours - val gridDemand = thermalGrid.energyDemand( - tick, - testGridAmbientTemperature, - ThermalGridState( - None, - Some(ThermalStorageState(0L, KilowattHours(575d), Kilowatts(0d))), - ), - ) + val (houseDemand, storageDemand, updatedThermalGridState) = + thermalGrid.energyDemandAndUpdatedState( + tick, + testGridAmbientTemperature, + testGridAmbientTemperature, + ThermalGridState( + None, + Some(ThermalStorageState(0L, KilowattHours(575d), Kilowatts(0d))), + ), + ) - gridDemand.required should approximate(KilowattHours(0d)) - gridDemand.possible should approximate(KilowattHours(575d)) + houseDemand.required should approximate(KilowattHours(0d)) + houseDemand.possible should approximate(KilowattHours(0d)) + storageDemand.required should approximate(KilowattHours(0d)) + storageDemand.possible should approximate(KilowattHours(575d)) + updatedThermalGridState.houseState shouldBe None + updatedThermalGridState.storageState shouldBe Some( + ThermalStorageState(10800L, KilowattHours(575d), Kilowatts(0d)) + ) } } From 67e2a4e433b0c7d5ef8931ae95299de116f15066 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 24 Aug 2024 10:00:39 +0200 Subject: [PATCH 02/27] fmt --- .../scala/edu/ie3/simona/model/participant/HpModel.scala | 5 ++++- 1 file changed, 4 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 ad512a75e0..569bd48c10 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -11,7 +11,10 @@ import edu.ie3.simona.agent.participant.data.Data.PrimaryData.ApparentPowerAndHe 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.{ThermalEnergyDemand, ThermalGridState} +import edu.ie3.simona.model.thermal.ThermalGrid.{ + ThermalEnergyDemand, + ThermalGridState, +} import edu.ie3.simona.model.thermal.{ThermalGrid, ThermalThreshold} import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage.ProvideFlexOptions import edu.ie3.simona.ontology.messages.flex.MinMaxFlexibilityMessage.ProvideMinMaxFlexOptions From 1ec348cc749eccd6a27a21d044ee5efca8cde191 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 24 Aug 2024 11:10:56 +0200 Subject: [PATCH 03/27] Add unapply method for ThermalHouseResults --- CHANGELOG.md | 1 + .../edu/ie3/simona/agent/ValueStore.scala | 2 +- .../ParticipantAgentFundamentals.scala | 5 +- .../edu/ie3/simona/event/ResultEvent.scala | 59 ++++++++++++++++++- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b43cb834c8..2b39983e5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update RTD references and bibliography [#868](https://github.com/ie3-institute/simona/issues/868) - Add gradle application plugin for command line execution with gradle run [#890](https://github.com/ie3-institute/simona/issues/890) - Additional tests to check flexibility options of thermal house and storage [#729](https://github.com/ie3-institute/simona/issues/729) +- Add unapply method for ThermalHouseResults [#934](https://github.com/ie3-institute/simona/issues/934) ### Changed - Adapted to changed data source in PSDM [#435](https://github.com/ie3-institute/simona/issues/435) diff --git a/src/main/scala/edu/ie3/simona/agent/ValueStore.scala b/src/main/scala/edu/ie3/simona/agent/ValueStore.scala index a21f7d0f58..fbae2ff77c 100644 --- a/src/main/scala/edu/ie3/simona/agent/ValueStore.scala +++ b/src/main/scala/edu/ie3/simona/agent/ValueStore.scala @@ -22,7 +22,7 @@ import scala.collection.SortedMap */ final case class ValueStore[+D]( maxTickSpan: Long, - private val store: SortedMap[Long, D] = SortedMap.empty[Long, D], + store: SortedMap[Long, D] = SortedMap.empty[Long, D], ) { /** Determine the lastly known data tick, if available. Includes the given diff --git a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala index e9fef1ad20..fe78e9136f 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala @@ -1907,8 +1907,9 @@ protected trait ParticipantAgentFundamentals[ def buildResultEvent[R <: ResultEntity]( result: R ): Option[ResultEvent] = result match { - case thermalResult: ThermalUnitResult => - Some(ThermalResultEvent(thermalResult)) + case thermalUnitResult: ThermalUnitResult => + Some(ThermalResultEvent(thermalUnitResult)) + case unsupported => log.debug( s"Results of class '${unsupported.getClass.getSimpleName}' are currently not supported." diff --git a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala index d81242c608..a1a765d977 100644 --- a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala +++ b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala @@ -16,9 +16,18 @@ import edu.ie3.datamodel.models.result.system.{ FlexOptionsResult, SystemParticipantResult, } -import edu.ie3.datamodel.models.result.thermal.ThermalUnitResult +import edu.ie3.datamodel.models.result.thermal.{ + CylindricalStorageResult, + ThermalHouseResult, + ThermalUnitResult, +} import edu.ie3.simona.agent.grid.GridResultsSupport.PartialTransformer3wResult import edu.ie3.simona.event.listener.ResultEventListener +import tech.units.indriya.ComparableQuantity + +import java.time.ZonedDateTime +import java.util.UUID +import javax.measure.quantity.{Energy, Power, Temperature} sealed trait ResultEvent extends Event with ResultEventListener.Request @@ -44,6 +53,54 @@ object ResultEvent { thermalResult: ThermalUnitResult ) extends ResultEvent + object ThermalHouseResult { + def unapply(result: ThermalHouseResult): Option[ + ( + ZonedDateTime, + UUID, + ComparableQuantity[Power], + ComparableQuantity[Temperature], + ) + ] = { + if (result != null) { + Some( + ( + result.getTime, + result.getInputModel, + result.getqDot, + result.getIndoorTemperature, + ) + ) + } else { + None + } + } + } + + object CylindricalThermalStorageResult { + def unapply(result: CylindricalStorageResult): Option[ + ( + ZonedDateTime, + UUID, + ComparableQuantity[Power], + ComparableQuantity[Energy], + ) + ] = { + if (result != null) { + Some( + ( + result.getTime, + result.getInputModel, + result.getqDot, + result.getEnergy, + ) + ) + } else { + None + } + } + } + /** Event that holds all grid calculation results of a power flow calculation. * The usage of a type is necessary here, to avoid passing in other instances * of [[edu.ie3.datamodel.models.result.ResultEntity]] except of the wanted From 32dea34a90aac575aeaf263eb2be80fb8e369d1f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Sat, 26 Oct 2024 18:06:06 +0200 Subject: [PATCH 04/27] remove unused parameter --- .../simona/model/participant/HpModel.scala | 29 +------------------ 1 file changed, 1 insertion(+), 28 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 569bd48c10..3c02b58f09 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -133,7 +133,7 @@ final case class HpModel( val (turnOn, canOperate, canBeOutOfOperation, houseDemand, storageDemand) = operatesInNextState(lastState, relevantData) val updatedState = - calcState(lastState, relevantData, turnOn, houseDemand, storageDemand) + calcState(lastState, relevantData, turnOn) (canOperate, canBeOutOfOperation, updatedState) } @@ -224,8 +224,6 @@ final case class HpModel( state: HpState, relevantData: HpRelevantData, isRunning: Boolean, - houseDemand: Boolean, - storageDemand: Boolean, ): HpState = { val lastStateStorageqDot = state.thermalGridState.storageState .map(_.qDot) @@ -311,36 +309,11 @@ final case class HpModel( /* If the setpoint 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, - noThermalStorageOrThermalStorageIsEmpty, - ) = determineDemandBooleans( - lastState, - updatedThermalGridState, - thermalEnergyDemandHouse, - thermalEnergyDemandStorage, - ) - val updatedHpState: HpState = calcState( lastState, data, turnOn, - houseDemand, - heatStorageDemand, ) ( From e886345b083572f60a6d97665d4613cb42385c09 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 28 Oct 2024 09:25:43 +0100 Subject: [PATCH 05/27] remove unused parameter --- .../scala/edu/ie3/simona/model/participant/HpModel.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 3c02b58f09..e136de4d54 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -130,7 +130,7 @@ final case class HpModel( lastState: HpState, relevantData: HpRelevantData, ): (Boolean, Boolean, HpState) = { - val (turnOn, canOperate, canBeOutOfOperation, houseDemand, storageDemand) = + val (turnOn, canOperate, canBeOutOfOperation) = operatesInNextState(lastState, relevantData) val updatedState = calcState(lastState, relevantData, turnOn) @@ -149,12 +149,12 @@ final case class HpModel( * Relevant (external) data * @return * boolean defining if heat pump runs in next time step, if it can be in - * operation and out of operation plus the demand of house and storage + * operation and can be out of operation */ private def operatesInNextState( state: HpState, relevantData: HpRelevantData, - ): (Boolean, Boolean, Boolean, Boolean, Boolean) = { + ): (Boolean, Boolean, Boolean) = { val (demandHouse, demandThermalStorage, updatedState) = thermalGrid.energyDemandAndUpdatedState( relevantData.currentTick, @@ -183,7 +183,7 @@ final case class HpModel( val canBeOutOfOperation = !(demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) - (turnHpOn, canOperate, canBeOutOfOperation, houseDemand, heatStorageDemand) + (turnHpOn, canOperate, canBeOutOfOperation) } def determineDemandBooleans( From b893c0897a3a23b2725c8af9362bd7458dbb0bd2 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 28 Oct 2024 09:49:22 +0100 Subject: [PATCH 06/27] fix scapegoat code smell because of unnecessary store before return --- .../ie3/simona/agent/participant/hp/HpAgentFundamentals.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala index a390f290b6..9eb908d1ac 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala @@ -314,9 +314,7 @@ trait HpAgentFundamentals nodalVoltage: squants.Dimensionless, model: HpModel, ): HpState = { - val (_, _, state) = - model.determineState(modelState, calcRelevantData) - state + model.determineState(modelState, calcRelevantData)._3 } /** Abstract definition, individual implementations found in individual agent From 23b2582f027a3869d7b09e623f550d1bbccfe686 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Mon, 28 Oct 2024 12:06:54 +0100 Subject: [PATCH 07/27] Proposal for separating state and operation point calculation --- .../simona/model/participant/HpModel.scala | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 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 e136de4d54..1eb45443ec 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -118,7 +118,7 @@ final case class HpModel( * function calculates the heat pump's next state to get the actual active * power of this state use [[calculateActivePower]] with the generated state * - * @param lastState + * @param lastHpState * Last state of the heat pump * @param relevantData * data of heat pump including @@ -127,13 +127,34 @@ final case class HpModel( * [[HpState]] */ def determineState( - lastState: HpState, + lastHpState: HpState, relevantData: HpRelevantData, ): (Boolean, Boolean, HpState) = { + + // Use lastHpState and relevantData to update state of thermalGrid to the current tick + val (demandHouse, demandThermalStorage, currentThermalGridState) = + thermalGrid.energyDemandAndUpdatedState( + relevantData.currentTick, + lastHpState.ambientTemperature.getOrElse( + relevantData.ambientTemperature + ), + relevantData.ambientTemperature, + lastHpState.thermalGridState, + ) + + // Determining the operation point and limitations at this tick val (turnOn, canOperate, canBeOutOfOperation) = - operatesInNextState(lastState, relevantData) + operatesInNextState( + lastHpState, + currentThermalGridState, + relevantData, + demandHouse, + demandThermalStorage, + ) + + // Updating the HpState val updatedState = - calcState(lastState, relevantData, turnOn) + calcState(lastHpState, relevantData, turnOn) (canOperate, canBeOutOfOperation, updatedState) } @@ -143,39 +164,41 @@ final case class HpModel( * met or the heat pump currently is in operation and the grid is able to * handle additional energy * - * @param state - * Current state of the heat pump + * @param lastState + * last state of the heat pump + * @param currentThermalGridState + * 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 * @return * boolean defining if heat pump runs in next time step, if it can be in * operation and can be out of operation */ private def operatesInNextState( - state: HpState, + lastState: HpState, + currentThermalGridState: ThermalGridState, relevantData: HpRelevantData, + demandHouse: ThermalEnergyDemand, + demandThermalStorage: ThermalEnergyDemand, ): (Boolean, Boolean, Boolean) = { - val (demandHouse, demandThermalStorage, updatedState) = - thermalGrid.energyDemandAndUpdatedState( - relevantData.currentTick, - state.ambientTemperature.getOrElse(relevantData.ambientTemperature), - relevantData.ambientTemperature, - state.thermalGridState, - ) val ( - houseDemand, - heatStorageDemand, + houseHasDemand, + heatStorageHasDemand, noThermalStorageOrThermalStorageIsEmpty, ) = determineDemandBooleans( - state, - updatedState, + lastState, + currentThermalGridState, demandHouse, demandThermalStorage, ) val turnHpOn: Boolean = - houseDemand || heatStorageDemand + houseHasDemand || heatStorageHasDemand val canOperate = demandHouse.hasRequiredDemand || demandHouse.hasAdditionalDemand || From 6be8e36fe31833c3e6b727be6572b2b3b9e69ff4 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 29 Oct 2024 11:30:30 +0100 Subject: [PATCH 08/27] aligning states of HpModel --- .../participant/hp/HpAgentFundamentals.scala | 4 +- .../simona/model/participant/HpModel.scala | 48 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala index 9eb908d1ac..dc9465e67b 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala @@ -189,7 +189,7 @@ trait HpAgentFundamentals val accompanyingResults = baseStateData.model.thermalGrid.results( tick, - updatedState.thermalGridState, + updatedState.currentThermalGridState, )(baseStateData.startDate) val result = AccompaniedSimulationResult(power, accompanyingResults) @@ -254,7 +254,7 @@ trait HpAgentFundamentals ) val accompanyingResults = baseStateData.model.thermalGrid.results( currentTick, - lastModelState.thermalGridState, + lastModelState.currentThermalGridState, )(baseStateData.startDate) val result = AccompaniedSimulationResult(power, accompanyingResults) 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 1eb45443ec..a3f04c0209 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -82,7 +82,7 @@ final case class HpModel( * [[HpModel.determineState]]. This state then is fed into the power * calculation logic by [[HpState]]. * - * @param modelState + * @param currentState * Current state of the heat pump * @param relevantData * data of heat pump including state of the heat pump @@ -90,9 +90,9 @@ final case class HpModel( * active power */ override protected def calculateActivePower( - modelState: HpState, + currentState: HpState, relevantData: HpRelevantData, - ): Power = modelState.activePower + ): Power = currentState.activePower /** "Calculate" the heat output of the heat pump. The hp's state is already * updated, because the calculation of apparent power in @@ -101,7 +101,7 @@ final case class HpModel( * * @param tick * Current simulation time for the calculation - * @param modelState + * @param currentState * Current state of the heat pump * @param data * Relevant (external) data for calculation @@ -110,20 +110,20 @@ final case class HpModel( */ override def calculateHeat( tick: Long, - modelState: HpState, + currentState: HpState, data: HpRelevantData, - ): Power = modelState.qDot + ): Power = currentState.qDot - /** Given a [[HpRelevantData]] object and the current [[HpState]], this - * function calculates the heat pump's next state to get the actual active - * power of this state use [[calculateActivePower]] with the generated state + /** Given a [[HpRelevantData]] object and the last [[HpState]], this function + * calculates the heat pump's next state to get the actual active power of + * this state use [[calculateActivePower]] with the generated state * * @param lastHpState * Last state of the heat pump * @param relevantData * data of heat pump including * @return - * Booleans if Hp can operate and can be out of operation plus next + * Booleans if Hp can operate and can be out of operation plus the updated * [[HpState]] */ def determineState( @@ -139,7 +139,7 @@ final case class HpModel( relevantData.ambientTemperature ), relevantData.ambientTemperature, - lastHpState.thermalGridState, + lastHpState.currentThermalGridState, ) // Determining the operation point and limitations at this tick @@ -210,7 +210,7 @@ final case class HpModel( } def determineDemandBooleans( - hpState: HpState, + lastHpState: HpState, updatedGridState: ThermalGridState, demandHouse: ThermalEnergyDemand, demandThermalStorage: ThermalEnergyDemand, @@ -223,9 +223,9 @@ final case class HpModel( ) val houseDemand = - (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || (hpState.isRunning && demandHouse.hasAdditionalDemand) + (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || (lastHpState.isRunning && demandHouse.hasAdditionalDemand) val heatStorageDemand = { - (demandThermalStorage.hasRequiredDemand) || (hpState.isRunning && demandThermalStorage.hasAdditionalDemand) + (demandThermalStorage.hasRequiredDemand) || (lastHpState.isRunning && demandThermalStorage.hasAdditionalDemand) } (houseDemand, heatStorageDemand, noThermalStorageOrThermalStorageIsEmpty) } @@ -234,8 +234,8 @@ final case class HpModel( * calculate inner temperature change of thermal house and update its inner * temperature. * - * @param state - * Current state of the heat pump + * @param lastState + * state of the heat pump until this tick * @param relevantData * data of heat pump including state of the heat pump * @param isRunning @@ -244,27 +244,27 @@ final case class HpModel( * next [[HpState]] */ private def calcState( - state: HpState, + lastState: HpState, relevantData: HpRelevantData, isRunning: Boolean, ): HpState = { - val lastStateStorageqDot = state.thermalGridState.storageState + val lastStateStorageQDot = lastState.currentThermalGridState.storageState .map(_.qDot) .getOrElse(zeroKW) val (newActivePower, newThermalPower) = if (isRunning) (pRated, pThermal) - else if (lastStateStorageqDot < zeroKW) - (zeroKW, lastStateStorageqDot * (-1)) + else if (lastStateStorageQDot < zeroKW) + (zeroKW, lastStateStorageQDot * (-1)) else (zeroKW, zeroKW) /* Push thermal energy to the thermal grid and get its updated state in return */ val (thermalGridState, maybeThreshold) = thermalGrid.updateState( relevantData.currentTick, - state.thermalGridState, - state.ambientTemperature.getOrElse(relevantData.ambientTemperature), + lastState.currentThermalGridState, + lastState.ambientTemperature.getOrElse(relevantData.ambientTemperature), relevantData.ambientTemperature, newThermalPower, ) @@ -411,7 +411,7 @@ object HpModel { * result active power * @param qDot * result heat power - * @param thermalGridState + * @param currentThermalGridState * Currently applicable state of the thermal grid * @param maybeThermalThreshold * An optional threshold of the thermal grid, indicating the next state @@ -423,7 +423,7 @@ object HpModel { ambientTemperature: Option[Temperature], activePower: Power, qDot: Power, - thermalGridState: ThermalGridState, + currentThermalGridState: ThermalGridState, maybeThermalThreshold: Option[ThermalThreshold], ) extends ModelState From 286f0ebad8d7f9b94dccf7a2bad139db0721ee61 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 29 Oct 2024 11:30:41 +0100 Subject: [PATCH 09/27] add scala doc --- .../edu/ie3/simona/model/participant/HpModel.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 a3f04c0209..c104571b9b 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -209,6 +209,20 @@ final case class HpModel( (turnHpOn, canOperate, canBeOutOfOperation) } + /** This method will return booleans whether there is a heat demand of house + * or thermal storage as well as a boolean indicating if there is no thermal + * storage or it is empty. + * + * @param lastHpState + * @param updatedGridState + * @param demandHouse + * @param demandThermalStorage + * @return + * First boolean: true, if house has heat demand Second boolean: true, if + * thermalStorage has heat demand Third boolean: true, if there is no + * thermalStorage or it's empty + */ + def determineDemandBooleans( lastHpState: HpState, updatedGridState: ThermalGridState, From f44dddff0798a43571e0440edeb78ef265b46284 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 1 Nov 2024 18:15:07 +0100 Subject: [PATCH 10/27] merging dev --- .../ie3/simona/agent/participant/hp/HpAgentFundamentals.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala index 58b9c402b1..128e1e7395 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala @@ -189,7 +189,7 @@ trait HpAgentFundamentals val accompanyingResults = baseStateData.model.thermalGrid.results( updatedState.tick, - updatedState.thermalGridState, + updatedState.currentThermalGridState, )(baseStateData.startDate) val result = AccompaniedSimulationResult(power, accompanyingResults) @@ -254,7 +254,7 @@ trait HpAgentFundamentals ) val accompanyingResults = baseStateData.model.thermalGrid.results( updatedState.tick, - updatedState.thermalGridState, + updatedState.currentThermalGridState, )(baseStateData.startDate) val result = AccompaniedSimulationResult(power, accompanyingResults) From ae614e9e6735edb76d83650d578ad2bc1d90c69d Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 5 Nov 2024 16:09:27 +0100 Subject: [PATCH 11/27] ValueStore.store again private val --- src/main/scala/edu/ie3/simona/agent/ValueStore.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/agent/ValueStore.scala b/src/main/scala/edu/ie3/simona/agent/ValueStore.scala index fbae2ff77c..a21f7d0f58 100644 --- a/src/main/scala/edu/ie3/simona/agent/ValueStore.scala +++ b/src/main/scala/edu/ie3/simona/agent/ValueStore.scala @@ -22,7 +22,7 @@ import scala.collection.SortedMap */ final case class ValueStore[+D]( maxTickSpan: Long, - store: SortedMap[Long, D] = SortedMap.empty[Long, D], + private val store: SortedMap[Long, D] = SortedMap.empty[Long, D], ) { /** Determine the lastly known data tick, if available. Includes the given From 3243763269dfa98026bfc340f2c0c87356f31255 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 5 Nov 2024 16:09:47 +0100 Subject: [PATCH 12/27] SonarQube issue null parameter --- src/main/scala/edu/ie3/simona/event/ResultEvent.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala index a1a765d977..da844a801f 100644 --- a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala +++ b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala @@ -62,7 +62,7 @@ object ResultEvent { ComparableQuantity[Temperature], ) ] = { - if (result != null) { + Option(result).flatMap { result => Some( ( result.getTime, @@ -71,8 +71,6 @@ object ResultEvent { result.getIndoorTemperature, ) ) - } else { - None } } } @@ -86,7 +84,7 @@ object ResultEvent { ComparableQuantity[Energy], ) ] = { - if (result != null) { + Option(result).flatMap { result => Some( ( result.getTime, @@ -95,8 +93,6 @@ object ResultEvent { result.getEnergy, ) ) - } else { - None } } } From 80fbc092122622856e269af10d4e7046a9d6c4f2 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 5 Nov 2024 16:36:39 +0100 Subject: [PATCH 13/27] remove not necessary headOption --- 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 ee743d88ca..40de44725c 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -67,7 +67,7 @@ final case class ThermalGrid( /* First get the energy demand of the houses but only if inner temperature is below target temperature */ val (houseDemand, updatedHouseState) = - house.zip(state.houseState).headOption match { + house.zip(state.houseState) match { case Some((thermalHouse, lastHouseState)) => val (updatedHouseState, updatedStorageState) = thermalHouse.determineState( From 1beb478839d9ec62e979df7ffa753f994d053c3a Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 5 Nov 2024 16:36:47 +0100 Subject: [PATCH 14/27] break long line --- src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala | 3 ++- 1 file changed, 2 insertions(+), 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 40de44725c..074d80e0a4 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -78,7 +78,8 @@ final case class ThermalGrid( lastHouseState.qDot, ) if ( - updatedHouseState.innerTemperature < thermalHouse.targetTemperature | (lastHouseState.qDot > zeroKW && updatedHouseState.innerTemperature < thermalHouse.upperBoundaryTemperature) + updatedHouseState.innerTemperature < thermalHouse.targetTemperature | + (lastHouseState.qDot > zeroKW && updatedHouseState.innerTemperature < thermalHouse.upperBoundaryTemperature) ) { ( thermalHouse.energyDemand( From 07a65f11afef654dfdeae05de1208a95df2fa61f Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 5 Nov 2024 16:37:02 +0100 Subject: [PATCH 15/27] use wildcard for not used val --- 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 074d80e0a4..0d868e64df 100644 --- a/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala +++ b/src/main/scala/edu/ie3/simona/model/thermal/ThermalGrid.scala @@ -69,7 +69,7 @@ final case class ThermalGrid( val (houseDemand, updatedHouseState) = house.zip(state.houseState) match { case Some((thermalHouse, lastHouseState)) => - val (updatedHouseState, updatedStorageState) = + val (updatedHouseState, _) = thermalHouse.determineState( tick, lastHouseState, From 79e91c21efa356bc4d68184335e5eac170481f40 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 5 Nov 2024 16:45:24 +0100 Subject: [PATCH 16/27] rollback currentThermalGridState to thermalGridState --- .../agent/participant/hp/HpAgentFundamentals.scala | 4 ++-- .../edu/ie3/simona/model/participant/HpModel.scala | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala index 128e1e7395..58b9c402b1 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/hp/HpAgentFundamentals.scala @@ -189,7 +189,7 @@ trait HpAgentFundamentals val accompanyingResults = baseStateData.model.thermalGrid.results( updatedState.tick, - updatedState.currentThermalGridState, + updatedState.thermalGridState, )(baseStateData.startDate) val result = AccompaniedSimulationResult(power, accompanyingResults) @@ -254,7 +254,7 @@ trait HpAgentFundamentals ) val accompanyingResults = baseStateData.model.thermalGrid.results( updatedState.tick, - updatedState.currentThermalGridState, + updatedState.thermalGridState, )(baseStateData.startDate) val result = AccompaniedSimulationResult(power, accompanyingResults) 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 ccc295e240..4f3b1f92bc 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -139,7 +139,7 @@ final case class HpModel( relevantData.ambientTemperature ), relevantData.ambientTemperature, - lastHpState.currentThermalGridState, + lastHpState.thermalGridState, ) // Determining the operation point and limitations at this tick @@ -262,7 +262,7 @@ final case class HpModel( relevantData: HpRelevantData, isRunning: Boolean, ): HpState = { - val lastStateStorageQDot = lastState.currentThermalGridState.storageState + val lastStateStorageQDot = lastState.thermalGridState.storageState .map(_.qDot) .getOrElse(zeroKW) @@ -277,7 +277,7 @@ final case class HpModel( val (thermalGridState, maybeThreshold) = thermalGrid.updateState( relevantData.currentTick, - lastState.currentThermalGridState, + lastState.thermalGridState, lastState.ambientTemperature.getOrElse(relevantData.ambientTemperature), relevantData.ambientTemperature, newThermalPower, @@ -425,8 +425,8 @@ object HpModel { * result active power * @param qDot * result heat power - * @param currentThermalGridState - * Currently applicable state of the thermal grid + * @param thermalGridState + * applicable state of the thermal grid * @param maybeThermalThreshold * An optional threshold of the thermal grid, indicating the next state * change @@ -437,7 +437,7 @@ object HpModel { ambientTemperature: Option[Temperature], activePower: Power, qDot: Power, - currentThermalGridState: ThermalGridState, + thermalGridState: ThermalGridState, maybeThermalThreshold: Option[ThermalThreshold], ) extends ModelState From 71c9852a0c38526266f5afeaadb1b6e6a61cc756 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Tue, 5 Nov 2024 16:45:36 +0100 Subject: [PATCH 17/27] scala doc format --- .../scala/edu/ie3/simona/model/participant/HpModel.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 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 4f3b1f92bc..41927fd2b0 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -218,9 +218,9 @@ final case class HpModel( * @param demandHouse * @param demandThermalStorage * @return - * First boolean: true, if house has heat demand Second boolean: true, if - * thermalStorage has heat demand Third boolean: true, if there is no - * thermalStorage or it's empty + * 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. */ def determineDemandBooleans( From f819146eac5a7099b6381c239c5ba7943af3d01c Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 13 Nov 2024 17:56:28 +0100 Subject: [PATCH 18/27] Tiny bit of code cleanup --- .../simona/model/participant/HpModel.scala | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 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 41927fd2b0..9f0e94a9cf 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -223,7 +223,7 @@ final case class HpModel( * thermalStorage or it's empty. */ - def determineDemandBooleans( + private def determineDemandBooleans( lastHpState: HpState, updatedGridState: ThermalGridState, demandHouse: ThermalEnergyDemand, @@ -238,9 +238,8 @@ final case class HpModel( val houseDemand = (demandHouse.hasRequiredDemand && noThermalStorageOrThermalStorageIsEmpty) || (lastHpState.isRunning && demandHouse.hasAdditionalDemand) - val heatStorageDemand = { - (demandThermalStorage.hasRequiredDemand) || (lastHpState.isRunning && demandThermalStorage.hasAdditionalDemand) - } + val heatStorageDemand = + demandThermalStorage.hasRequiredDemand || (lastHpState.isRunning && demandThermalStorage.hasAdditionalDemand) (houseDemand, heatStorageDemand, noThermalStorageOrThermalStorageIsEmpty) } @@ -270,7 +269,7 @@ final case class HpModel( if (isRunning) (pRated, pThermal) else if (lastStateStorageQDot < zeroKW) - (zeroKW, lastStateStorageQDot * (-1)) + (zeroKW, lastStateStorageQDot * -1) else (zeroKW, zeroKW) /* Push thermal energy to the thermal grid and get its updated state in return */ @@ -346,12 +345,11 @@ final case class HpModel( /* If the setpoint 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 updatedHpState: HpState = - calcState( - lastState, - data, - turnOn, - ) + val updatedHpState = calcState( + lastState, + data, + turnOn, + ) ( updatedHpState, From 61acfb680ea1ac13088d6b0c89b9d54e142d743a Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 09:45:37 +0100 Subject: [PATCH 19/27] grammar --- src/main/scala/edu/ie3/simona/model/participant/HpModel.scala | 4 ++-- 1 file 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 9f0e94a9cf..f555827013 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -211,7 +211,7 @@ final case class HpModel( /** This method will return booleans whether there is a heat demand of house * or thermal storage as well as a boolean indicating if there is no thermal - * storage or it is empty. + * storage, or it is empty. * * @param lastHpState * @param updatedGridState @@ -220,7 +220,7 @@ final case class HpModel( * @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. + * thermalStorage, or it's empty. */ private def determineDemandBooleans( From 671325ea387a1f5663794d39a07c493ab5b890ca Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 12:56:30 +0100 Subject: [PATCH 20/27] fmt from review --- .../edu/ie3/simona/event/ResultEvent.scala | 71 +++++++++---------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala index da844a801f..5e86582ffb 100644 --- a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala +++ b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala @@ -53,47 +53,44 @@ object ResultEvent { thermalResult: ThermalUnitResult ) extends ResultEvent - object ThermalHouseResult { - def unapply(result: ThermalHouseResult): Option[ - ( - ZonedDateTime, - UUID, - ComparableQuantity[Power], - ComparableQuantity[Temperature], - ) - ] = { - Option(result).flatMap { result => - Some( - ( - result.getTime, - result.getInputModel, - result.getqDot, - result.getIndoorTemperature, - ) + object ThermalHouseResult + def unapply(result: ThermalHouseResult): Option[ + ( + ZonedDateTime, + UUID, + ComparableQuantity[Power], + ComparableQuantity[Temperature], + ) + ] = + Option(result).flatMap { result => + Some( + ( + result.getTime, + result.getInputModel, + result.getqDot, + result.getIndoorTemperature, ) - } + ) } - } - object CylindricalThermalStorageResult { - def unapply(result: CylindricalStorageResult): Option[ - ( - ZonedDateTime, - UUID, - ComparableQuantity[Power], - ComparableQuantity[Energy], - ) - ] = { - Option(result).flatMap { result => - Some( - ( - result.getTime, - result.getInputModel, - result.getqDot, - result.getEnergy, - ) + object CylindricalThermalStorageResult + def unapply(result: CylindricalStorageResult): Option[ + ( + ZonedDateTime, + UUID, + ComparableQuantity[Power], + ComparableQuantity[Energy], + ) + ] = { + Option(result).flatMap { result => + Some( + ( + result.getTime, + result.getInputModel, + result.getqDot, + result.getEnergy, ) - } + ) } } From 5790cff86f58e6d13c92d05aacc5cd0fc4731a6d Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Thu, 14 Nov 2024 12:59:45 +0100 Subject: [PATCH 21/27] update scalaDoc --- src/main/scala/edu/ie3/simona/model/participant/HpModel.scala | 4 ++++ 1 file changed, 4 insertions(+) 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 f555827013..bf26b80fd8 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/HpModel.scala @@ -214,9 +214,13 @@ final case class HpModel( * storage, or it is empty. * * @param lastHpState + * 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 From 1e99533088964742ca9166b3cba4a65781125be3 Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 15 Nov 2024 08:09:27 +0100 Subject: [PATCH 22/27] Update src/main/scala/edu/ie3/simona/event/ResultEvent.scala include reviewers suggestion Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/event/ResultEvent.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala index 5e86582ffb..2ec9ab5882 100644 --- a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala +++ b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala @@ -62,16 +62,14 @@ object ResultEvent { ComparableQuantity[Temperature], ) ] = - Option(result).flatMap { result => - Some( + Option(result).map { result => ( result.getTime, result.getInputModel, result.getqDot, result.getIndoorTemperature, ) - ) - } + } object CylindricalThermalStorageResult def unapply(result: CylindricalStorageResult): Option[ From 005b9b7261ee5fd2f2fa007d219e9dbfd1a3fb4b Mon Sep 17 00:00:00 2001 From: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> Date: Fri, 15 Nov 2024 08:09:57 +0100 Subject: [PATCH 23/27] Update src/main/scala/edu/ie3/simona/event/ResultEvent.scala include more suggestion from reviewer Co-authored-by: Sebastian Peter --- src/main/scala/edu/ie3/simona/event/ResultEvent.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala index 2ec9ab5882..0ccaa7f909 100644 --- a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala +++ b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala @@ -80,16 +80,14 @@ object ResultEvent { ComparableQuantity[Energy], ) ] = { - Option(result).flatMap { result => - Some( + Option(result).map { result => ( result.getTime, result.getInputModel, result.getqDot, result.getEnergy, ) - ) - } + } } /** Event that holds all grid calculation results of a power flow calculation. From 61e71a1cdc5b910b6662f98b3adbacb306a45486 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 08:14:59 +0100 Subject: [PATCH 24/27] add brackets for objects --- .../edu/ie3/simona/event/ResultEvent.scala | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala index 0ccaa7f909..6e91283b65 100644 --- a/src/main/scala/edu/ie3/simona/event/ResultEvent.scala +++ b/src/main/scala/edu/ie3/simona/event/ResultEvent.scala @@ -53,15 +53,15 @@ object ResultEvent { thermalResult: ThermalUnitResult ) extends ResultEvent - object ThermalHouseResult - def unapply(result: ThermalHouseResult): Option[ - ( - ZonedDateTime, - UUID, - ComparableQuantity[Power], - ComparableQuantity[Temperature], - ) - ] = + object ThermalHouseResult { + def unapply(result: ThermalHouseResult): Option[ + ( + ZonedDateTime, + UUID, + ComparableQuantity[Power], + ComparableQuantity[Temperature], + ) + ] = Option(result).map { result => ( result.getTime, @@ -70,16 +70,17 @@ object ResultEvent { result.getIndoorTemperature, ) } + } - object CylindricalThermalStorageResult - def unapply(result: CylindricalStorageResult): Option[ - ( - ZonedDateTime, - UUID, - ComparableQuantity[Power], - ComparableQuantity[Energy], - ) - ] = { + object CylindricalThermalStorageResult { + def unapply(result: CylindricalStorageResult): Option[ + ( + ZonedDateTime, + UUID, + ComparableQuantity[Power], + ComparableQuantity[Energy], + ) + ] = { Option(result).map { result => ( result.getTime, @@ -88,6 +89,7 @@ object ResultEvent { result.getEnergy, ) } + } } /** Event that holds all grid calculation results of a power flow calculation. From ee7fbcccaa565087bdc5a2486d20eed6d548ae02 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 12:54:42 +0100 Subject: [PATCH 25/27] use zeroKW and zeroKWH within thermal unit tests --- .../ThermalGridWithHouseAndStorageSpec.scala | 23 +++++++------- .../ThermalGridWithHouseOnlySpec.scala | 17 +++++----- .../ThermalGridWithStorageOnlySpec.scala | 31 ++++++++++--------- 3 files changed, 37 insertions(+), 34 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 1ea45a656d..f2829532cd 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseAndStorageSpec.scala @@ -13,6 +13,7 @@ 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, @@ -103,15 +104,15 @@ class ThermalGridWithHouseAndStorageSpec testGridAmbientTemperature, ThermalGrid.startingState(thermalGrid), ) - houseDemand.required should approximate(KilowattHours(0d)) + houseDemand.required should approximate(zeroKWH) houseDemand.possible should approximate(KilowattHours(31.05009722d)) storageDemand.required should approximate(KilowattHours(1150d)) storageDemand.possible should approximate(KilowattHours(1150d)) updatedThermalGridState.houseState shouldBe Some( - ThermalHouseState(10800, Kelvin(292.0799935185185), Kilowatts(0d)) + ThermalHouseState(10800, Kelvin(292.0799935185185), zeroKW) ) updatedThermalGridState.storageState shouldBe Some( - ThermalStorageState(10800, KilowattHours(0d), Kilowatts(0d)) + ThermalStorageState(10800, zeroKWH, zeroKW) ) } @@ -136,10 +137,10 @@ class ThermalGridWithHouseAndStorageSpec storageDemand.required should approximate(KilowattHours(1150d)) storageDemand.possible should approximate(KilowattHours(1150d)) updatedThermalGridState.houseState shouldBe Some( - ThermalHouseState(10800, Celsius(15.959996296296296), Kilowatts(0d)) + ThermalHouseState(10800, Celsius(15.959996296296296), zeroKW) ) updatedThermalGridState.storageState shouldBe Some( - ThermalStorageState(10800, KilowattHours(0d), Kilowatts(0d)) + ThermalStorageState(10800, zeroKWH, zeroKW) ) } } @@ -159,7 +160,7 @@ class ThermalGridWithHouseAndStorageSpec storageState.copy(storedEnergy = initialLoading) ) ) - val externalQDot = Kilowatts(0d) + val externalQDot = zeroKW val (updatedGridState, reachedThreshold) = thermalGrid invokePrivate handleConsumption( @@ -216,7 +217,7 @@ class ThermalGridWithHouseAndStorageSpec ) => houseTick shouldBe 0L innerTemperature should approximate(Celsius(18.9999d)) - qDotHouse should approximate(Kilowatts(0d)) + qDotHouse should approximate(zeroKW) storageTick shouldBe 0L storedEnergy should approximate(initialLoading) @@ -228,7 +229,7 @@ class ThermalGridWithHouseAndStorageSpec } "revising infeed from storage to house" should { - val zeroInflux = Kilowatts(0d) + val zeroInflux = zeroKW val tick = 3600L val ambientTemperature = Celsius(14d) "hand back unaltered information if needed information is missing" in { @@ -371,7 +372,7 @@ class ThermalGridWithHouseAndStorageSpec ( ThermalStorageState( tick, - KilowattHours(0d), + zeroKWH, testGridQDotInfeed, ), Some(StorageEmpty(tick)), @@ -517,7 +518,7 @@ class ThermalGridWithHouseAndStorageSpec .getOrElse(fail("No initial storage state found")) ) - qDotStorage should approximate(Kilowatts(0d)) + qDotStorage should approximate(zeroKW) case _ => fail("Thermal grid state has been calculated wrong.") } @@ -554,7 +555,7 @@ class ThermalGridWithHouseAndStorageSpec ) => houseTick shouldBe 0L innerTemperature should approximate(Celsius(20.99999167d)) - qDotHouse should approximate(Kilowatts(0d)) + qDotHouse should approximate(zeroKW) storageTick shouldBe 0L storedEnergy should approximate( 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..c0d6226694 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala @@ -13,6 +13,7 @@ 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 squants.energy._ import squants.thermal.Celsius @@ -90,10 +91,10 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { houseDemand.required should approximate(expectedHouseDemand.required) houseDemand.possible should approximate(expectedHouseDemand.possible) - storageDemand.required should approximate(KilowattHours(0d)) - storageDemand.possible should approximate(KilowattHours(0d)) + storageDemand.required should approximate(zeroKWH) + storageDemand.possible should approximate(zeroKWH) updatedThermalGridState.houseState shouldBe Some( - ThermalHouseState(10800, Kelvin(292.0799935185185), Kilowatts(0d)) + ThermalHouseState(10800, Kelvin(292.0799935185185), zeroKW) ) updatedThermalGridState.storageState shouldBe None } @@ -108,7 +109,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { "deliver the house state by just letting it cool down, if just no infeed is given" in { val tick = 0L val gridState = ThermalGrid.startingState(thermalGrid) - val externalQDot = Megawatts(0d) + val externalQDot =zeroKW val (updatedGridState, reachedThreshold) = thermalGrid invokePrivate handleConsumption( @@ -154,7 +155,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ) => tick shouldBe 0L innerTemperature should approximate(Celsius(18.9999d)) - qDot should approximate(Megawatts(0d)) + qDot should approximate(zeroKW) case _ => fail("Thermal grid state has been calculated wrong.") } reachedThreshold shouldBe Some( @@ -239,7 +240,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ) => tick shouldBe 0L innerTemperature should approximate(Celsius(18.9999d)) - qDot should approximate(Megawatts(0d)) + qDot should approximate(zeroKW) thresholdTick shouldBe 154285L case _ => fail("Thermal grid state updated failed") } @@ -251,7 +252,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ThermalGrid.startingState(thermalGrid), testGridAmbientTemperature, testGridAmbientTemperature, - Megawatts(0d), + zeroKW, ) match { case ( ThermalGridState( @@ -262,7 +263,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { ) => tick shouldBe 0L innerTemperature should approximate(Celsius(18.9999d)) - qDot should approximate(Kilowatts(0d)) + qDot should approximate(zeroKW) thresholdTick shouldBe 154285L case _ => fail("Thermal grid state updated failed") } 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..9ef8dbb424 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithStorageOnlySpec.scala @@ -17,6 +17,7 @@ import edu.ie3.simona.model.thermal.ThermalStorage.ThermalStorageThreshold.{ 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, Power, Temperature} @@ -88,13 +89,13 @@ class ThermalGridWithStorageOnlySpec ThermalGrid.startingState(thermalGrid), ) - houseDemand.required should approximate(KilowattHours(0d)) - houseDemand.possible should approximate(KilowattHours(0d)) + houseDemand.required should approximate(zeroKWH) + houseDemand.possible should approximate(zeroKWH) storageDemand.required should approximate(KilowattHours(1150d)) storageDemand.possible should approximate(KilowattHours(1150d)) updatedThermalGridState.houseState shouldBe None updatedThermalGridState.storageState shouldBe Some( - ThermalStorageState(10800, KilowattHours(0d), Kilowatts(0d)) + ThermalStorageState(10800, zeroKWH, zeroKW) ) } @@ -108,17 +109,17 @@ class ThermalGridWithStorageOnlySpec testGridAmbientTemperature, ThermalGridState( None, - Some(ThermalStorageState(0L, KilowattHours(575d), Kilowatts(0d))), + Some(ThermalStorageState(0L, KilowattHours(575d), zeroKW)), ), ) - houseDemand.required should approximate(KilowattHours(0d)) - houseDemand.possible should approximate(KilowattHours(0d)) - storageDemand.required should approximate(KilowattHours(0d)) + houseDemand.required should approximate(zeroKWH) + houseDemand.possible should approximate(zeroKWH) + storageDemand.required should approximate(zeroKWH) storageDemand.possible should approximate(KilowattHours(575d)) updatedThermalGridState.houseState shouldBe None updatedThermalGridState.storageState shouldBe Some( - ThermalStorageState(10800L, KilowattHours(575d), Kilowatts(0d)) + ThermalStorageState(10800L, KilowattHours(575d), zeroKW) ) } } @@ -138,7 +139,7 @@ class ThermalGridWithStorageOnlySpec ThermalStorageState( 0L, KilowattHours(200d), - Kilowatts(0d), + zeroKW, ) ) ) @@ -191,7 +192,7 @@ class ThermalGridWithStorageOnlySpec Some(ThermalStorageState(tick, storedEnergy, qDot)), ) => tick shouldBe 0L - storedEnergy should approximate(KilowattHours(0d)) + storedEnergy should approximate(zeroKWH) qDot should approximate(testGridQDotInfeed) case _ => fail("Thermal grid state has been calculated wrong.") } @@ -217,7 +218,7 @@ class ThermalGridWithStorageOnlySpec Some(ThermalStorageState(tick, storedEnergy, qDot)), ) => tick shouldBe 0L - storedEnergy should approximate(KilowattHours(0d)) + storedEnergy should approximate(zeroKWH) qDot should approximate(testGridQDotInfeed) case _ => fail("Thermal grid state updated failed") } @@ -233,7 +234,7 @@ class ThermalGridWithStorageOnlySpec ThermalStorageState( 0L, KilowattHours(200d), - Kilowatts(0d), + zeroKW, ) ) ), @@ -262,7 +263,7 @@ class ThermalGridWithStorageOnlySpec ThermalGrid.startingState(thermalGrid), testGridAmbientTemperature, testGridAmbientTemperature, - Kilowatts(0d), + zeroKW, ) updatedState match { case ( @@ -273,8 +274,8 @@ class ThermalGridWithStorageOnlySpec None, ) => tick shouldBe 0L - storedEnergy should approximate(KilowattHours(0d)) - qDot should approximate(Megawatts(0d)) + storedEnergy should approximate(zeroKWH) + qDot should approximate(zeroKW) case _ => fail("Thermal grid state updated failed") } From bb2f81027a092441a1e9d7a8ce2ea25e11bfeaad Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 12:58:05 +0100 Subject: [PATCH 26/27] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b683cd1327..4a3acbb5d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Rewrote StorageModelTest from groovy to scala [#646](https://github.com/ie3-institute/simona/issues/646) - Updated `ExtEvSimulationClasses` [#898](https://github.com/ie3-institute/simona/issues/898) - Refactoring of `ThermalGrid.energyGrid` to distinguish between demand of house and storage [#928](https://github.com/ie3-institute/simona/issues/928) +- Refactoring to use zeroKW and zeroKWH in thermal grid unit tests [#1023](https://github.com/ie3-institute/simona/issues/1023) ### Fixed - Fix rendering of references in documentation [#505](https://github.com/ie3-institute/simona/issues/505) From 86fcf1ee5976ff984bb7c6b0929f2369ead3f88c Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 15 Nov 2024 12:58:16 +0100 Subject: [PATCH 27/27] fmt --- .../ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c0d6226694..d50b1e558a 100644 --- a/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala +++ b/src/test/scala/edu/ie3/simona/model/thermal/ThermalGridWithHouseOnlySpec.scala @@ -109,7 +109,7 @@ class ThermalGridWithHouseOnlySpec extends UnitSpec with ThermalHouseTestData { "deliver the house state by just letting it cool down, if just no infeed is given" in { val tick = 0L val gridState = ThermalGrid.startingState(thermalGrid) - val externalQDot =zeroKW + val externalQDot = zeroKW val (updatedGridState, reachedThreshold) = thermalGrid invokePrivate handleConsumption(