com.zepben.evolve.services.network.tracing.feeder.AssignToFeeders.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of evolve-sdk Show documentation
Show all versions of evolve-sdk Show documentation
SDK for interaction with the evolve platform
/*
* Copyright 2020 Zeppelin Bend Pty Ltd
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.zepben.evolve.services.network.tracing.feeder
import com.zepben.evolve.cim.iec61970.base.auxiliaryequipment.AuxiliaryEquipment
import com.zepben.evolve.cim.iec61970.base.core.ConductingEquipment
import com.zepben.evolve.cim.iec61970.base.core.Equipment
import com.zepben.evolve.cim.iec61970.base.core.Feeder
import com.zepben.evolve.cim.iec61970.base.core.Terminal
import com.zepben.evolve.cim.iec61970.base.wires.PowerTransformer
import com.zepben.evolve.cim.iec61970.base.wires.ProtectedSwitch
import com.zepben.evolve.services.network.NetworkService
import com.zepben.evolve.services.network.tracing.traversals.BasicTraversal
/**
* Convenience class that provides methods for assigning HV/MV feeders on a [NetworkService].
* Requires that a Feeder have a normalHeadTerminal with associated ConductingEquipment.
* This class is backed by a [BasicTraversal].
*/
class AssignToFeeders {
private val normalTraversal = AssociatedTerminalTrace.newNormalTrace()
private val currentTraversal = AssociatedTerminalTrace.newCurrentTrace()
private lateinit var activeFeeder: Feeder
fun run(network: NetworkService) {
val terminalToAuxEquipment = network.sequenceOf()
.filter { it.terminal != null }
.groupBy { it.terminal!!.mRID }
val feederStartPoints = network.sequenceOf()
.mapNotNull { it.normalHeadTerminal }
.mapNotNull { it.conductingEquipment }
.toSet()
configureStepActions(normalTraversal, terminalToAuxEquipment)
configureStepActions(currentTraversal, terminalToAuxEquipment)
configureStopConditions(normalTraversal, feederStartPoints)
configureStopConditions(currentTraversal, feederStartPoints)
network.sequenceOf().forEach(::run)
}
private fun run(feeder: Feeder) {
activeFeeder = feeder
val headTerminal = feeder.normalHeadTerminal ?: return
run(normalTraversal, headTerminal)
run(currentTraversal, headTerminal)
}
private fun run(traversal: BasicTraversal, headTerminal: Terminal) {
traversal.reset()
traversal.tracker.visit(headTerminal)
traversal.applyStepActions(headTerminal, false)
AssociatedTerminalTrace.queueAssociated(traversal, headTerminal)
traversal.run()
}
private fun configureStepActions(traversal: BasicTraversal, terminalToAuxEquipment: Map>) {
traversal.clearStepActions()
normalTraversal.addStepAction(processNormal(terminalToAuxEquipment))
currentTraversal.addStepAction(processCurrent(terminalToAuxEquipment))
}
private fun configureStopConditions(traversal: BasicTraversal, feederStartPoints: Set) {
traversal.clearStopConditions()
traversal.addStopCondition(reachedEquipment(feederStartPoints))
traversal.addStopCondition(reachedSubstationTransformer)
traversal.addStopCondition(reachedLv)
}
private val reachedEquipment: (Set) -> (Terminal) -> Boolean = { { terminal: Terminal -> it.contains(terminal.conductingEquipment) } }
private val reachedSubstationTransformer: (Terminal) -> Boolean = { ps: Terminal ->
val ce = ps.conductingEquipment
ce is PowerTransformer && ce.substations.isNotEmpty()
}
private val reachedLv: (Terminal) -> Boolean = { terminal ->
terminal.conductingEquipment?.baseVoltage?.let { it.nominalVoltage < 1000 } ?: false
}
private fun processNormal(
terminalToAuxEquipment: Map>
): (Terminal, Boolean) -> Unit =
{ terminal, isStopping ->
process(
terminal,
{ eq, feeder ->
eq.addContainer(feeder)
// Handle classes extending Equipment
when (eq) {
is ProtectedSwitch ->
eq.relayFunctions.flatMap { it.schemes }.mapNotNull { it.system }.forEach { system ->
system.addContainer(feeder)
}
}
},
{ feeder, eq ->
feeder.addEquipment(eq)
when (eq) {
is ProtectedSwitch ->
eq.relayFunctions.flatMap { it.schemes }.mapNotNull { it.system }.forEach { system ->
feeder.addEquipment(system)
}
}
},
isStopping,
terminalToAuxEquipment
)
}
private fun processCurrent(
terminalToAuxEquipment: Map>
): (Terminal, Boolean) -> Unit =
{ terminal, isStopping ->
process(
terminal,
{ eq, feeder ->
eq.addCurrentContainer(feeder)
// Handle classes extending Equipment
when (eq) {
is ProtectedSwitch ->
eq.relayFunctions.flatMap { it.schemes }.mapNotNull { it.system }.forEach { system ->
system.addCurrentContainer(feeder)
}
}
},
{ feeder, eq ->
feeder.addCurrentEquipment(eq)
// Handle classes extending Equipment
when (eq) {
is ProtectedSwitch ->
eq.relayFunctions.flatMap { it.schemes }.mapNotNull { it.system }.forEach { system ->
feeder.addCurrentEquipment(system)
}
}
},
isStopping,
terminalToAuxEquipment
)
}
private fun process(
terminal: Terminal,
assignFeederToEquipment: (Equipment, Feeder) -> Unit,
assignEquipmentToFeeder: (Feeder, Equipment) -> Unit,
isStopping: Boolean,
terminalToAuxEquipment: Map>
) {
if (isStopping && (reachedLv(terminal) || reachedSubstationTransformer(terminal)))
return
terminalToAuxEquipment[terminal.mRID]?.forEach {
assignFeederToEquipment(it, activeFeeder)
assignEquipmentToFeeder(activeFeeder, it)
}
terminal.conductingEquipment?.let {
assignFeederToEquipment(it, activeFeeder)
assignEquipmentToFeeder(activeFeeder, it)
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy