Skip to main content
Version: 0.41.1

Protection Relays

Protection Relay Functions, Schemes, and Systems

Each protection relay in the CIM model is implemented in a ProtectionRelayFunction, which is composed of a collection of Sensors, thresholds that determine the conditions that activate the relay, the time limits for each condition before activation, and the ProtectedSwitches to open when the relay is activated.

ProtectionRelayFunctions may be grouped into ProtectionRelaySchemes, each of which belong to a ProtectionRelaySystem. A ProtectionRelaySystem is a physical piece of equipment containing a suite of ProtectionRelayFunctions, such as a circuit breaker panel. They typically comprise two schemes: main and failsafe.

Here is a contrived example of such a system modelled using the Evolve SDK:

from zepben.evolve import Breaker, CurrentTransformer, CurrentRelay, RelaySetting, UnitSymbol, ProtectionRelayScheme, ProtectionRelaySystem


def main():
# Breakers for stove, bathroom, and washer are for individual outlets,
# whereas the failsafe breaker can disconnect all appliances from power.
stove_breaker = Breaker("stoveBreaker")
bathroom_breaker = Breaker("bathroomBreaker")
washer_breaker = Breaker("washerBreaker")
failsafe_breaker = Breaker("failsafeBreaker")

stove_ct = CurrentTransformer("stoveCT")
bathroom_ct = CurrentTransformer("bathroomCT")
washer_ct = CurrentTransformer("washerCT")
failsafe_ct = CurrentTransformer("failsafeCT")

stove_cr = (CurrentRelay("stoveCR")
.add_protected_switch(stove_breaker)
.add_sensor(stove_ct)
.add_threshold(RelaySetting(UnitSymbol.A, 50.0))
.add_time_limit(0.5))
stove_breaker.add_relay_function(stove_cr)
stove_ct.add_relay_function(stove_cr)

bathroom_cr = (CurrentRelay("bathroomCR")
.add_protected_switch(bathroom_breaker)
.add_sensor(bathroom_ct)
.add_threshold(RelaySetting(UnitSymbol.A, 50.0))
.add_time_limit(0.5))
bathroom_breaker.add_relay_function(bathroom_cr)
bathroom_ct.add_relay_function(bathroom_cr)

washer_cr = (CurrentRelay("washerCR")
.add_protected_switch(washer_breaker)
.add_sensor(washer_ct)
.add_threshold(RelaySetting(UnitSymbol.A, 50.0))
.add_time_limit(0.5))
washer_breaker.add_relay_function(washer_cr)
washer_ct.add_relay_function(washer_cr)

failsafe_cr = (CurrentRelay("failsafeCR")
.add_protected_switch(failsafe_breaker)
.add_sensor(failsafe_ct)
.add_threshold(RelaySetting(UnitSymbol.A, 50.0))
.add_time_limit(0.5))
failsafe_breaker.add_relay_function(failsafe_cr)
failsafe_ct.add_relay_function(failsafe_cr)

main_scheme = (ProtectionRelayScheme("main")
.add_function(stove_cr)
.add_function(bathroom_cr)
.add_function(washer_cr))
stove_cr.add_scheme(main_scheme)
bathroom_cr.add_scheme(main_scheme)
washer_cr.add_scheme(main_scheme)

failsafe_scheme = (ProtectionRelayScheme("failsafe")
.add_function(failsafe_cr))

failsafe_cr.add_scheme(failsafe_scheme)

system = (ProtectionRelaySystem("system")
.add_scheme(main_scheme)
.add_scheme(failsafe_scheme))
main_scheme.system = system
failsafe_scheme.system = system

For brevity, this example excludes modelling of connectivity between the sensors and breakers.

Grounds and Ground Disconnectors

To aid in modelling protection systems, our network data model also supports explicit modelling of grounds and ground disconnectors:

from zepben.evolve import NetworkService, Terminal, Ground, GroundDisconnector, Junction


def main():
# junction --- ground disconnector --- ground
network_service = NetworkService()

ground_terminal = Terminal("ground-t1")
ground = (Ground("ground")
.add_terminal(ground_terminal))

gd_terminal1 = Terminal("gd-t1")
gd_terminal2 = Terminal("gd-t2")
gd = (GroundDisconnector("gd")
.add_terminal(gd_terminal1)
.add_terminal(gd_terminal2))

junction_terminal = Terminal("junction-t1")
junction = (Junction("junction")
.add_terminal(junction_terminal))

network_service.connect_terminals(junction_terminal, gd_terminal1)
network_service.connect_terminals(gd_terminal2, ground_terminal)
for io in [ground, ground_terminal, gd, gd_terminal1, gd_terminal2, junction, junction_terminal]:
network_service.add(io)

Series Compensators

The Evolve SDK also supports modelling series compensators, which are series capacitors and reactors or an AC transmission line without charging susceptance.

from zepben.evolve import NetworkService, Terminal, AcLineSegment, SeriesCompensator


def main():
# AC line 1 --- series compensator -- AC line 2
network_service = NetworkService()

acls1_terminal1 = Terminal("acls1-t1")
acls1_terminal2 = Terminal("acls1-t2")
acls1 = (AcLineSegment("acls1")
.add_terminal(acls1_terminal1)
.add_terminal(acls1_terminal2))

acls2_terminal1 = Terminal("acls2-t1")
acls2_terminal2 = Terminal("acls2-t2")
acls2 = (AcLineSegment("acls2")
.add_terminal(acls2_terminal1)
.add_terminal(acls2_terminal2))

sc_terminal1 = Terminal("sc-t1")
sc_terminal2 = Terminal("sc-t2")
sc = SeriesCompensator("sc")
# dummy (likely unrealistic) values
sc.r = 1.0
sc.r0 = 1.5
sc.x = 123.0
sc.x0 = 125.0
sc.varistor_voltage_threshold = 10
sc.varistor_rated_current = 5
sc.add_terminal(sc_terminal1)
sc.add_terminal(sc_terminal2)

network_service.connect_terminals(acls1_terminal2, sc_terminal1)
network_service.connect_terminals(sc_terminal2, acls2_terminal1)

for io in [acls1, acls1_terminal1, acls1_terminal2, acls2, acls2_terminal1, acls2_terminal2, sc, sc_terminal1, sc_terminal2]:
network_service.add(io)