1 # Copyright (C) 2010-2011 Richard Lincoln
3 # Permission is hereby granted, free of charge, to any person obtaining a copy
4 # of this software and associated documentation files (the "Software"), to
5 # deal in the Software without restriction, including without limitation the
6 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 # sell copies of the Software, and to permit persons to whom the Software is
8 # furnished to do so, subject to the following conditions:
10 # The above copyright notice and this permission notice shall be included in
11 # all copies or substantial portions of the Software.
13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 from CIM14
.IEC61970
.Core
.Equipment
import Equipment
23 class GeneratingUnit(Equipment
):
24 """A single or set of synchronous machines for converting mechanical power into alternating-current power. For example, individual machines within a set may be defined for scheduling purposes while a single control signal is derived for the set. In this case there would be a GeneratingUnit for each member of the set and an additional GeneratingUnit corresponding to the set.
27 def __init__(self
, genControlMode
="setpoint", genOperatingMode
="fixed", genControlSource
="unavailable", startupTime
=0.0, minimumOffTime
=0.0, spinReserveRamp
=0.0, controlDeadband
=0.0, maxOperatingP
=0.0, fastStartFlag
=False, lowControlLimit
=0.0, baseP
=0.0, maxEconomicP
=0.0, efficiency
=0.0, shortPF
=0.0, lowerRampRate
=0.0, stepChange
=0.0, penaltyFactor
=0.0, longPF
=0.0, ratedGrossMinP
=0.0, ratedGrossMaxP
=0.0, dispReserveFlag
=False, variableCost
=0.0, modelDetail
=0, energyMinP
=0.0, maximumAllowableSpinningReserve
=0.0, fuelPriority
=0, raiseRampRate
=0.0, nominalP
=0.0, normalPF
=0.0, governorMPL
=0.0, ratedNetMaxP
=0.0, controlResponseRate
=0.0, tieLinePF
=0.0, governorSCD
=0.0, controlPulseLow
=0.0, highControlLimit
=0.0, initialP
=0.0, minEconomicP
=0.0, autoCntrlMarginP
=0.0, allocSpinResP
=0.0, startupCost
=0.0, minOperatingP
=0.0, controlPulseHigh
=0.0, SynchronousMachines
=None, GrossToNetActivePowerCurves
=None, GenUnitOpCostCurves
=None, GenUnitOpSchedule
=None, ControlAreaGeneratingUnit
=None, *args
, **kw_args
):
28 """Initialises a new 'GeneratingUnit' instance.
30 @param genControlMode: The unit control mode. Values are: "setpoint", "pulse"
31 @param genOperatingMode: Operating mode for secondary control. Values are: "fixed", "EDC", "manual", "off", "MRN", "LFC", "AGC", "REG"
32 @param genControlSource: The source of controls for a generating unit. Values are: "unavailable", "onAGC", "plantControl", "offAGC"
33 @param startupTime: Time it takes to get the unit on-line, from the time that the prime mover mechanical power is applied
34 @param minimumOffTime: Minimum time interval between unit shutdown and startup
35 @param spinReserveRamp:
36 @param controlDeadband: Unit control error deadband. When a unit's desired active power change is less than this deadband, then no control pulses will be sent to the unit.
37 @param maxOperatingP: This is the maximum operating active power limit the dispatcher can enter for this unit
39 @param lowControlLimit: Low limit for secondary (AGC) control
40 @param baseP: For dispatchable units, this value represents the economic active power basepoint, for units that are not dispatchable, this value represents the fixed generation value. The value must be between the operating low and high limits.
41 @param maxEconomicP: Maximum high economic active power limit, that should not exceed the maximum operating active power limit
42 @param efficiency: The efficiency of the unit in converting mechanical energy, from the prime mover, into electrical energy.
43 @param shortPF: Generating unit economic participation factor
46 @param penaltyFactor: Defined as: 1 / ( 1 - Incremental Transmission Loss); with the Incremental Transmission Loss expressed as a plus or minus value. The typical range of penalty factors is (0.9 to 1.1).
47 @param longPF: Generating unit economic participation factor
48 @param ratedGrossMinP: The gross rated minimum generation level which the unit can safely operate at while delivering power to the transmission grid
49 @param ratedGrossMaxP: The unit's gross rated maximum capacity (Book Value).
50 @param dispReserveFlag:
51 @param variableCost: The variable cost component of production per unit of ActivePower.
52 @param modelDetail: Detail level of the generator model data
54 @param maximumAllowableSpinningReserve: Maximum allowable spinning reserve. Spinning reserve will never be considered greater than this value regardless of the current operating point.
57 @param nominalP: The nominal power of the generating unit. Used to give precise meaning to percentage based attributes such as the govenor speed change droop (govenorSCD attribute).
58 @param normalPF: Generating unit economic participation factor
59 @param governorMPL: Governor Motor Position Limit
60 @param ratedNetMaxP: The net rated maximum capacity determined by subtracting the auxiliary power used to operate the internal plant machinery from the rated gross maximum capacity
61 @param controlResponseRate: Unit response rate which specifies the active power change for a control pulse of one second in the most responsive loading level of the unit.
62 @param tieLinePF: Generating unit economic participation factor
63 @param governorSCD: Governor Speed Changer Droop. This is the change in generator power output divided by the change in frequency normalized by the nominal power of the generator and the nominal frequency and expressed in percent and negated. A positive value of speed change droop provides additional generator output upon a drop in frequency.
64 @param controlPulseLow: Pulse low limit which is the smallest control pulse that the unit can respond to
65 @param highControlLimit: High limit for secondary (AGC) control
66 @param initialP: Default Initial active power which is used to store a powerflow result for the initial active power for this unit in this network configuration
67 @param minEconomicP: Low economic active power limit that must be greater than or equal to the minimum operating active power limit
68 @param autoCntrlMarginP: The planned unused capacity which can be used to support automatic control overruns.
69 @param allocSpinResP: The planned unused capacity (spinning reserve) which can be used to support emergency load
70 @param startupCost: The initial startup cost incurred for each start of the GeneratingUnit.
71 @param minOperatingP: This is the minimum operating active power limit the dispatcher can enter for this unit.
72 @param controlPulseHigh: Pulse high limit which is the largest control pulse that the unit can respond to
73 @param SynchronousMachines: A synchronous machine may operate as a generator and as such becomes a member of a generating unit
74 @param GrossToNetActivePowerCurves: A generating unit may have a gross active power to net active power curve, describing the losses and auxiliary power requirements of the unit
75 @param GenUnitOpCostCurves: A generating unit may have one or more cost curves, depending upon fuel mixture and fuel cost.
76 @param GenUnitOpSchedule: A generating unit may have an operating schedule, indicating the planned operation of the unit
77 @param ControlAreaGeneratingUnit: ControlArea specifications for this generating unit.
79 #: The unit control mode. Values are: "setpoint", "pulse"
80 self
.genControlMode
= genControlMode
82 #: Operating mode for secondary control. Values are: "fixed", "EDC", "manual", "off", "MRN", "LFC", "AGC", "REG"
83 self
.genOperatingMode
= genOperatingMode
85 #: The source of controls for a generating unit. Values are: "unavailable", "onAGC", "plantControl", "offAGC"
86 self
.genControlSource
= genControlSource
88 #: Time it takes to get the unit on-line, from the time that the prime mover mechanical power is applied
89 self
.startupTime
= startupTime
91 #: Minimum time interval between unit shutdown and startup
92 self
.minimumOffTime
= minimumOffTime
95 self
.spinReserveRamp
= spinReserveRamp
97 #: Unit control error deadband. When a unit's desired active power change is less than this deadband, then no control pulses will be sent to the unit.
98 self
.controlDeadband
= controlDeadband
100 #: This is the maximum operating active power limit the dispatcher can enter for this unit
101 self
.maxOperatingP
= maxOperatingP
104 self
.fastStartFlag
= fastStartFlag
106 #: Low limit for secondary (AGC) control
107 self
.lowControlLimit
= lowControlLimit
109 #: For dispatchable units, this value represents the economic active power basepoint, for units that are not dispatchable, this value represents the fixed generation value. The value must be between the operating low and high limits.
112 #: Maximum high economic active power limit, that should not exceed the maximum operating active power limit
113 self
.maxEconomicP
= maxEconomicP
115 #: The efficiency of the unit in converting mechanical energy, from the prime mover, into electrical energy.
116 self
.efficiency
= efficiency
118 #: Generating unit economic participation factor
119 self
.shortPF
= shortPF
122 self
.lowerRampRate
= lowerRampRate
125 self
.stepChange
= stepChange
127 #: Defined as: 1 / ( 1 - Incremental Transmission Loss); with the Incremental Transmission Loss expressed as a plus or minus value. The typical range of penalty factors is (0.9 to 1.1).
128 self
.penaltyFactor
= penaltyFactor
130 #: Generating unit economic participation factor
133 #: The gross rated minimum generation level which the unit can safely operate at while delivering power to the transmission grid
134 self
.ratedGrossMinP
= ratedGrossMinP
136 #: The unit's gross rated maximum capacity (Book Value).
137 self
.ratedGrossMaxP
= ratedGrossMaxP
140 self
.dispReserveFlag
= dispReserveFlag
142 #: The variable cost component of production per unit of ActivePower.
143 self
.variableCost
= variableCost
145 #: Detail level of the generator model data
146 self
.modelDetail
= modelDetail
149 self
.energyMinP
= energyMinP
151 #: Maximum allowable spinning reserve. Spinning reserve will never be considered greater than this value regardless of the current operating point.
152 self
.maximumAllowableSpinningReserve
= maximumAllowableSpinningReserve
155 self
.fuelPriority
= fuelPriority
158 self
.raiseRampRate
= raiseRampRate
160 #: The nominal power of the generating unit. Used to give precise meaning to percentage based attributes such as the govenor speed change droop (govenorSCD attribute).
161 self
.nominalP
= nominalP
163 #: Generating unit economic participation factor
164 self
.normalPF
= normalPF
166 #: Governor Motor Position Limit
167 self
.governorMPL
= governorMPL
169 #: The net rated maximum capacity determined by subtracting the auxiliary power used to operate the internal plant machinery from the rated gross maximum capacity
170 self
.ratedNetMaxP
= ratedNetMaxP
172 #: Unit response rate which specifies the active power change for a control pulse of one second in the most responsive loading level of the unit.
173 self
.controlResponseRate
= controlResponseRate
175 #: Generating unit economic participation factor
176 self
.tieLinePF
= tieLinePF
178 #: Governor Speed Changer Droop. This is the change in generator power output divided by the change in frequency normalized by the nominal power of the generator and the nominal frequency and expressed in percent and negated. A positive value of speed change droop provides additional generator output upon a drop in frequency.
179 self
.governorSCD
= governorSCD
181 #: Pulse low limit which is the smallest control pulse that the unit can respond to
182 self
.controlPulseLow
= controlPulseLow
184 #: High limit for secondary (AGC) control
185 self
.highControlLimit
= highControlLimit
187 #: Default Initial active power which is used to store a powerflow result for the initial active power for this unit in this network configuration
188 self
.initialP
= initialP
190 #: Low economic active power limit that must be greater than or equal to the minimum operating active power limit
191 self
.minEconomicP
= minEconomicP
193 #: The planned unused capacity which can be used to support automatic control overruns.
194 self
.autoCntrlMarginP
= autoCntrlMarginP
196 #: The planned unused capacity (spinning reserve) which can be used to support emergency load
197 self
.allocSpinResP
= allocSpinResP
199 #: The initial startup cost incurred for each start of the GeneratingUnit.
200 self
.startupCost
= startupCost
202 #: This is the minimum operating active power limit the dispatcher can enter for this unit.
203 self
.minOperatingP
= minOperatingP
205 #: Pulse high limit which is the largest control pulse that the unit can respond to
206 self
.controlPulseHigh
= controlPulseHigh
208 self
._SynchronousMachines
= []
209 self
.SynchronousMachines
= [] if SynchronousMachines
is None else SynchronousMachines
211 self
._GrossToNetActivePowerCurves
= []
212 self
.GrossToNetActivePowerCurves
= [] if GrossToNetActivePowerCurves
is None else GrossToNetActivePowerCurves
214 self
._GenUnitOpCostCurves
= []
215 self
.GenUnitOpCostCurves
= [] if GenUnitOpCostCurves
is None else GenUnitOpCostCurves
217 self
._GenUnitOpSchedule
= None
218 self
.GenUnitOpSchedule
= GenUnitOpSchedule
220 self
._ControlAreaGeneratingUnit
= []
221 self
.ControlAreaGeneratingUnit
= [] if ControlAreaGeneratingUnit
is None else ControlAreaGeneratingUnit
223 super(GeneratingUnit
, self
).__init
__(*args
, **kw_args
)
225 _attrs
= ["genControlMode", "genOperatingMode", "genControlSource", "startupTime", "minimumOffTime", "spinReserveRamp", "controlDeadband", "maxOperatingP", "fastStartFlag", "lowControlLimit", "baseP", "maxEconomicP", "efficiency", "shortPF", "lowerRampRate", "stepChange", "penaltyFactor", "longPF", "ratedGrossMinP", "ratedGrossMaxP", "dispReserveFlag", "variableCost", "modelDetail", "energyMinP", "maximumAllowableSpinningReserve", "fuelPriority", "raiseRampRate", "nominalP", "normalPF", "governorMPL", "ratedNetMaxP", "controlResponseRate", "tieLinePF", "governorSCD", "controlPulseLow", "highControlLimit", "initialP", "minEconomicP", "autoCntrlMarginP", "allocSpinResP", "startupCost", "minOperatingP", "controlPulseHigh"]
226 _attr_types
= {"genControlMode": str, "genOperatingMode": str, "genControlSource": str, "startupTime": float, "minimumOffTime": float, "spinReserveRamp": float, "controlDeadband": float, "maxOperatingP": float, "fastStartFlag": bool, "lowControlLimit": float, "baseP": float, "maxEconomicP": float, "efficiency": float, "shortPF": float, "lowerRampRate": float, "stepChange": float, "penaltyFactor": float, "longPF": float, "ratedGrossMinP": float, "ratedGrossMaxP": float, "dispReserveFlag": bool, "variableCost": float, "modelDetail": int, "energyMinP": float, "maximumAllowableSpinningReserve": float, "fuelPriority": int, "raiseRampRate": float, "nominalP": float, "normalPF": float, "governorMPL": float, "ratedNetMaxP": float, "controlResponseRate": float, "tieLinePF": float, "governorSCD": float, "controlPulseLow": float, "highControlLimit": float, "initialP": float, "minEconomicP": float, "autoCntrlMarginP": float, "allocSpinResP": float, "startupCost": float, "minOperatingP": float, "controlPulseHigh": float}
227 _defaults
= {"genControlMode": "setpoint", "genOperatingMode": "fixed", "genControlSource": "unavailable", "startupTime": 0.0, "minimumOffTime": 0.0, "spinReserveRamp": 0.0, "controlDeadband": 0.0, "maxOperatingP": 0.0, "fastStartFlag": False, "lowControlLimit": 0.0, "baseP": 0.0, "maxEconomicP": 0.0, "efficiency": 0.0, "shortPF": 0.0, "lowerRampRate": 0.0, "stepChange": 0.0, "penaltyFactor": 0.0, "longPF": 0.0, "ratedGrossMinP": 0.0, "ratedGrossMaxP": 0.0, "dispReserveFlag": False, "variableCost": 0.0, "modelDetail": 0, "energyMinP": 0.0, "maximumAllowableSpinningReserve": 0.0, "fuelPriority": 0, "raiseRampRate": 0.0, "nominalP": 0.0, "normalPF": 0.0, "governorMPL": 0.0, "ratedNetMaxP": 0.0, "controlResponseRate": 0.0, "tieLinePF": 0.0, "governorSCD": 0.0, "controlPulseLow": 0.0, "highControlLimit": 0.0, "initialP": 0.0, "minEconomicP": 0.0, "autoCntrlMarginP": 0.0, "allocSpinResP": 0.0, "startupCost": 0.0, "minOperatingP": 0.0, "controlPulseHigh": 0.0}
228 _enums
= {"genControlMode": "GeneratorControlMode", "genOperatingMode": "GeneratorOperatingMode", "genControlSource": "GeneratorControlSource"}
229 _refs
= ["SynchronousMachines", "GrossToNetActivePowerCurves", "GenUnitOpCostCurves", "GenUnitOpSchedule", "ControlAreaGeneratingUnit"]
230 _many_refs
= ["SynchronousMachines", "GrossToNetActivePowerCurves", "GenUnitOpCostCurves", "ControlAreaGeneratingUnit"]
232 def getSynchronousMachines(self
):
233 """A synchronous machine may operate as a generator and as such becomes a member of a generating unit
235 return self
._SynchronousMachines
237 def setSynchronousMachines(self
, value
):
238 for x
in self
._SynchronousMachines
:
239 x
.GeneratingUnit
= None
241 y
._GeneratingUnit
= self
242 self
._SynchronousMachines
= value
244 SynchronousMachines
= property(getSynchronousMachines
, setSynchronousMachines
)
246 def addSynchronousMachines(self
, *SynchronousMachines
):
247 for obj
in SynchronousMachines
:
248 obj
.GeneratingUnit
= self
250 def removeSynchronousMachines(self
, *SynchronousMachines
):
251 for obj
in SynchronousMachines
:
252 obj
.GeneratingUnit
= None
254 def getGrossToNetActivePowerCurves(self
):
255 """A generating unit may have a gross active power to net active power curve, describing the losses and auxiliary power requirements of the unit
257 return self
._GrossToNetActivePowerCurves
259 def setGrossToNetActivePowerCurves(self
, value
):
260 for x
in self
._GrossToNetActivePowerCurves
:
261 x
.GeneratingUnit
= None
263 y
._GeneratingUnit
= self
264 self
._GrossToNetActivePowerCurves
= value
266 GrossToNetActivePowerCurves
= property(getGrossToNetActivePowerCurves
, setGrossToNetActivePowerCurves
)
268 def addGrossToNetActivePowerCurves(self
, *GrossToNetActivePowerCurves
):
269 for obj
in GrossToNetActivePowerCurves
:
270 obj
.GeneratingUnit
= self
272 def removeGrossToNetActivePowerCurves(self
, *GrossToNetActivePowerCurves
):
273 for obj
in GrossToNetActivePowerCurves
:
274 obj
.GeneratingUnit
= None
276 def getGenUnitOpCostCurves(self
):
277 """A generating unit may have one or more cost curves, depending upon fuel mixture and fuel cost.
279 return self
._GenUnitOpCostCurves
281 def setGenUnitOpCostCurves(self
, value
):
282 for x
in self
._GenUnitOpCostCurves
:
283 x
.GeneratingUnit
= None
285 y
._GeneratingUnit
= self
286 self
._GenUnitOpCostCurves
= value
288 GenUnitOpCostCurves
= property(getGenUnitOpCostCurves
, setGenUnitOpCostCurves
)
290 def addGenUnitOpCostCurves(self
, *GenUnitOpCostCurves
):
291 for obj
in GenUnitOpCostCurves
:
292 obj
.GeneratingUnit
= self
294 def removeGenUnitOpCostCurves(self
, *GenUnitOpCostCurves
):
295 for obj
in GenUnitOpCostCurves
:
296 obj
.GeneratingUnit
= None
298 def getGenUnitOpSchedule(self
):
299 """A generating unit may have an operating schedule, indicating the planned operation of the unit
301 return self
._GenUnitOpSchedule
303 def setGenUnitOpSchedule(self
, value
):
304 if self
._GenUnitOpSchedule
is not None:
305 self
._GenUnitOpSchedule
._GeneratingUnit
= None
307 self
._GenUnitOpSchedule
= value
308 if self
._GenUnitOpSchedule
is not None:
309 self
._GenUnitOpSchedule
.GeneratingUnit
= None
310 self
._GenUnitOpSchedule
._GeneratingUnit
= self
312 GenUnitOpSchedule
= property(getGenUnitOpSchedule
, setGenUnitOpSchedule
)
314 def getControlAreaGeneratingUnit(self
):
315 """ControlArea specifications for this generating unit.
317 return self
._ControlAreaGeneratingUnit
319 def setControlAreaGeneratingUnit(self
, value
):
320 for x
in self
._ControlAreaGeneratingUnit
:
321 x
.GeneratingUnit
= None
323 y
._GeneratingUnit
= self
324 self
._ControlAreaGeneratingUnit
= value
326 ControlAreaGeneratingUnit
= property(getControlAreaGeneratingUnit
, setControlAreaGeneratingUnit
)
328 def addControlAreaGeneratingUnit(self
, *ControlAreaGeneratingUnit
):
329 for obj
in ControlAreaGeneratingUnit
:
330 obj
.GeneratingUnit
= self
332 def removeControlAreaGeneratingUnit(self
, *ControlAreaGeneratingUnit
):
333 for obj
in ControlAreaGeneratingUnit
:
334 obj
.GeneratingUnit
= None