From 8817af4b0fd5729e6c39de0c72df0ec9be659277 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Sun, 13 Nov 2022 19:49:11 +0100 Subject: [PATCH 1/4] Participant sends to EmAgent results first, then flex completion --- .../ParticipantAgentFundamentals.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) 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 b27101c0b0..0b3e96a814 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala @@ -780,6 +780,14 @@ protected trait ParticipantAgentFundamentals[ flexCtrl.tick ) + // announce current result to EmAgent before completion, + // since time could advance once all completions in + flexStateData.emAgent ! buildResultEvent( + stateDataWithResults, + flexCtrl.tick, + result + ) + flexStateData.emAgent ! FlexCtrlCompletion( baseStateData.modelUuid, revokeRequest, @@ -787,13 +795,6 @@ protected trait ParticipantAgentFundamentals[ flexChangeIndicator.changesAtTick ) - // announce current result to EmAgent - flexStateData.emAgent ! buildResultEvent( - stateDataWithResults, - flexCtrl.tick, - result - ) - if (currentTickDefined) { // if we've received ActivityStartTrigger, send completion goToIdleReplyCompletionAndScheduleTriggerForNextAction( From a5e1d0afcf69014070b60623ee9ce6defa71f8f7 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Sun, 13 Nov 2022 19:51:37 +0100 Subject: [PATCH 2/4] Adapt Storage model test to sending results first --- .../StorageAgentModelCalculationSpec.scala | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala index d68dab5a33..ab3862c2c8 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala @@ -420,6 +420,12 @@ class StorageAgentModelCalculationSpec IssuePowerCtrl(0L, storageInput.getType.getpMax()) ) + emAgent.expectMsgPF() { + case ParticipantResultEvent(result: StorageResult) => + result.getP should beEquivalentTo(storageInput.getType.getpMax()) + result.getQ should beEquivalentTo(0.asMegaVar) + } + // next potential activation at fully charged battery: // net power = 12.961kW * 0.92 = 11.92412kW // time to charge fully ~= 16.7727262054h = 60382 ticks (rounded) @@ -431,12 +437,6 @@ class StorageAgentModelCalculationSpec ) ) - emAgent.expectMsgPF() { - case ParticipantResultEvent(result: StorageResult) => - result.getP should beEquivalentTo(storageInput.getType.getpMax()) - result.getQ should beEquivalentTo(0.asMegaVar) - } - resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => result.getInputModel shouldBe storageInput.getUuid @@ -479,6 +479,12 @@ class StorageAgentModelCalculationSpec emAgent.send(storageAgent, IssuePowerCtrl(28800L, 9.asKiloWatt)) + emAgent.expectMsgPF() { + case ParticipantResultEvent(result: StorageResult) => + result.getP should beEquivalentTo(9d.asKiloWatt) + result.getQ should beEquivalentTo(0d.asMegaVar) + } + // after 8 hours, we're at about half full storage: 95.39296 kWh // net power = 9kW * 0.92 = 8.28kW // time to charge fully ~= 12.6337004831h = 45481 ticks (rounded) from now @@ -491,12 +497,6 @@ class StorageAgentModelCalculationSpec ) ) - emAgent.expectMsgPF() { - case ParticipantResultEvent(result: StorageResult) => - result.getP should beEquivalentTo(9d.asKiloWatt) - result.getQ should beEquivalentTo(0d.asMegaVar) - } - resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => result.getInputModel shouldBe storageInput.getUuid @@ -516,6 +516,14 @@ class StorageAgentModelCalculationSpec IssuePowerCtrl(36000L, storageInput.getType.getpMax().multiply(-1)) ) + emAgent.expectMsgPF() { + case ParticipantResultEvent(result: StorageResult) => + result.getP should beEquivalentTo( + storageInput.getType.getpMax().multiply(-1) + ) + result.getQ should beEquivalentTo(0d.asMegaVar) + } + // after 2 hours, we're at: 111.95296 kWh // net power = -12.961kW * 0.92 = -11.92412kW // time to discharge until lowest energy (40 kWh) ~= 6.03423648873h = 21723 ticks (rounded) from now @@ -528,14 +536,6 @@ class StorageAgentModelCalculationSpec ) ) - emAgent.expectMsgPF() { - case ParticipantResultEvent(result: StorageResult) => - result.getP should beEquivalentTo( - storageInput.getType.getpMax().multiply(-1) - ) - result.getQ should beEquivalentTo(0d.asMegaVar) - } - resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => result.getInputModel shouldBe storageInput.getUuid @@ -554,6 +554,12 @@ class StorageAgentModelCalculationSpec emAgent.send(storageAgent, IssuePowerCtrl(43200L, 12.asKiloWatt)) + emAgent.expectMsgPF() { + case ParticipantResultEvent(result: StorageResult) => + result.getP should beEquivalentTo(12d.asKiloWatt) + result.getQ should beEquivalentTo(0d.asMegaVar) + } + // after 2 hours, we're at: 88.10472 kWh // net power = 12 * 0.92 = 11.04 kW // time to charge until full ~= 10.135442029h = 36488 ticks (rounded) from now @@ -566,12 +572,6 @@ class StorageAgentModelCalculationSpec ) ) - emAgent.expectMsgPF() { - case ParticipantResultEvent(result: StorageResult) => - result.getP should beEquivalentTo(12d.asKiloWatt) - result.getQ should beEquivalentTo(0d.asMegaVar) - } - resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => result.getInputModel shouldBe storageInput.getUuid @@ -614,6 +614,12 @@ class StorageAgentModelCalculationSpec emAgent.send(storageAgent, IssuePowerCtrl(79688L, (-12).asKiloWatt)) + emAgent.expectMsgPF() { + case ParticipantResultEvent(result: StorageResult) => + result.getP should beEquivalentTo((-12d).asKiloWatt) + result.getQ should beEquivalentTo(0d.asMegaVar) + } + // we're full now at 200 kWh // net power = -12 * 0.92 = -11.04 kW // time to discharge until lowest energy ~= 14.4927536232h = 52174 ticks (rounded) from now @@ -626,12 +632,6 @@ class StorageAgentModelCalculationSpec ) ) - emAgent.expectMsgPF() { - case ParticipantResultEvent(result: StorageResult) => - result.getP should beEquivalentTo((-12d).asKiloWatt) - result.getQ should beEquivalentTo(0d.asMegaVar) - } - resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => result.getInputModel shouldBe storageInput.getUuid @@ -672,6 +672,12 @@ class StorageAgentModelCalculationSpec emAgent.send(storageAgent, IssuePowerCtrl(131862L, 0.asKiloWatt)) + emAgent.expectMsgPF() { + case ParticipantResultEvent(result: StorageResult) => + result.getP should beEquivalentTo(0d.asKiloWatt) + result.getQ should beEquivalentTo(0d.asMegaVar) + } + // we're not charging or discharging, no new expected tick emAgent.expectMsg( FlexCtrlCompletion( @@ -679,12 +685,6 @@ class StorageAgentModelCalculationSpec ) ) - emAgent.expectMsgPF() { - case ParticipantResultEvent(result: StorageResult) => - result.getP should beEquivalentTo(0d.asKiloWatt) - result.getQ should beEquivalentTo(0d.asMegaVar) - } - resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => result.getInputModel shouldBe storageInput.getUuid From 66be6076626991b862702a8a12e17b7c6c58ae93 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Sun, 13 Nov 2022 20:15:08 +0100 Subject: [PATCH 3/4] fmt --- .../model/participant/StorageModelTest.groovy | 389 +++++++++--------- 1 file changed, 197 insertions(+), 192 deletions(-) diff --git a/src/test/groovy/edu/ie3/simona/model/participant/StorageModelTest.groovy b/src/test/groovy/edu/ie3/simona/model/participant/StorageModelTest.groovy index 3e0dbfca15..524e94ad19 100644 --- a/src/test/groovy/edu/ie3/simona/model/participant/StorageModelTest.groovy +++ b/src/test/groovy/edu/ie3/simona/model/participant/StorageModelTest.groovy @@ -1,3 +1,9 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + package edu.ie3.simona.model.participant import edu.ie3.datamodel.models.OperationTime @@ -18,209 +24,208 @@ import static tech.units.indriya.quantity.Quantities.getQuantity class StorageModelTest extends Specification { - @Shared - StorageInput inputModel - @Shared - static final Double TOLERANCE = 1e-10 - - def setupSpec() { - def nodeInput = new NodeInput( - UUID.fromString("ad39d0b9-5ad6-4588-8d92-74c7d7de9ace"), - "NodeInput", - OperatorInput.NO_OPERATOR_ASSIGNED, - OperationTime.notLimited(), - getQuantity(1d, PU), - false, - NodeInput.DEFAULT_GEO_POSITION, - GermanVoltageLevelUtils.LV, - -1) - - def typeInput = new StorageTypeInput( - UUID.fromString("fbee4995-24dd-45e4-9c85-7d986fe99ff3"), - "Test_StorageTypeInput", - getQuantity(100d, EURO), - getQuantity(101d, EURO_PER_MEGAWATTHOUR), - getQuantity(100d, KILOWATTHOUR), - getQuantity(13d, KILOVOLTAMPERE), - 0.997, - getQuantity(10d, KILOWATT), - getQuantity(0.03, PU_PER_HOUR), - getQuantity(0.9, PU), - getQuantity(20d, PERCENT), - getQuantity(43800.0, HOUR), - 100000 - ) - - inputModel = new StorageInput( - UUID.randomUUID(), - "Test_StorageInput", - new OperatorInput(UUID.randomUUID(), "NO_OPERATOR"), - OperationTime.notLimited(), - nodeInput, - CosPhiFixed.CONSTANT_CHARACTERISTIC, - typeInput - ) - } - - def buildStorageModel() { - return StorageModel.apply(inputModel, 1, - TimeUtil.withDefaults.toZonedDateTime("2020-01-01 00:00:00"), - TimeUtil.withDefaults.toZonedDateTime("2020-01-01 01:00:00"), - 0) - } - - def "Calculate flex options"() { - given: - def storageModel = buildStorageModel() - def startTick = 3600L - def data = new StorageModel.StorageRelevantData(startTick + timeDelta) - def oldState = new StorageModel.StorageState( - getQuantity(lastStored, KILOWATTHOUR), - getQuantity(lastPower, KILOWATT), - startTick + @Shared + StorageInput inputModel + @Shared + static final Double TOLERANCE = 1e-10 + + def setupSpec() { + def nodeInput = new NodeInput( + UUID.fromString("ad39d0b9-5ad6-4588-8d92-74c7d7de9ace"), + "NodeInput", + OperatorInput.NO_OPERATOR_ASSIGNED, + OperationTime.notLimited(), + getQuantity(1d, PU), + false, + NodeInput.DEFAULT_GEO_POSITION, + GermanVoltageLevelUtils.LV, + -1) + + def typeInput = new StorageTypeInput( + UUID.fromString("fbee4995-24dd-45e4-9c85-7d986fe99ff3"), + "Test_StorageTypeInput", + getQuantity(100d, EURO), + getQuantity(101d, EURO_PER_MEGAWATTHOUR), + getQuantity(100d, KILOWATTHOUR), + getQuantity(13d, KILOVOLTAMPERE), + 0.997, + getQuantity(10d, KILOWATT), + getQuantity(0.03, PU_PER_HOUR), + getQuantity(0.9, PU), + getQuantity(20d, PERCENT), + getQuantity(43800.0, HOUR), + 100000 ) - when: - def result = (FlexibilityMessage.ProvideMinMaxFlexOptions) storageModel.determineFlexOptions(data, oldState) - - then: - equals(result.referencePower(), getQuantity(pRef, KILOWATT), TOLERANCE) - equals(result.minPower(), getQuantity(pMin, KILOWATT), TOLERANCE) - equals(result.maxPower(), getQuantity(pMax, KILOWATT), TOLERANCE) - - where: - lastStored | lastPower | timeDelta || pRef | pMin | pMax - // UNCHANGED STATE - // completely empty - 0 | 0 | 1 || 0 | 0 | 10 - // at lowest allowed charge - 20 | 0 | 1 || 0 | 0 | 10 - // at a tiny bit above lowest allowed charge - 20.011 | 0 | 1 || 0 | -10 | 10 - // at mid-level charge - 60 | 0 | 1 || 0 | -10 | 10 - // almost fully charged - 99.989 | 0 | 1 || 0 | -10 | 10 - // fully charged - 100 | 0 | 1 || 0 | -10 | 0 - // CHANGED STATE - // discharged to lowest allowed charge - 30 | -10 | 3600 || 0 | 0 | 10 - // almost discharged to lowest allowed charge - 30 | -10 | 3590 || 0 | -10 | 10 - // charged to mid-level charge - 50 | 10 | 3600 || 0 | -10 | 10 - // discharged to mid-level charge - 70 | -10 | 3600 || 0 | -10 | 10 - // almost fully charged - 95 | 4.98 | 3600 || 0 | -10 | 10 - // fully charged - 95 | 5 | 3600 || 0 | -10 | 0 - } - - def "Handle controlled power change"() { - given: - def storageModel = buildStorageModel() - def startTick = 3600L - def data = new StorageModel.StorageRelevantData(startTick + 1) - def oldState = new StorageModel.StorageState( - getQuantity(lastStored, KILOWATTHOUR), - getQuantity(0d, KILOWATT), - startTick + inputModel = new StorageInput( + UUID.randomUUID(), + "Test_StorageInput", + new OperatorInput(UUID.randomUUID(), "NO_OPERATOR"), + OperationTime.notLimited(), + nodeInput, + CosPhiFixed.CONSTANT_CHARACTERISTIC, + typeInput ) - - when: - def result = storageModel.handleControlledPowerChange( - data, - oldState, - getQuantity(setPower, KILOWATT) + } + + def buildStorageModel() { + return StorageModel.apply(inputModel, 1, + TimeUtil.withDefaults.toZonedDateTime("2020-01-01 00:00:00"), + TimeUtil.withDefaults.toZonedDateTime("2020-01-01 01:00:00"), + 0) + } + + def "Calculate flex options"() { + given: + def storageModel = buildStorageModel() + def startTick = 3600L + def data = new StorageModel.StorageRelevantData(startTick + timeDelta) + def oldState = new StorageModel.StorageState( + getQuantity(lastStored, KILOWATTHOUR), + getQuantity(lastPower, KILOWATT), + startTick ) - then: - equals(result._1.chargingPower(), getQuantity(expPower, KILOWATT), TOLERANCE) - result._1.tick() == startTick + 1 - equals(result._1.storedEnergy(), getQuantity(lastStored, KILOWATTHOUR), TOLERANCE) - def flexChangeIndication = result._2 - flexChangeIndication.changesAtTick().defined == expScheduled - flexChangeIndication.changesAtTick().map(x -> x == startTick + 1 + expDelta).getOrElse( _ -> true) - flexChangeIndication.changesAtNextActivation() == expActiveNext - - where: - lastStored | setPower || expPower | expActiveNext | expScheduled | expDelta - // no power - 0 | 0 || 0 | false | false | 0 - 50 | 0 || 0 | false | false | 0 - 100 | 0 || 0 | false | false | 0 - // charging on empty - 0 | 1 || 0.9 | true | true | 100*3600/0.9 - 0 | 2.5 || 2.25 | true | true | 40*3600/0.9 - 0 | 5 || 4.5 | true | true | 20*3600/0.9 - 0 | 10 || 9 | true | true | 10*3600/0.9 - // charging on half full - 50 | 5 || 4.5 | false | true | 10*3600/0.9 - 50 | 10 || 9 | false | true | 5*3600/0.9 - // discharging on half full - 50 | -5 || -4.5 | false | true | 6*3600/0.9 - 50 | -10 || -9 | false | true | 3*3600/0.9 - // discharging on full - 100 | -5 || -4.5 | true | true | 16*3600/0.9 - 100 | -10 || -9 | true | true | 8*3600/0.9 - } - - def "Handle the edge case of charging in tolerance margins"() { - given: - def storageModel = buildStorageModel() - def startTick = 1800L - def data = new StorageModel.StorageRelevantData(startTick + 1) - // margin is at ~ 20.0030864 kWh - def oldState = new StorageModel.StorageState( - getQuantity(20.001d, KILOWATTHOUR), - getQuantity(0d, KILOWATT), - startTick + when: + def result = (FlexibilityMessage.ProvideMinMaxFlexOptions) storageModel.determineFlexOptions(data, oldState) + + then: + equals(result.referencePower(), getQuantity(pRef, KILOWATT), TOLERANCE) + equals(result.minPower(), getQuantity(pMin, KILOWATT), TOLERANCE) + equals(result.maxPower(), getQuantity(pMax, KILOWATT), TOLERANCE) + + where: + lastStored | lastPower | timeDelta || pRef | pMin | pMax + // UNCHANGED STATE + // completely empty + 0 | 0 | 1 || 0 | 0 | 10 + // at lowest allowed charge + 20 | 0 | 1 || 0 | 0 | 10 + // at a tiny bit above lowest allowed charge + 20.011 | 0 | 1 || 0 | -10 | 10 + // at mid-level charge + 60 | 0 | 1 || 0 | -10 | 10 + // almost fully charged + 99.989 | 0 | 1 || 0 | -10 | 10 + // fully charged + 100 | 0 | 1 || 0 | -10 | 0 + // CHANGED STATE + // discharged to lowest allowed charge + 30 | -10 | 3600 || 0 | 0 | 10 + // almost discharged to lowest allowed charge + 30 | -10 | 3590 || 0 | -10 | 10 + // charged to mid-level charge + 50 | 10 | 3600 || 0 | -10 | 10 + // discharged to mid-level charge + 70 | -10 | 3600 || 0 | -10 | 10 + // almost fully charged + 95 | 4.98 | 3600 || 0 | -10 | 10 + // fully charged + 95 | 5 | 3600 || 0 | -10 | 0 + } + + def "Handle controlled power change"() { + given: + def storageModel = buildStorageModel() + def startTick = 3600L + def data = new StorageModel.StorageRelevantData(startTick + 1) + def oldState = new StorageModel.StorageState( + getQuantity(lastStored, KILOWATTHOUR), + getQuantity(0d, KILOWATT), + startTick + ) + + when: + def result = storageModel.handleControlledPowerChange( + data, + oldState, + getQuantity(setPower, KILOWATT) + ) + + then: + equals(result._1.chargingPower(), getQuantity(expPower, KILOWATT), TOLERANCE) + result._1.tick() == startTick + 1 + equals(result._1.storedEnergy(), getQuantity(lastStored, KILOWATTHOUR), TOLERANCE) + def flexChangeIndication = result._2 + flexChangeIndication.changesAtTick().defined == expScheduled + flexChangeIndication.changesAtTick().map(x -> x == startTick + 1 + expDelta).getOrElse( _ -> true) + flexChangeIndication.changesAtNextActivation() == expActiveNext + + where: + lastStored | setPower || expPower | expActiveNext | expScheduled | expDelta + // no power + 0 | 0 || 0 | false | false | 0 + 50 | 0 || 0 | false | false | 0 + 100 | 0 || 0 | false | false | 0 + // charging on empty + 0 | 1 || 0.9 | true | true | 100*3600/0.9 + 0 | 2.5 || 2.25 | true | true | 40*3600/0.9 + 0 | 5 || 4.5 | true | true | 20*3600/0.9 + 0 | 10 || 9 | true | true | 10*3600/0.9 + // charging on half full + 50 | 5 || 4.5 | false | true | 10*3600/0.9 + 50 | 10 || 9 | false | true | 5*3600/0.9 + // discharging on half full + 50 | -5 || -4.5 | false | true | 6*3600/0.9 + 50 | -10 || -9 | false | true | 3*3600/0.9 + // discharging on full + 100 | -5 || -4.5 | true | true | 16*3600/0.9 + 100 | -10 || -9 | true | true | 8*3600/0.9 + } + + def "Handle the edge case of charging in tolerance margins"() { + given: + def storageModel = buildStorageModel() + def startTick = 1800L + def data = new StorageModel.StorageRelevantData(startTick + 1) + // margin is at ~ 20.0030864 kWh + def oldState = new StorageModel.StorageState( + getQuantity(20.001d, KILOWATTHOUR), + getQuantity(0d, KILOWATT), + startTick ) - when: - def result = storageModel.handleControlledPowerChange( - data, - oldState, - getQuantity(-5d, KILOWATT) + when: + def result = storageModel.handleControlledPowerChange( + data, + oldState, + getQuantity(-5d, KILOWATT) ) - then: - equals(result._1.chargingPower(), getQuantity(0d, KILOWATT), TOLERANCE) - result._1.tick() == startTick + 1 - equals(result._1.storedEnergy(), oldState.storedEnergy(), TOLERANCE) - def flexChangeIndication = result._2 - !flexChangeIndication.changesAtTick().defined - flexChangeIndication.changesAtNextActivation() - } - - def "Handle the edge case of discharging in tolerance margins"() { - given: - def storageModel = buildStorageModel() - def startTick = 1800L - def data = new StorageModel.StorageRelevantData(startTick + 1) - // margin is at ~ 99.9975 kWh - def oldState = new StorageModel.StorageState( - getQuantity(99.9990, KILOWATTHOUR), - getQuantity(0d, KILOWATT), - startTick + then: + equals(result._1.chargingPower(), getQuantity(0d, KILOWATT), TOLERANCE) + result._1.tick() == startTick + 1 + equals(result._1.storedEnergy(), oldState.storedEnergy(), TOLERANCE) + def flexChangeIndication = result._2 + !flexChangeIndication.changesAtTick().defined + flexChangeIndication.changesAtNextActivation() + } + + def "Handle the edge case of discharging in tolerance margins"() { + given: + def storageModel = buildStorageModel() + def startTick = 1800L + def data = new StorageModel.StorageRelevantData(startTick + 1) + // margin is at ~ 99.9975 kWh + def oldState = new StorageModel.StorageState( + getQuantity(99.9990, KILOWATTHOUR), + getQuantity(0d, KILOWATT), + startTick ) - when: - def result = storageModel.handleControlledPowerChange( - data, - oldState, - getQuantity(9d, KILOWATT) + when: + def result = storageModel.handleControlledPowerChange( + data, + oldState, + getQuantity(9d, KILOWATT) ) - then: - equals(result._1.chargingPower(), getQuantity(0d, KILOWATT), TOLERANCE) - result._1.tick() == startTick + 1 - equals(result._1.storedEnergy(), oldState.storedEnergy(), TOLERANCE) - def flexChangeIndication = result._2 - !flexChangeIndication.changesAtTick().defined - flexChangeIndication.changesAtNextActivation() - } - + then: + equals(result._1.chargingPower(), getQuantity(0d, KILOWATT), TOLERANCE) + result._1.tick() == startTick + 1 + equals(result._1.storedEnergy(), oldState.storedEnergy(), TOLERANCE) + def flexChangeIndication = result._2 + !flexChangeIndication.changesAtTick().defined + flexChangeIndication.changesAtNextActivation() + } } \ No newline at end of file From 35c35c44cdd24a86c5be57d91f0a1866e1013130 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Sun, 13 Nov 2022 19:53:12 +0100 Subject: [PATCH 4/4] Adapt EVCS model test to sending results first --- .../EvcsAgentModelCalculationSpec.scala | 188 +++++++++--------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala index fbc7db36c7..a2ea20b8c0 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala @@ -1449,15 +1449,6 @@ class EvcsAgentModelCalculationSpec IssueNoCtrl(0L) ) - // next potential activation at fully charged battery: - // net power = 12.961kW * 0.92 = 11.92412kW - // time to charge fully ~= 16.7727262054h = 60382 ticks (rounded) - emAgent.expectMsg( - FlexCtrlCompletion( - modelUuid = evcsInputModel.getUuid - ) - ) - emAgent.expectMsgType[ParticipantResultEvent] match { case result => result.systemParticipantResult.getP should equalWithTolerance( @@ -1470,6 +1461,15 @@ class EvcsAgentModelCalculationSpec ) } + // next potential activation at fully charged battery: + // net power = 12.961kW * 0.92 = 11.92412kW + // time to charge fully ~= 16.7727262054h = 60382 ticks (rounded) + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModel.getUuid + ) + ) + // results arrive after next activation resultListener.expectNoMessage() @@ -1520,15 +1520,6 @@ class EvcsAgentModelCalculationSpec emAgent.send(evcsAgent, IssueNoCtrl(900L)) - // at 4500 ev is departing - emAgent.expectMsg( - FlexCtrlCompletion( - modelUuid = evcsInputModel.getUuid, - requestAtNextActivation = true, - requestAtTick = Some(4500L) - ) - ) - emAgent.expectMsgType[ParticipantResultEvent] match { case result => result.systemParticipantResult.getP should equalWithTolerance( @@ -1541,6 +1532,15 @@ class EvcsAgentModelCalculationSpec ) } + // at 4500 ev is departing + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModel.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(4500L) + ) + ) + emAgent.expectMsg(CompletionMessage(activation1, None)) // result of tick 0 @@ -1649,17 +1649,6 @@ class EvcsAgentModelCalculationSpec emAgent.send(evcsAgent, IssueNoCtrl(4500L)) - // we currently have an empty battery in ev4500 - // time to charge to minimal soc ~= 1.45454545455h = 5236 ticks (rounded) from now - // current tick is 4500, thus: 4500 + 5236 = 9736 - emAgent.expectMsg( - FlexCtrlCompletion( - modelUuid = evcsInputModel.getUuid, - requestAtNextActivation = true, - requestAtTick = Some(9736L) - ) - ) - emAgent.expectMsgType[ParticipantResultEvent] match { case result => result.systemParticipantResult.getP should equalWithTolerance( @@ -1672,6 +1661,17 @@ class EvcsAgentModelCalculationSpec ) } + // we currently have an empty battery in ev4500 + // time to charge to minimal soc ~= 1.45454545455h = 5236 ticks (rounded) from now + // current tick is 4500, thus: 4500 + 5236 = 9736 + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModel.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(9736L) + ) + ) + emAgent.expectMsg(CompletionMessage(activation2, None)) // already sent out after EV departed @@ -1710,18 +1710,6 @@ class EvcsAgentModelCalculationSpec evService.expectNoMessage() - // ev4500 is now at 16 kWh - // time to charge fully = 6.4 h = 23040 ticks from now - // current tick is 9736, thus: 9736 + 23040 = 32776 - emAgent.expectMsg( - FlexCtrlCompletion( - modelUuid = evcsInputModel.getUuid, - requestAtTick = Some(32776L), - requestAtNextActivation = - true // since battery is still below lowest soc, it's still considered empty - ) - ) - emAgent.expectMsgType[ParticipantResultEvent] match { case result => result.systemParticipantResult.getP should equalWithTolerance( @@ -1734,6 +1722,18 @@ class EvcsAgentModelCalculationSpec ) } + // ev4500 is now at 16 kWh + // time to charge fully = 6.4 h = 23040 ticks from now + // current tick is 9736, thus: 9736 + 23040 = 32776 + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModel.getUuid, + requestAtTick = Some(32776L), + requestAtNextActivation = + true // since battery is still below lowest soc, it's still considered empty + ) + ) + resultListener.expectMsgPF() { case ParticipantResultEvent(result: EvResult) => result.getInputModel shouldBe ev4500.getUuid @@ -1814,6 +1814,18 @@ class EvcsAgentModelCalculationSpec // no departing evs here evService.expectNoMessage() + emAgent.expectMsgType[ParticipantResultEvent] match { + case result => + result.systemParticipantResult.getP should equalWithTolerance( + 16.asKiloWatt, + testingTolerance + ) + result.systemParticipantResult.getQ should equalWithTolerance( + 0.asMegaVar, + testingTolerance + ) + } + // ev4500 is now at ~ 21.45555556 kWh, ev11700 just arrived with 11.6 kWh // ev4500: time to charge fully ~= 7.3180556 h = 26345 ticks from now // ev11700: time to charge fully = 5.8 h = 20880 ticks from now @@ -1828,18 +1840,6 @@ class EvcsAgentModelCalculationSpec ) ) - emAgent.expectMsgType[ParticipantResultEvent] match { - case result => - result.systemParticipantResult.getP should equalWithTolerance( - 16.asKiloWatt, - testingTolerance - ) - result.systemParticipantResult.getQ should equalWithTolerance( - 0.asMegaVar, - testingTolerance - ) - } - emAgent.expectMsg(CompletionMessage(activation3, None)) resultListener.expectMsgPF() { @@ -1899,18 +1899,6 @@ class EvcsAgentModelCalculationSpec // no departing evs here evService.expectNoMessage() - // ev4500 is now at ~ 35.455556 kWh, ev11700 at 25.6 kWh - // ev4500: time to discharge to lowest soc ~= 1.9455556 h = 7004 ticks from now - // ev11700: time to discharge to lowest soc ~= 1.4 h = 5040 ticks from now - // current tick is 18000, thus: 18000 + 5040 = 23040 - emAgent.expectMsg( - FlexCtrlCompletion( - modelUuid = evcsInputModel.getUuid, - requestAtTick = Some(23040L), - revokeRequestAtTick = Some(32580L) - ) - ) - emAgent.expectMsgType[ParticipantResultEvent] match { case result => result.systemParticipantResult.getP should equalWithTolerance( @@ -1923,6 +1911,18 @@ class EvcsAgentModelCalculationSpec ) } + // ev4500 is now at ~ 35.455556 kWh, ev11700 at 25.6 kWh + // ev4500: time to discharge to lowest soc ~= 1.9455556 h = 7004 ticks from now + // ev11700: time to discharge to lowest soc ~= 1.4 h = 5040 ticks from now + // current tick is 18000, thus: 18000 + 5040 = 23040 + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModel.getUuid, + requestAtTick = Some(23040L), + revokeRequestAtTick = Some(32580L) + ) + ) + Range(0, 2) .map { _ => resultListener.expectMsgType[ParticipantResultEvent] @@ -1989,16 +1989,6 @@ class EvcsAgentModelCalculationSpec // no departing evs here evService.expectNoMessage() - // ev4500 is now at 21.455556 kWh, ev11700 at 11.6 kWh (lowest soc) - // ev4500: time to discharge to lowest soc = 0.5455556 h = 1964 ticks from now - // current tick is 18864, thus: 23040 + 1964 = 25004 - emAgent.expectMsg( - FlexCtrlCompletion( - modelUuid = evcsInputModel.getUuid, - requestAtTick = Some(25004L) - ) - ) - emAgent.expectMsgType[ParticipantResultEvent] match { case result => result.systemParticipantResult.getP should equalWithTolerance( @@ -2011,6 +2001,16 @@ class EvcsAgentModelCalculationSpec ) } + // ev4500 is now at 21.455556 kWh, ev11700 at 11.6 kWh (lowest soc) + // ev4500: time to discharge to lowest soc = 0.5455556 h = 1964 ticks from now + // current tick is 18864, thus: 23040 + 1964 = 25004 + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModel.getUuid, + requestAtTick = Some(25004L) + ) + ) + Range(0, 2) .map { _ => resultListener.expectMsgType[ParticipantResultEvent] @@ -2071,13 +2071,6 @@ class EvcsAgentModelCalculationSpec // no departing evs here evService.expectNoMessage() - // no new activation - emAgent.expectMsg( - FlexCtrlCompletion( - modelUuid = evcsInputModel.getUuid - ) - ) - emAgent.expectMsgType[ParticipantResultEvent] match { case result => result.systemParticipantResult.getP should equalWithTolerance( @@ -2090,6 +2083,13 @@ class EvcsAgentModelCalculationSpec ) } + // no new activation + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModel.getUuid + ) + ) + Range(0, 2) .map { _ => resultListener.expectMsgType[ParticipantResultEvent] @@ -2193,6 +2193,18 @@ class EvcsAgentModelCalculationSpec emAgent.send(evcsAgent, IssuePowerCtrl(36000L, 4.asKiloWatt)) + emAgent.expectMsgType[ParticipantResultEvent] match { + case result => + result.systemParticipantResult.getP should equalWithTolerance( + 4.asKiloWatt, + testingTolerance + ) + result.systemParticipantResult.getQ should equalWithTolerance( + 0.asMegaVar, + testingTolerance + ) + } + // ev11700 is now at 16 kWh // ev11700: time to charge fully = 16 h = 57600 ticks from now // current tick is 36000, thus: 36000 + 57600 = 93600 @@ -2206,18 +2218,6 @@ class EvcsAgentModelCalculationSpec ) ) - emAgent.expectMsgType[ParticipantResultEvent] match { - case result => - result.systemParticipantResult.getP should equalWithTolerance( - 4.asKiloWatt, - testingTolerance - ) - result.systemParticipantResult.getQ should equalWithTolerance( - 0.asMegaVar, - testingTolerance - ) - } - } }