Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DBFS with multiple connections between sub grids #25

Merged
merged 50 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
1f525cd
Fix communication protocol
ckittl Dec 13, 2021
ba62812
Add a first changelog
ckittl Dec 13, 2021
a5bf9c5
Merge remote-tracking branch 'origin/dev' into ck/#22-dbfsMultipleCon…
ckittl Jan 12, 2022
31f9e86
Address reviewer comments
ckittl Jan 12, 2022
7a34ab3
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
ckittl Jan 26, 2022
6ab7d4b
Send FinishGridSimulationTrigger only once
ckittl Feb 8, 2022
fa5934c
Merge remote-tracking branch 'origin/dev' into ck/#22-dbfsMultipleCon…
ckittl Feb 8, 2022
89cc974
Fix gradel download plugin call
ckittl Feb 8, 2022
73dcc5a
Fix config auto-generation
ckittl Feb 8, 2022
b97ba5e
Merge remote-tracking branch 'origin/dev' into ck/#22-dbfsMultipleCon…
ckittl Mar 8, 2022
210c795
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
sebastian-peter Jun 21, 2022
a726da2
Naming a lot of unnamed variables, removing some dead code
sebastian-peter Jun 21, 2022
910a61a
Small code improvements
sebastian-peter Jun 21, 2022
617cfa1
More code improvements
sebastian-peter Jun 21, 2022
e9645e4
Consolidate ReceivedValues and ReceivedValuesStore field types
sebastian-peter Jun 21, 2022
6d0dd29
Possibly fixing codacy issue
sebastian-peter Jun 21, 2022
2ad52c2
Refactoring
sebastian-peter Jun 22, 2022
69cff10
Applying code style improvements from #266
sebastian-peter Jun 27, 2022
f38ac31
Applying code style improvements
sebastian-peter Jun 29, 2022
67ab51f
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
sebastian-peter Jun 29, 2022
314d8d5
Simplifying ReceivedValuesStore
sebastian-peter Jun 29, 2022
2ad69c4
Further improving DBFS tests, removing synchronous tests
sebastian-peter Jun 29, 2022
14dd3b8
Simplifying DbfsTestGrid a tiny bit
sebastian-peter Jun 30, 2022
ebb559e
Solving CodeSmells in test, plus some minor improvements
sebastian-peter Jul 1, 2022
9f9b765
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
sebastian-peter Jul 4, 2022
27f0b74
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
t-ober Jul 7, 2022
7300b2b
Apply suggestions from code review
sebastian-peter Jul 8, 2022
3f571a3
Addressing some reviewer comments
sebastian-peter Jul 8, 2022
c89ee1b
Replacing subnet with subgrid in a lot of places
sebastian-peter Jul 8, 2022
aebcc06
Variable renaming
sebastian-peter Jul 8, 2022
a42da7c
Refactoring SweepValueStore to use a map instead of a vector
sebastian-peter Jul 8, 2022
06be2d8
Revert "Refactoring SweepValueStore to use a map instead of a vector"
sebastian-peter Jul 8, 2022
edbc579
Adapting slack voltage communication to only send one message per sub…
sebastian-peter Jul 9, 2022
b35c13a
Always taking the slack node with smallest index
sebastian-peter Jul 10, 2022
abfd7b8
Fixed horribly inefficient map operation
sebastian-peter Jul 11, 2022
44e4a28
Fixating the order of nodes
sebastian-peter Jul 11, 2022
fcee14c
Have DBFS return power in correct unit (Watt/Var)
sebastian-peter Jul 19, 2022
2cc81d8
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
sebastian-peter Jul 19, 2022
2eb4be0
Enhancing QuantityUtilSpec.scala
sebastian-peter Jul 20, 2022
c237231
Reverting Var unit naming in ScalaDoc
sebastian-peter Jul 21, 2022
dedb104
Merged fix & dev
sebastian-peter Jul 31, 2022
b3457ba
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
sebastian-peter Jul 31, 2022
1daeab0
Fixing the merge
sebastian-peter Jul 31, 2022
d99ce36
Applying test adaptations of #71 (slack voltage angle)
sebastian-peter Jul 31, 2022
4642454
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
t-ober Aug 1, 2022
d0c84c0
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
sebastian-peter Aug 1, 2022
e0aa251
Renaming ReceivedSlackValues to ReceivedSlackVoltageValues
sebastian-peter Aug 1, 2022
eb9097e
Added comment to nodes sequence conversion
sebastian-peter Aug 1, 2022
bc66dc3
Replacing RichQuantity and RichUnit with the new copies in PSU
sebastian-peter Aug 1, 2022
419bc1b
Merge branch 'dev' into ck/#22-dbfsMultipleConnections
t-ober Aug 2, 2022
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix breaking SIMONA caused by introducing temperature dependant load profiles in PSDM [#255](https://github.com/ie3-institute/simona/issues/255)
- Respect for voltage angle in DBFS slack voltage exchange protocol [#69](https://github.com/ie3-institute/simona/issues/69)
- Adapted to changed time series interfaces in PSDM [#296](https://github.com/ie3-institute/simona/issues/296)
- Fix handling of multiple connections between subgrids [#22](https://github.com/ie3-institute/simona/issues/22)
- Consolidate request replies for different sub grid gates in one message
- Await and send responses for distinct pairs of sender reference and target node

### Removed
- Remove workaround for tscfg tmp directory [#178](https://github.com/ie3-institute/simona/issues/178)
Expand Down
246 changes: 153 additions & 93 deletions src/main/scala/edu/ie3/simona/agent/grid/DBFSAlgorithm.scala

Large diffs are not rendered by default.

96 changes: 66 additions & 30 deletions src/main/scala/edu/ie3/simona/agent/grid/GridAgentData.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ import edu.ie3.powerflow.model.PowerFlowResult
import edu.ie3.powerflow.model.PowerFlowResult.SuccessFullPowerFlowResult.ValidNewtonRaphsonPFResult
import edu.ie3.simona.agent.grid.ReceivedValues.{
ReceivedPowerValues,
ReceivedSlackValues
ReceivedSlackVoltageValues
}
import edu.ie3.simona.agent.grid.ReceivedValuesStore.NodeToReceivedPower
import edu.ie3.simona.model.grid.{GridModel, RefSystem}
import edu.ie3.simona.ontology.messages.PowerMessage.{
FailedPowerFlow,
PowerResponseMessage,
ProvideGridPowerMessage,
ProvidePowerMessage
}

Expand Down Expand Up @@ -53,9 +54,9 @@ object GridAgentData {
refSystem: RefSystem
) extends GridAgentData
with GridAgentDataHelper {
override protected val subnetGates: Vector[SubGridGate] =
override protected val subgridGates: Vector[SubGridGate] =
subGridGateToActorRef.keys.toVector
override protected val subnetId: Int = subGridContainer.getSubnet
override protected val subgridId: Int = subGridContainer.getSubnet
}

/** State data indicating that a power flow has been executed.
Expand All @@ -64,12 +65,30 @@ object GridAgentData {
* the base data of the [[GridAgent]]
* @param powerFlowResult
* result of the executed power flow
* @param pendingRequestAnswers
* Set of subgrid numbers of [[GridAgent]]s that don't have their request
* answered, yet
*/
final case class PowerFlowDoneData(
final case class PowerFlowDoneData private (
gridAgentBaseData: GridAgentBaseData,
powerFlowResult: PowerFlowResult
powerFlowResult: PowerFlowResult,
pendingRequestAnswers: Set[Int]
) extends GridAgentData

object PowerFlowDoneData {
def apply(
gridAgentBaseData: GridAgentBaseData,
powerFlowResult: PowerFlowResult
): PowerFlowDoneData = {
/* Determine the subgrid numbers of all superior grids */
val superiorSubGrids = gridAgentBaseData.gridEnv.subgridGateToActorRef
.map { case (subGridGate, _) => subGridGate.getSuperiorNode.getSubnet }
.filterNot(_ == gridAgentBaseData.gridEnv.gridModel.subnetNo)
.toSet
PowerFlowDoneData(gridAgentBaseData, powerFlowResult, superiorSubGrids)
}
}

/** The base data that is mainly used by the [[GridAgent]]. This data has to
* be copied several times at several places for each state transition with
* updated data. So be careful in adding more data on it!
Expand All @@ -78,7 +97,7 @@ object GridAgentData {

def apply(
gridModel: GridModel,
subnetGateToActorRef: Map[SubGridGate, ActorRef],
subgridGateToActorRef: Map[SubGridGate, ActorRef],
nodeToAssetAgents: Map[UUID, Set[ActorRef]],
superiorGridNodeUuids: Vector[UUID],
inferiorGridGates: Vector[SubGridGate],
Expand All @@ -93,11 +112,11 @@ object GridAgentData {
Int,
SweepValueStore
] // initialization is assumed to be always with no sweep data
val inferiorGridGateToActorRef = subnetGateToActorRef.filter {
val inferiorGridGateToActorRef = subgridGateToActorRef.filter {
case (gate, _) => inferiorGridGates.contains(gate)
}
GridAgentBaseData(
GridEnvironment(gridModel, subnetGateToActorRef, nodeToAssetAgents),
GridEnvironment(gridModel, subgridGateToActorRef, nodeToAssetAgents),
powerFlowParams,
currentSweepNo,
ReceivedValuesStore.empty(
Expand Down Expand Up @@ -135,7 +154,7 @@ object GridAgentData {
gridAgentBaseData.copy(
receivedValueStore = ReceivedValuesStore.empty(
gridAgentBaseData.gridEnv.nodeToAssetAgents,
gridAgentBaseData.gridEnv.subnetGateToActorRef.filter {
gridAgentBaseData.gridEnv.subgridGateToActorRef.filter {
case (gate, _) => inferiorGridGates.contains(gate)
},
superiorGridNodeUuids
Expand Down Expand Up @@ -176,9 +195,9 @@ object GridAgentData {
) extends GridAgentData
with GridAgentDataHelper {

override protected val subnetGates: Vector[SubGridGate] =
gridEnv.subnetGateToActorRef.keys.toVector
override protected val subnetId: Int = gridEnv.gridModel.subnetNo
override protected val subgridGates: Vector[SubGridGate] =
gridEnv.subgridGateToActorRef.keys.toVector
override protected val subgridId: Int = gridEnv.gridModel.subnetNo

val allRequestedDataReceived: Boolean = {
// we expect power values from inferior grids and assets
Expand Down Expand Up @@ -221,10 +240,33 @@ object GridAgentData {
val updatedNodeToReceivedPowersMap = receivedPowerValues.values.foldLeft(
receivedValueStore.nodeToReceivedPower
) {
case (
nodeToReceivedPowerValuesMapWithAddedPowerResponse,
(
senderRef,
provideGridPowerMessage: ProvideGridPowerMessage
)
) =>
/* Go over all includes messages and add them. */
provideGridPowerMessage.nodalResidualPower.foldLeft(
nodeToReceivedPowerValuesMapWithAddedPowerResponse
) {
case (
nodeToReceivedPowerValuesMapWithAddedExchangedPower,
exchangedPower
) =>
updateNodalReceivedPower(
exchangedPower,
nodeToReceivedPowerValuesMapWithAddedExchangedPower,
senderRef,
replace
)
}
case (
nodeToReceivedPowerValuesMapWithAddedPowerResponse,
(senderRef, powerResponseMessage)
) =>
// some other singular power response message
updateNodalReceivedPower(
powerResponseMessage,
nodeToReceivedPowerValuesMapWithAddedPowerResponse,
Expand Down Expand Up @@ -328,8 +370,8 @@ object GridAgentData {
}
.map { case (uuid, _) => uuid }

/** Update this [[GridAgentBaseData]] with [[ReceivedSlackValues]] and
* return a copy of this [[GridAgentBaseData]] for further processing
/** Update this [[GridAgentBaseData]] with [[ReceivedSlackVoltageValues]]
* and return a copy of this [[GridAgentBaseData]] for further processing
*
* @param receivedSlackValues
* the slack voltage values that should be used for the update
Expand All @@ -338,33 +380,27 @@ object GridAgentData {
* receivedSlackValues
*/
def updateWithReceivedSlackVoltages(
receivedSlackValues: ReceivedSlackValues
receivedSlackValues: ReceivedSlackVoltageValues
): GridAgentBaseData = {
val updatedNodeToReceivedSlackVoltageValuesMap =
receivedSlackValues.values.foldLeft(
receivedValueStore.nodeToReceivedSlackVoltage
) {
case (
nodeToSlackVoltageUpdated,
(senderRef, slackValues)
) =>
val nodeUuid: UUID = slackValues.nodeUuid

receivedSlackValues.values.flatMap { case (senderRef, slackValues) =>
slackValues.nodalSlackVoltages.map { exchangeVoltage =>
receivedValueStore.nodeToReceivedSlackVoltage
.get(nodeUuid) match {
.get(exchangeVoltage.nodeUuid) match {
case Some(None) =>
/* Slack voltage is expected and not yet received */
nodeToSlackVoltageUpdated + (nodeUuid -> Some(slackValues))
exchangeVoltage.nodeUuid -> Some(exchangeVoltage)
case Some(Some(_)) =>
throw new RuntimeException(
s"Already received slack value for node $nodeUuid!"
s"Already received slack value for node ${exchangeVoltage.nodeUuid}!"
)
case None =>
throw new RuntimeException(
s"Received slack value for node $nodeUuid from $senderRef which is not in my slack values nodes list!"
s"Received slack value for node ${exchangeVoltage.nodeUuid} from $senderRef which is not in my slack values nodes list!"
)
}
}
}
}.toMap
this.copy(
receivedValueStore = receivedValueStore.copy(
nodeToReceivedSlackVoltage =
Expand Down Expand Up @@ -406,7 +442,7 @@ object GridAgentData {
sweepValueStores = updatedSweepValueStore,
receivedValueStore = ReceivedValuesStore.empty(
gridEnv.nodeToAssetAgents,
gridEnv.subnetGateToActorRef.filter { case (gate, _) =>
gridEnv.subgridGateToActorRef.filter { case (gate, _) =>
inferiorGridGates.contains(gate)
},
superiorGridNodeUuids
Expand Down
28 changes: 14 additions & 14 deletions src/main/scala/edu/ie3/simona/agent/grid/GridAgentDataHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,43 @@ import edu.ie3.datamodel.graph.SubGridGate
*/
private[grid] trait GridAgentDataHelper {

protected val subnetGates: Vector[SubGridGate]
protected val subnetId: Int
protected val subgridGates: Vector[SubGridGate]
protected val subgridId: Int

// methods definition
def superiorGridIds: Vector[String] =
subnetGates.collect {
case gate: SubGridGate if gate.getInferiorSubGrid == subnetId =>
subgridGates.collect {
case gate: SubGridGate if gate.getInferiorSubGrid == subgridId =>
gate.getSuperiorSubGrid.toString
}

def inferiorGridIds: Vector[String] =
subnetGates.collect {
case gate: SubGridGate if gate.getSuperiorSubGrid == subnetId =>
subgridGates.collect {
case gate: SubGridGate if gate.getSuperiorSubGrid == subgridId =>
gate.getInferiorSubGrid.toString
}

def superiorGridNodeUuids: Vector[UUID] =
subnetGates.collect {
case gate: SubGridGate if gate.getInferiorSubGrid == subnetId =>
subgridGates.collect {
case gate: SubGridGate if gate.getInferiorSubGrid == subgridId =>
gate.getSuperiorNode.getUuid
}

def inferiorGridNodeUuids: Vector[UUID] =
subnetGates.collect {
case gate: SubGridGate if gate.getSuperiorSubGrid == subnetId =>
subgridGates.collect {
case gate: SubGridGate if gate.getSuperiorSubGrid == subgridId =>
gate.getInferiorNode.getUuid
}

def superiorGridGates: Vector[SubGridGate] =
subnetGates.collect {
case gate: SubGridGate if gate.getInferiorSubGrid == subnetId =>
subgridGates.collect {
case gate: SubGridGate if gate.getInferiorSubGrid == subgridId =>
gate
}

def inferiorGridGates: Vector[SubGridGate] =
subnetGates.collect {
case gate: SubGridGate if gate.getSuperiorSubGrid == subnetId =>
subgridGates.collect {
case gate: SubGridGate if gate.getSuperiorSubGrid == subgridId =>
gate
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ import edu.ie3.simona.model.grid.GridModel
*
* @param gridModel
* [[GridModel]] with all asset information
* @param subnetGateToActorRef
* @param subgridGateToActorRef
* a mapping of all [[SubGridGate]] s to their corresponding [[ActorRef]] s
* @param nodeToAssetAgents
* a mapping of all node uuids to a set of asset [[ActorRef]] s at those
* nodes
*/
final case class GridEnvironment(
gridModel: GridModel,
subnetGateToActorRef: Map[SubGridGate, ActorRef],
subgridGateToActorRef: Map[SubGridGate, ActorRef],
nodeToAssetAgents: Map[UUID, Set[ActorRef]]
)
Loading