Model of an electric distribution network for calculation
Project description
egrid
Purpose
Egrid is the outsourced first part of a power flow calculation for an electric, balanced, distribution network. Instances of Model provide a structure for calculating current and power flow through lines and into consumers (using the voltage vector which is the result of a power-flow-calculation).
Function make_model(*args) creates an instance of Model from arguments of type
- Slacknode
- Branch (line, series capacitor, transformer winding, transformer,
closed switch)
- Injection (consumer, shunt capacitor, PQ/PV-generator, battery)
- Output (indicates that measured flow (I, P or Q) or a part thereof
flows through the referenced terminal (device or node+device))
- PValue (measured active power)
- QValue (measured reactive power)
- IValue (measured electric current)
- Vvalue (measured voltage or setpoint)
- Defk/Deft (definition of a scaling/termional factor, for estimation)
- Defvl (definition of voltage limits)
- Klink/Tlink (associates a factor to an injection or terminal of a branch)
- Defoterm (term for objective function)
including tuples, lists and iterables thereof (for a power-flow-calculation just Slacknode ... Injection are necessary). Additionally, make_model can consume network descriptions as multiline strings if package 'graphparser' is installed. This method is intended to input very small electric networks using a text editor.
Most fields of Model instances provide pandas.DataFrame instances. Electric values are stored per unit. Branch models are PI-equivalent circuits. Active and reactive power of injections have a dedicated voltage exponent.
Details of egrid.model.Model
Fields of egrid.model.Model
nodes: pandas.DataFrame (id of node)
* .idx, int, index of power-flow-calculation node
slacks: pandas.DataFrame
* .id_of_node, str, id of connection node
* .V, complex, given voltage at this slack
* .index_of_node, int, index of power-flow-calculation node
injections: pandas.DataFrame
* .id, str, unique identifier of injection
* .id_of_node, str, unique identifier of connected node
* .P10, float, active power at voltage magnitude 1.0 pu
* .Q10, float, reactive power at voltage magnitude 1.0 pu
* .Exp_v_p, float, voltage dependency exponent of active power
* .Exp_v_q, float, voltage dependency exponent of reactive power
* .index_of_node, int, index of connected power-flow-calculation node
terminal_to_branch: numpy.array
* [0, br] indices of terminal A
* [1, br] indices of terminal B
index of branch is the column index
branchterminals: pandas.DataFrame
* .index_of_branch, int, index of branch
* .id_of_branch, str, unique idendifier of branch
* .id_of_node, str, unique identifier of connected node
* .id_of_other_node, str, unique identifier of node connected
at other side of the branch
* .index_of_node, int, index of connected power-flow-calculation node
* .index_of_other_node, int, index of power-flow-calculation node connected
at other side of the branch
* .y_lo, complex, longitudinal branch admittance
* .y_tr_half, complex, half of transversal branch admittance
* .g_lo, float, longitudinal conductance
* .b_lo, float, longitudinal susceptance
* .g_tr_half, float, transversal conductance of branch devided by 2
* .b_tr_half, float, transversal susceptance of branch devided by 2
* .side, str, 'A' | 'B', side of branch, first or second
bridgeterminals: pandas.DataFrame
* .index_of_branch, int, index of branch
* .id_of_branch, str, unique idendifier of branch
* .id_of_node, str, unique identifier of connected node
* .id_of_other_node, str, unique identifier of node connected
at other side of the branch
* .index_of_node, int, index of connected power-flow-calculation node
* .index_of_other_node, int, index of power-flow-calculation node connected
at other side of the branch
* .y_lo, complex, longitudinal branch admittance
* .y_tr_half, complex, half of transversal branch admittance
* .g_lo, float, longitudinal conductance
* .b_lo, float, longitudinal susceptance
* .g_tr_half, float, transversal conductance of branch devided by 2
* .b_tr_half, float, transversal susceptance of branch devided by 2
* .side, str, 'A' | 'B', side of branch, first or second
branchoutputs: pandas.DataFrame
* .id_of_batch, str, unique identifier of measurement batch
* .id_of_node, str, id of node connected to branch terminal
* .id_of_branch, str, unique identifier of branch
* .index_of_node, int, index of power-flow-calculation node connected
to branch terminal
* .index_of_branch, int, index of branch
injectionoutputs: pandas.DataFrame
* .id_of_batch, str, unique identifier of measurement batch
* .id_of_injection, str, unique identifier of injection
* .index_of_injection, str, index of injection
pvalues: pandas.DataFrame
* .id_of_batch, str, unique identifier of measurement batch
* .P, float, active power
* .direction, float, -1: from device into node, 1: from node into device
qvalues: pandas.DataFrame
* .id_of_batch, str, unique identifier of measurement batch
* .Q, float, reactive power
* .direction, float, -1: from device into node, 1: from node into device
ivalues: pandas.DataFrame
* .id_of_batch, str, unique identifier of measurement batch
* .I, float, electric current
vvalues: pandas.DataFrame
* .id_of_node, str, unique identifier of node voltage is given for
* .V, float, magnitude of voltage
* .index_of_node, index of node voltage is given for
shape_of_Y: tuple (int, int)
shape of admittance matrix for power flow calculation
count_of_slacks: int
count_of_slacks
factors: egrid.factors.Factors (namedtuple)
* .gen_factordata, pandas.DataFrame (index: ('step','id'))
* .step, -1
* .type, 'var'|'const', type of factor decision variable or parameter
* .id_of_source, str, id of factor (previous optimization step)
for initialization
* .value, float, used by initialization if no source factor in previous
optimization step
* .min, float
smallest possible value
* .max, float
greatest possible value
* .is_discrete, bool
just 0 digits after decimal point if True, input for solver,
accepted by MINLP solvers
* .m, float,
multiplier,
the effective value of the factor is a linear function
of var/const (mx + n)
* .n, float,
value of factor when var/const is 0,
the effective value of the factor is a linear function
of var/const (mx + n)
* .index_of_symbol, int
* .cost, float, cost of changing (for Volt-Var-control)
* .gen_injfactor, pandas.DataFrame (index: ('id_of_injection', 'part'))
* .step, -1 (int)
* id, str, ID of factor
* .terminalfactors, pandas.DataFrame
* .id, str, identifier of factor
* .index_of_terminal, int
* .index_of_other_terminal, int
* .type, 'var'|'const'
* .id_of_source, str
* .value, float
* .min, float
* .max, float
* .is_discrete, bool
* .m, float
* .n, float
* .index_of_symbol, int
* .cost, float, cost of changing (for Volt-Var-control)
* .get_groups: function (iterable_of_int) -> (pandas.DataFrame)
pandas.DataFrame(index: ('step', 'id'))
* .type, 'var'|'const', type of factor decision
variable or parameter
* .id_of_source, str, id of factor (previous optimization step)
for initialization
* .value, float, used by initialization if no source factor
in previous optimization step
* .min, float
smallest possible value
* .max, float
greatest possible value
* .is_discrete, bool
just 0 digits after decimal point if True, input for solver,
accepted by MINLP solvers
* .m, float
increase of multiplier with respect to change of var/const
the effective multiplier is a linear
function of var/const (mx + n)
* .n, float
multiplier when var/const is 0.
the effective multiplier is a linear function of
var/const (mx + n)
* .cost, float, cost of changing (for Volt-Var-control)
* .get_injfactorgroups: function (iterable_of_int) -> (pandas.DataFrame)
pandas.DataFrame (index: ('step', 'id_of_injection', 'part'))
* .id, str, ID of factor
mnodeinj: scipy.sparse.csc_matrix
converts a vector ordered according to injection indices to a vector
ordered according to power flow calculation nodes (adding values of
injections for each node) by calculating 'mnodeinj @ vector'
terms: pandas.DataFrame
* .id, str, unique identifier
* .args, list of strings, arguments for function
* .fn, str, identifier of function
* .weight, float, multiplier for term in objective function
* .step, int
messages: pandas.DataFrame
* .message, str, message on reason of error
* .level, int, 0 - information, 1 - warning. 2 - error
Making a Model
Function model_from_frames consumes a dictionary of pandas.DataFrames. model_from_frames aggregates nodes connected without impedance, creates indices, arranges data per branch-terminal from branch-data, calculates values of branches from admittances.
Function make_model generates a model from network device objects defined in egrid.builder.
Example - 3 nodes, 2 lines, 1 consumer:
node: 0 1 2
| line | line |
+-----=====-----+-----=====-----+
| | |
\|/ consumer
Python code for example, suitable input for function egrid.make_model (Branchtap is for demo only, it is used with transformers, however, transformers/transformerwindings are modeled using class Branch too.):
from egrid.builder import (
Slacknode, PValue, QValue, IValue, Output, Branch,
Injection, Defk, Deft, Klink, Tlink)
example = [
Slacknode(id_of_node='n_0', V=1.+0.j),
PValue(
id_of_batch='pq_line_0',
P=30.),
QValue(
id_of_batch='pq_line_0',
Q=8.),
Output(
id_of_batch='pq_line_0',
id_of_node='n_0',
id_of_device='line_0'),
IValue(
id_of_batch='i_line_0',
I=40.0),
Output(
id_of_batch='i_line_0',
id_of_node='n_0',
id_of_device='line_0'),
Branch(
id='line_0',
id_of_node_A='n_0',
id_of_node_B='n_1',
y_lo=1e3-1e3j,
y_tr=1e-6+1e-6j),
Branchtaps(
id='taps_0',
id_of_node='n_0',
id_of_branch='line_0',
Vstep=.1/16,
positionmin=-16,
positionneutral=0,
positionmax=16,
position=0),
Branch(
id='line_1',
id_of_node_A='n_1',
id_of_node_B='n_2',
y_lo=1e3-1e3j,
y_tr=1e-6+1e-6j),
Output(
id_of_batch='pq_consumer_0',
id_of_device='consumer_0'),
Output(
id_of_batch='i_consumer_0',
id_of_device='consumer_0'),
Injection(
id='consumer_0',
id_of_node='n_2',
P10=30.0,
Q10=10.0,
Exp_v_p=2.0,
Exp_v_q=2.0),
Defk(step=(0, 1, 2), id=('kp', 'kq')),
Klink(
step=(0, 1, 2), objid='consumer_0', part=('p', 'q'), id=('kp', 'kq'))]
Valid input to make_model is a multiline pseudo graphic string e.g. this one:
y_tr=1e-6+1e-6j y_tr=1e-6+1e-6j
slack=True y_lo=1e3-1e3j y_lo=1e3-1e3j
n0(---------- line_0 ----------)n1(---------- line_1 ----------)n2
| |
n1->> load0_1_ _load1 <<-n2->> load1_1_
| P10=30.0 P10=20.7 P10=4.3
| Q10=5 Q10=5.7 Q10=2
|
| y_lo=1e3-1e3j
| y_tr=1e-6+1e-6j
n1(---------- line_2 ----------)n3
|
_load2 <<-n3->> load2_1_
P10=20.7 P10=20
Q10=5.7 Q10=5.7
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file egrid-0.0.7.tar.gz
.
File metadata
- Download URL: egrid-0.0.7.tar.gz
- Upload date:
- Size: 51.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | cacc446a6538bf6ff38b0e017f43b8667a4750fdbda7f1943dd965290642bd15 |
|
MD5 | 1c5f548aa1ff998b0c8e6f444534efb7 |
|
BLAKE2b-256 | c0d70ec4398183fb16c45f2875e7849384b80363308c0a470aa55935387730a0 |
File details
Details for the file egrid-0.0.7-py3-none-any.whl
.
File metadata
- Download URL: egrid-0.0.7-py3-none-any.whl
- Upload date:
- Size: 53.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.11
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 71ebda63a1a01bb8d5f51f50f6d1791cfcaf72d272448c2b6def11332f62e755 |
|
MD5 | 92da3c43f5392fd811b08753c338ce1e |
|
BLAKE2b-256 | 21168f2c4b24accf355481239a61319696ec63671bf21c3b6802775dd5f83ebf |