This project is an extension of evolve-sdk-python for the Edith project.
It provides functionality to create synthetic feeders from an Edith network hosted in the Energy workbench server, and apply certain scenarios to them to modify the network.
Functionality is implemented on the NetworkConsumerClient from the Evolve SDK, so to use simply do the following:
from zepben.evolve import connect_with_password
from zepben.edith import NetworkConsumerClient, usage_point_proportional_allocator
channel = connect_with_password(client_id="some_client_id", username="test", password="secret", host="host", port=443)
client = NetworkConsumerClient(channel)
mutator = usage_point_proportional_allocator(
proportion=30,
edith_customers=["9995435452"],
allow_duplicate_customers=True, # exclude to prevent adding a customer to multiple usage points
seed=1234, # exclude for non-deterministic allocation
callback=print # prints set of usage points with added NMI names, after assigning NMIs
)
await client.create_synthetic_feeder(
"some_feeder_mrid",
mutators=[mutator],
)
synthetic_feeder = client.service
# ... do stuff with synthetic feeder ...
The create_synthetic_feeder
function fetches a feeder's network and applies a sequence of mutator functions.
mutator = ... # see subsections for options
await client.create_synthetic_feeder(
"some_feeder_mrid",
mutators=[mutator]
)
A mutator function takes a network and changes it in some way, for example increasing line impedances. Mutator functions return a set containing the mRIDs of modified objects. The Edith extension provides a few functions that create mutator functions:
from zepben.edith import usage_point_proportional_allocator
mutator = usage_point_proportional_allocator(
proportion=30,
edith_customers=["9995435452"],
allow_duplicate_customers=True, # exclude to prevent adding a customer to multiple usage points
seed=1234 # exclude for non-deterministic allocation
callback=print # function to call on set of mrids of named usage points (Set[str] -> Any)
)
await client.create_synthetic_feeder(
"some_feeder_mrid",
mutators=[mutator]
)
The usage_point_proportional_allocator
function creates a mutator that distributes NMI names across a percentage
of usage points. It will use up all provided names before reusing any. In other words, it will not reuse a name unless
the number of modified usage points (len(modified_usage_point_mrids)
) is greater than the length of edith_customers
.
By default, it will stop allocating NMI names once it uses up all provided names, unless allow_duplicate_customers
is
set to True
. This allocator also removes an existing NMI on each usage point it adds a NMI to, if there exists one.
Example: A synthetic feeder is created on a feeder with 5 usage points: UP1, UP2, UP3, UP4, and UP5. The allocator is
a usage_point_proportional_allocator(proportion=60, edith_customers=["A", "B", "C"])
. One possible result of the
allocation is for UP5 to receive name "A", UP2 to receive name "B", and UP3 to receive name "C". UP1 and UP4 would not
be modified in this case.
The seed
parameter is used to seed the pseudorandom number generator, making the random allocations reproducible.
A callback function may be provided. It will be run on the set of mRIDs of named usage points.
from zepben.edith import line_weakener
mutator = line_weakener(
weakening_percentage=30,
use_weakest_when_necessary=False # exclude to use weakest line type when necessary
callback=print # function to call on the set of mRIDs of downgraded lines (Set[str] -> Any)
)
await client.create_synthetic_feeder(
"some_feeder_mrid",
mutators=[mutator]
)
The line weakener decreases the amp rating and modifies impedance of lines by selecting from a built-in catalogue of linecodes. For each line, the applied linecode must match its phase count and whether its voltage category (HV or LV).
Suppose a line has an amp rating of 300A. with a weakening_percentage
of 30, the linecode used will have an amp rating
of at most (100 - 30)% of 300A, i.e. 210A. Linecode "ABC4w:70ABC" would be used if the line is 3-phase LV, with an amp
rating of 175A. Note that if there are multiple linecodes that fit the criteria, the one with the highest amp rating is
used. If there are no linecodes that fit the criteria and use_weakest_when_necessary
is True
, then the
lowest-amp-rating linecode that matches the phase and voltage criteria is used, if there is one. Otherwise, the line is
left unmodified.
A callback function may be provided. It will be run on the set of mRIDs of downgraded lines.
from zepben.edith import transformer_weakener
mutator = transformer_weakener(
weakening_percentage=30,
use_weakest_when_necessary=False, # exclude to use weakest transformer model when necessary
match_voltages=False, # exclude to ensure transformer models match winding voltages
callback=print # function to call on the set of mRIDs of downgraded transformers (Set[str] -> Any)
)
await client.create_synthetic_feeder(
"some_feeder_mrid",
mutators=[mutator]
)
The transformer weakener decreases the VA rating of power transformers by selecting from a built-in catalogue of
transformer models. For each transformer, the applied model must match the number of windings (usually 2), the phase
count, and the rated voltages (e.g. 11000 and 433). The last requirement is ignored if match_voltages
is False
.
Suppose a transformer has a VA rating of 300kVA. With a weakening percentage of 30, the new VA rating should be at most (100 - 30)% of 300kVA, i.e. 210kVA. If the transformer is 3-phase and the winding voltages are 11kV and 433V, the "M_200KVA_11KV_433V_3PH_PADMOUNT_Tyree" transformer model may be used, decreasing the VA rating of the transformer to 200VA.
A callback function may be provided. It will be run on the set of mRIDs of downgraded transformers.