From 6619acf918396280c53ba52bdd31bf33a36b5d39 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 10 Feb 2022 13:04:34 +0100 Subject: [PATCH 1/6] fix sanity check --- .../ie3/simona/model/participant/PVModel.scala | 15 ++++++++------- .../ie3/simona/model/participant/WecModel.scala | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala b/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala index 235f8a3981..fbb7d00bf3 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala @@ -740,7 +740,7 @@ final case class PVModel private ( .multiply(genCorr * tempCorr) /* Calculate the foreseen active power output without boundary condition adaptions */ - val proposal = sRated + val activePower = sRated .multiply(-1) .multiply( `yield` @@ -753,18 +753,19 @@ final case class PVModel private ( .to(MEGAWATT) // MW. /* Do sanity check, if the proposed feed in is above the estimated maximum to be apparent active power of the plant */ - if (proposal.isLessThan(pMax)) + if (activePower.isGreaterThan(pMax)) logger.warn( - "The fed in active power is higher than the estimated maximum active power of this plant ({} < {}). " + + "The fed in active power of plant {} is higher than its estimated maximum active power ({} > {}). " + "Did you provide wrong weather input data?", - proposal, + uuid, + activePower, pMax ) - /* If the output is marginally small, suppress the output, as we are likely to be in night and then only produce incorrect output */ - if (proposal.compareTo(activationThreshold) > 0) + /* If the output is marginally small, suppress the output, as it's likely nighttime where there shouldn't be any output */ + if (activePower.compareTo(activationThreshold) > 0) Quantities.getQuantity(0d, MEGAWATT) - else proposal + else activePower } } diff --git a/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala b/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala index 66868b7dcb..83a6e00a2e 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala @@ -114,8 +114,9 @@ final case class WecModel( (if (activePower.isGreaterThan(pMax)) { logger.warn( - "The fed in active power is higher than the estimated maximum active power of this plant ({} > {}). " + + "The fed in active power of plant {} is higher than its estimated maximum active power ({} > {}). " + "Did you provide wrong weather input data?", + uuid, activePower, pMax ) From d8b8802a32e13a354672153313f91cc4575402ef Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 10 Feb 2022 13:06:21 +0100 Subject: [PATCH 2/6] beautify comment --- src/main/scala/edu/ie3/simona/model/participant/PVModel.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala b/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala index fbb7d00bf3..c5d726cf71 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala @@ -752,7 +752,7 @@ final case class PVModel private ( .asType(classOf[Power]) .to(MEGAWATT) // MW. - /* Do sanity check, if the proposed feed in is above the estimated maximum to be apparent active power of the plant */ + /* Do sanity check, if the proposed feed in is above the estimated maximum active power of the plant */ if (activePower.isGreaterThan(pMax)) logger.warn( "The fed in active power of plant {} is higher than its estimated maximum active power ({} > {}). " + From 5ac3333f39a0547b68fe47232f0f17f214d459c8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 10 Feb 2022 16:33:58 +0100 Subject: [PATCH 3/6] add limit active power function --- .../simona/model/participant/PVModel.scala | 17 +++---------- .../model/participant/SystemParticipant.scala | 25 +++++++++++++++++++ .../simona/model/participant/WecModel.scala | 13 +--------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala b/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala index c5d726cf71..99feb17cf2 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/PVModel.scala @@ -741,7 +741,6 @@ final case class PVModel private ( /* Calculate the foreseen active power output without boundary condition adaptions */ val activePower = sRated - .multiply(-1) .multiply( `yield` .divide(irraditionSTC) @@ -752,20 +751,12 @@ final case class PVModel private ( .asType(classOf[Power]) .to(MEGAWATT) // MW. - /* Do sanity check, if the proposed feed in is above the estimated maximum active power of the plant */ - if (activePower.isGreaterThan(pMax)) - logger.warn( - "The fed in active power of plant {} is higher than its estimated maximum active power ({} > {}). " + - "Did you provide wrong weather input data?", - uuid, - activePower, - pMax - ) - /* If the output is marginally small, suppress the output, as it's likely nighttime where there shouldn't be any output */ if (activePower.compareTo(activationThreshold) > 0) - Quantities.getQuantity(0d, MEGAWATT) - else activePower + return Quantities.getQuantity(0d, MEGAWATT) + + /* Do sanity check, if the proposed feed in is above the estimated maximum active power of the plant */ + limitActivePower(activePower, pMax).multiply(-1) } } diff --git a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala index 3331b2280d..e230b7a143 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala @@ -188,5 +188,30 @@ abstract class SystemParticipant[CD <: CalcRelevantData]( } } + /** Limits active power with respect to the maximum permissible power defined + * for the system participant. + * + * @param p + * the calculated active power + * @param pMax + * the maximum permissible power + * @return + */ + protected def limitActivePower( + p: ComparableQuantity[Power], + pMax: ComparableQuantity[Power] + ): ComparableQuantity[Power] = { + if (p.isGreaterThan(pMax)) { + logger.warn( + "The fed in active power of plant {} is higher than its estimated maximum active power ({} > {}).", + uuid, + p, + pMax + ) + pMax + } else + p + } + def getUuid: UUID = this.uuid } diff --git a/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala b/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala index 83a6e00a2e..7f912582a4 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/WecModel.scala @@ -112,18 +112,7 @@ final case class WecModel( val activePower = determinePower(wecData).to(MEGAWATT) val pMax = sMax.multiply(cosPhiRated).to(MEGAWATT) - (if (activePower.isGreaterThan(pMax)) { - logger.warn( - "The fed in active power of plant {} is higher than its estimated maximum active power ({} > {}). " + - "Did you provide wrong weather input data?", - uuid, - activePower, - pMax - ) - pMax - } else { - activePower - }).multiply(-1) + limitActivePower(activePower, pMax).multiply(-1) } /** Determine the turbine output power with the air density ρ, the wind From af47552e7e4e00dd4d731a7407cedc472d8ae496 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 10 Feb 2022 16:42:47 +0100 Subject: [PATCH 4/6] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 178aa25fc0..d488ed71e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Changed +- Harmonized active power output of `WecInput` and `PvInput` [#135](https://github.com/ie3-institute/simona/issues/135) - Improving code readability in EvcsAgent by moving FreeLotsRequest to separate methods ### Fixed From 1dd36e6b250b9c4ce780a81933738a5220028f8e Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 10 Feb 2022 16:45:04 +0100 Subject: [PATCH 5/6] refine logging statement --- .../edu/ie3/simona/model/participant/SystemParticipant.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala index e230b7a143..03a5817278 100644 --- a/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala +++ b/src/main/scala/edu/ie3/simona/model/participant/SystemParticipant.scala @@ -203,7 +203,7 @@ abstract class SystemParticipant[CD <: CalcRelevantData]( ): ComparableQuantity[Power] = { if (p.isGreaterThan(pMax)) { logger.warn( - "The fed in active power of plant {} is higher than its estimated maximum active power ({} > {}).", + "The calculated active power of plant {} is higher than its estimated maximum active power ({} > {}). Will be limited to the maximum permissible output.", uuid, p, pMax From 18a221d0b637ae267a66b552c3e45f23c513ba9c Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 10 Feb 2022 17:14:26 +0100 Subject: [PATCH 6/6] add test --- .../participant/SystemParticipantTest.groovy | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/test/groovy/edu/ie3/simona/model/participant/SystemParticipantTest.groovy b/src/test/groovy/edu/ie3/simona/model/participant/SystemParticipantTest.groovy index 1c643cb4cc..bb5f181bad 100644 --- a/src/test/groovy/edu/ie3/simona/model/participant/SystemParticipantTest.groovy +++ b/src/test/groovy/edu/ie3/simona/model/participant/SystemParticipantTest.groovy @@ -287,4 +287,37 @@ class SystemParticipantTest extends Specification { 1.07 || 44.440972086578 1.1 || 44.440972086578 } + + def "Limits active power to the maximum permissible power specified"() { + given: "a calculated power value and the maximum permissible power" + + Quantity pQuant = Quantities.getQuantity(p, KILOWATT) + Quantity pMaxQuant = Quantities.getQuantity(pMax, KILOWATT) + + def loadMock = new SystemParticipant( + UUID.fromString("d8461624-d142-4360-8e02-c21965ec555e"), + "System participant calculateQ Test", + OperationInterval.apply(0L, 86400L), + 1d, + QControl.apply(new QV("qV:{(0.93,-1),(0.97,0),(1,0),(1.03,0),(1.07,1)}")), + Quantities.getQuantity(200, KILOWATT), + 1d) { + @Override + ComparableQuantity calculateActivePower(CalcRelevantData data) { + return Quantities.getQuantity(0, MEGAWATT) + } + } + + when: + Quantity limited = loadMock.limitActivePower(pQuant, pMaxQuant) + + then: + if (p <= pMax) limited.isEquivalentTo(pQuant) else limited.isEquivalentTo(pMaxQuant) + + where: + p || pMax + 10 || 100 + 100 || 10 + 10 || 10 + } }