Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
542f33a
Adding transformer tap changing to congestion mitigation.
staudtMarius May 14, 2025
a361813
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius May 14, 2025
2965058
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Jun 11, 2025
7637501
Adapting to recent changes in `dev`.
staudtMarius Jun 11, 2025
319815f
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Jun 11, 2025
1796e47
Adapting to recent changes in `dev`.
staudtMarius Jun 11, 2025
9c28252
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Jun 13, 2025
ff727e9
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Jun 30, 2025
e2dce33
Adapting to changes in `dev`.
staudtMarius Jun 30, 2025
dccf02d
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Jul 1, 2025
a2bb566
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Jul 9, 2025
903424d
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Jul 23, 2025
805c516
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Sep 3, 2025
926490f
fmt
staudtMarius Sep 3, 2025
f6d644b
Fixing some issues.
staudtMarius Sep 3, 2025
076b369
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Sep 22, 2025
6321530
Merge branch 'dev' into ms/#1378-enhance-congestion-management-with-t…
staudtMarius Oct 30, 2025
7d8fa37
Fixing issues after merging dev.
staudtMarius Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated docker documentation [#488](https://github.com/ie3-institute/simona/issues/488)
- Added support classes for transformer tap position calculation [#1543](https://github.com/ie3-institute/simona/issues/1543)
- Added basic external em service [#1566](https://github.com/ie3-institute/simona/issues/1566)
- Adding transformer tap changing to congestion mitigation [#1378](https://github.com/ie3-institute/simona/issues/1378)

### Changed
- Upgraded `scala2` to `scala3` [#53](https://github.com/ie3-institute/simona/issues/53)
Expand Down
4 changes: 4 additions & 0 deletions src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ trait DBFSAlgorithm extends PowerFlowSupport with GridResultsSupport {
)
buffer.stash(requestGridPower)
Behaviors.same

case (msg, _) =>
ctx.log.warn("Msg '{}' received", msg)
Behaviors.same
}
}

Expand Down
1 change: 1 addition & 0 deletions src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ object GridAgent extends DBFSAlgorithm with DCMAlgorithm {
pfParams,
CongestionManagementParams(
cfg.congestionManagement.enableDetection,
cfg.congestionManagement.enableTransformerTapChange,
cfg.congestionManagement.timeout,
),
SimonaActorNaming.actorName(ctx.self),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
package edu.ie3.simona.agent.grid.congestion

import edu.ie3.simona.agent.grid.GridAgent
import edu.ie3.simona.agent.grid.congestion.mitigations.MitigationSteps

/** Messages for the congestion management.
*/
object CongestionManagementMessages {

final case class NextStep(step: MitigationSteps.Value)
extends GridAgent.InternalRequest

/** Message that informs all actors that the current step is started.
*/
case object StartStep extends GridAgent.InternalRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,61 @@

package edu.ie3.simona.agent.grid.congestion

import edu.ie3.simona.agent.grid.congestion.CongestionManagementParams.MitigationProgress
import edu.ie3.simona.agent.grid.congestion.mitigations.MitigationSteps
import edu.ie3.simona.agent.grid.congestion.mitigations.MitigationSteps.*

import scala.concurrent.duration.FiniteDuration

/** Holds all congestion management configuration parameters used in
* [[edu.ie3.simona.agent.grid]]. If the parameter [[detectionEnabled]] is set
* to false, no congestion management is run and all the other parameters are
* ignored
* ignored.
*
* @param detectionEnabled
* defines if the congestion management is active and can be run
* Defines if the congestion management is active and can be run.
* @param enableTransformerTapChange
* Defines if changing the transformer tapping can be used for congestion
* management.
* @param timeout
* used for asking other actors
* Used for asking other actors.
*/
final case class CongestionManagementParams(
detectionEnabled: Boolean,
enableTransformerTapChange: Boolean,
timeout: FiniteDuration,
)
progress: MitigationProgress = MitigationProgress(),
) {

def anyMitigationEnabled: Boolean = enableTransformerTapChange

}

object CongestionManagementParams {

case class MitigationProgress(
hasUsedTransformerTapChange: Boolean = false,
currentIteration: Int = 0,
maxNrOfOptimizationIterations: Int = 1,
) {

def getNextStepsAndUpdate: (MitigationSteps.Value, MitigationProgress) = {

if hasUsedTransformerTapChange then {
// we reset the progress and return no next step
(NoMeasure, reset)
} else {
(
TransformerTapChange,
copy(hasUsedTransformerTapChange = true),
)
}
}

def reset: MitigationProgress = copy(
hasUsedTransformerTapChange = false,
currentIteration = 0,
)

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ import edu.ie3.simona.agent.grid.congestion.data.{
CongestionManagementData,
}
import edu.ie3.simona.agent.grid.congestion.detection.CongestionDetection
import edu.ie3.simona.agent.grid.congestion.mitigations.TransformerTapChange
import edu.ie3.simona.agent.participant.ParticipantAgent.GridSimulationFinished
import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent
import edu.ie3.simona.ontology.messages.Activation
import org.apache.pekko.actor.typed.Behavior
import org.apache.pekko.actor.typed.scaladsl.{ActorContext, StashBuffer}

/** Trait that is normally mixed into every [[GridAgent]] to enable distributed
* congestion management (DCM) algorithm execution. It is considered to be the
* standard behaviour of a [[GridAgent]].
*/
trait DCMAlgorithm extends CongestionDetection {
trait DCMAlgorithm extends CongestionDetection with TransformerTapChange {

/** Method for starting the congestion management.
*
Expand Down Expand Up @@ -69,6 +72,39 @@ trait DCMAlgorithm extends CongestionDetection {
)
}

private[grid] def doPowerFlow(
stateData: CongestionManagementData,
ctx: ActorContext[Message],
)(using
constantData: GridAgentConstantData,
buffer: StashBuffer[Message],
): Behavior[Message] = {
val gridAgentBaseData = stateData.gridAgentBaseData
val tick = stateData.currentTick

// inform every system participant about a new simulation for the same tick
gridAgentBaseData.gridEnv.nodeToAssetAgents.values.foreach { actors =>
actors.foreach { actor =>
actor ! GridSimulationFinished(tick, tick)
}
}

// / clean copy of the gridAgentBaseData
val cleanedGridAgentBaseData = GridAgentBaseData.clean(
gridAgentBaseData,
gridAgentBaseData.superiorGridNodeUuids,
gridAgentBaseData.inferiorGridGates,
)

ctx.self ! Activation(tick)

// do another power flow calculation
GridAgent.simulateGrid(
cleanedGridAgentBaseData,
tick,
)
}

/** Method for finishing the congestion management. This method will return to
* the [[GridAgent.idle()]] state afterward.
*
Expand All @@ -90,12 +126,18 @@ trait DCMAlgorithm extends CongestionDetection {
constantData: GridAgentConstantData,
buffer: StashBuffer[Message],
): Behavior[Message] = {
val timestamp = constantData.simStartTime.plusSeconds(stateData.currentTick)

ctx.log.info(
s"There were some congestions that could not be resolved for timestamp: $timestamp."
)

// clean up agent and go back to idle
val powerFlowResults = stateData.getAllResults(constantData.simStartTime)

// return to idle
GridAgent.gotoIdle(
stateData.gridAgentBaseData,
stateData.resetProgress.gridAgentBaseData,
stateData.currentTick + constantData.resolution,
Some(powerFlowResults),
ctx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ final case class AwaitingData[T](
* @param receivedData
* Data that was received.
* @return
* A updated copy of this data.
* An updated copy of this data.
*/
def handleReceivingData(
receivedData: Vector[(ActorRef[GridAgent.Message], T)]
receivedData: Seq[(ActorRef[GridAgent.Message], T)]
): AwaitingData[T] = {
val mappedData = receivedData.map { case (ref, value) =>
ref -> Some(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ import edu.ie3.simona.agent.grid.GridAgentData.{
GridAgentBaseData,
GridAgentDataInternal,
}
import edu.ie3.simona.agent.grid.congestion.{CongestedComponents, Congestions}
import edu.ie3.simona.agent.grid.congestion.CongestionManagementParams.MitigationProgress
import edu.ie3.simona.agent.grid.congestion.mitigations.MitigationSteps
import edu.ie3.simona.agent.grid.congestion.{
CongestedComponents,
CongestionManagementParams,
Congestions,
}
import edu.ie3.simona.event.ResultEvent.PowerFlowResultEvent
import edu.ie3.util.quantities.QuantityUtils.asPercent
import org.apache.pekko.actor.typed.ActorRef
Expand All @@ -36,6 +42,8 @@ import scala.concurrent.duration.FiniteDuration
* Result of the previous power flow calculation.
* @param congestions
* The found congestions.
* @param congestedComponents
* The components that have congestion.
*/
final case class CongestionManagementData(
gridAgentBaseData: GridAgentBaseData,
Expand All @@ -46,6 +54,31 @@ final case class CongestionManagementData(
congestedComponents: CongestedComponents,
) extends GridAgentDataInternal {

def getNextMitigationMeasure
: (MitigationSteps.Value, CongestionManagementData) = {
val params = gridAgentBaseData.congestionManagementParams

val (nextStep, updatedProgress) = params.progress.getNextStepsAndUpdate

(
nextStep,
copy(gridAgentBaseData =
gridAgentBaseData.copy(congestionManagementParams =
params.copy(progress = updatedProgress)
)
),
)
}

def resetProgress: CongestionManagementData = {
val params = gridAgentBaseData.congestionManagementParams
val updatedParams = params.copy(progress = params.progress.reset)

copy(gridAgentBaseData =
gridAgentBaseData.copy(congestionManagementParams = updatedParams)
)
}

/** Builds a [[CongestionResult]] from the power flow results.
* @param startTime
* Of the simulation.
Expand Down Expand Up @@ -127,6 +160,9 @@ final case class CongestionManagementData(
def superiorGridRefs: Map[ActorRef[GridAgent.Message], Seq[UUID]] =
gridAgentBaseData.superiorGridRefs

def congestionManagementParams: CongestionManagementParams =
gridAgentBaseData.congestionManagementParams

def timeout: FiniteDuration =
gridAgentBaseData.congestionManagementParams.timeout
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ import edu.ie3.simona.agent.grid.congestion.data.{
AwaitingData,
CongestionManagementData,
}
import edu.ie3.simona.agent.grid.congestion.CongestionManagementMessages.*
import edu.ie3.simona.agent.grid.congestion.detection.DetectionMessages.*
import edu.ie3.simona.agent.grid.congestion.data.{
AwaitingData,
CongestionManagementData,
}
import edu.ie3.simona.agent.grid.congestion.Congestions
import edu.ie3.simona.agent.grid.congestion.mitigations.MitigationSteps
import edu.ie3.simona.agent.grid.congestion.mitigations.MitigationSteps.*
import org.apache.pekko.actor.typed.{ActorRef, Behavior}
import org.apache.pekko.actor.typed.scaladsl.{
ActorContext,
Expand All @@ -43,7 +51,7 @@ trait CongestionDetection {
private[grid] def checkForCongestion(
stateData: CongestionManagementData,
awaitingData: AwaitingData[Congestions],
)(implicit
)(using
constantData: GridAgentConstantData,
buffer: StashBuffer[GridAgent.Message],
): Behavior[GridAgent.Message] = Behaviors.receivePartial {
Expand Down Expand Up @@ -74,6 +82,25 @@ trait CongestionDetection {
ctx,
)

case (ctx, nextStep @ NextStep(step)) =>
stateData.inferiorGridRefs.keys.foreach(_ ! nextStep)

step match {
case TransformerTapChange =>
// use transformer tap change
ctx.self ! StartStep

GridAgent.updateTransformerTapping(
stateData,
AwaitingData(stateData.inferiorGridRefs.keySet),
)

case _ =>
// no mitigation measure found
ctx.self ! FinishStep
Behaviors.same
}

case (ctx, FinishStep) =>
// inform my inferior grids about the end of the congestion management
stateData.inferiorGridRefs.keys.foreach(
Expand Down Expand Up @@ -128,9 +155,9 @@ trait CongestionDetection {
private def processReceivedData(
stateData: CongestionManagementData,
awaitingData: AwaitingData[Congestions],
congestions: Vector[(ActorRef[GridAgent.Message], Congestions)],
congestions: Seq[(ActorRef[GridAgent.Message], Congestions)],
ctx: ActorContext[GridAgent.Message],
)(implicit
)(using
constantData: GridAgentConstantData,
buffer: StashBuffer[GridAgent.Message],
): Behavior[GridAgent.Message] = {
Expand All @@ -155,15 +182,16 @@ trait CongestionDetection {
s"Congestion overall: $updatedCongestions"
)

val timestamp =
constantData.simStartTime.plusSeconds(stateData.currentTick)
// first we find an option for the next mitigation step
val (step, updatedProgress) = stateData.getNextMitigationMeasure

ctx.log.info(
s"There were some congestions that could not be resolved for timestamp: $timestamp."
ctx.self ! NextStep(step)

val updatedStateData = updatedProgress.copy(
congestions = updatedCongestions
)

ctx.self ! FinishStep
checkForCongestion(stateData, updatedData)
checkForCongestion(updatedStateData, awaitingData)
}

} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ object DetectionMessages {
* vector of congestion in inferior grids
*/
final case class ReceivedCongestions(
values: Vector[(ActorRef[GridAgent.Message], Congestions)]
values: Seq[(ActorRef[GridAgent.Message], Congestions)]
) extends InternalReply
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/

package edu.ie3.simona.agent.grid.congestion.mitigations

/** Enumeration with all congestion management steps.
*/
object MitigationSteps extends Enumeration {
val TransformerTapChange, TopologyChange, FlexibilityDeployment, NoMeasure =
Value
}
Loading
Loading