-
Notifications
You must be signed in to change notification settings - Fork 114
/
area.py
143 lines (109 loc) · 4.46 KB
/
area.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from collections import OrderedDict
from andes.core.discrete import Sampling
from andes.core.model import Model, ModelData
from andes.core.param import ExtParam, IdxParam, NumParam
from andes.core.service import BackRef, ConstService, DeviceFinder
from andes.core.var import Algeb, ExtAlgeb
from andes.utils.tab import Tab
class AreaData(ModelData):
def __init__(self):
super().__init__()
class Area(AreaData, Model):
"""
Area model.
Area collects back references from the Bus model and
the ACTopology group.
"""
def __init__(self, system, config):
AreaData.__init__(self)
Model.__init__(self, system, config)
self.group = 'Collection'
self.flags.pflow = True
self.flags.tds = True
self.Bus = BackRef()
self.ACTopology = BackRef()
def bus_table(self):
"""
Return a formatted table with area idx and bus idx correspondence
Returns
-------
str
Formatted table
"""
if self.n:
header = ['Area ID', 'Bus ID']
rows = [(i, j) for i, j in zip(self.idx.v, self.Bus.v)]
return Tab(header=header, data=rows).draw()
else:
return ''
class ACEData(ModelData):
"""
Area Control Error data
"""
def __init__(self):
ModelData.__init__(self)
self.bus = IdxParam(model='Bus', info="bus idx for freq. measurement", mandatory=True)
self.bias = NumParam(default=1.0, info='bias parameter', tex_name=r'\beta',
unit='MW/0.1Hz', power=True)
self.busf = IdxParam(info='Optional BusFreq device idx', model='BusFreq',
default=None)
class ACEc(ACEData, Model):
"""
Area Control Error model.
Continuous frequency sampling.
System base frequency from ``system.config.freq`` is used.
Note: area idx is automatically retrieved from `bus`.
"""
def __init__(self, system, config):
ACEData.__init__(self)
Model.__init__(self, system, config)
self.flags.tds = True
self.group = 'Calculation'
self.config.add(OrderedDict([('freq_model', 'BusFreq'),
]))
self.config.add_extra('_help',
{'freq_model': 'default freq. measurement model',
})
self.config.add_extra('_alt', {'freq_model': ('BusFreq',)})
self.area = ExtParam(model='Bus', src='area', indexer=self.bus, export=False)
self.busf.model = self.config.freq_model
self.busfreq = DeviceFinder(self.busf, link=self.bus, idx_name='bus',
default_model='BusFreq')
self.imva = ConstService(v_str='1/sys_mva', info='reciprocal of system mva',
tex_name='1/S_{b, sys}')
self.f = ExtAlgeb(model='FreqMeasurement',
src='f',
indexer=self.busfreq,
export=False,
info='Bus frequency',
unit='p.u. (Hz)'
)
self.ace = Algeb(info='area control error',
unit='p.u. (MW)',
tex_name='ace',
e_str='10 * (bias * imva) * sys_f * (f - 1) - ace',
)
class ACE(ACEc):
"""
Area Control Error model.
Discrete frequency sampling.
System base frequency from ``system.config.freq`` is used.
Frequency sampling period (in seconds) can be specified in
``ACE.config.interval``. The sampling start time (in seconds)
can be specified in ``ACE.config.offset``.
Note: area idx is automatically retrieved from `bus`.
"""
def __init__(self, system, config):
ACEc.__init__(self, system, config)
self.config.add(OrderedDict([('interval', 4.0),
('offset', 0.0),
]))
self.config.add_extra('_help', {'interval': 'sampling time interval',
'offset': 'sampling time offset'})
self.fs = Sampling(self.f,
interval=self.config.interval,
offset=self.config.offset,
tex_name='f_s',
info='Sampled freq.',
)
self.ace.e_str = '10 * (bias * imva) * sys_f * (fs_v - 1) - ace'