def consistencyCheckP4(self, state): """ This consistency rule checks that the voltage and current at the start of a line is the same as at the end. :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P4", indentation=3) passed = True for l in self.getAllConnectedLines(): try: localVoltage = l.retrieveValue(state, self, "local", "voltage") localCurrent = l.retrieveValue(state, self, "local", "current") remoteVoltage = l.retrieveValue(state, self, "remote", "voltage") remoteCurrent = l.retrieveValue(state, self, "remote", "current") currentPassed = isClose(localVoltage, remoteVoltage) and isClose( localCurrent, remoteCurrent) passed = False if not currentPassed else passed logDebugCheckValues( "Line %s. Local: V=%f,A=%f (==) Remote: V=%f,A=%f." % (l.name, localVoltage, localCurrent, remoteVoltage, remoteCurrent), currentPassed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, l.name, indentation=3)
def consistencyCheckP7(self, state): """ This consistency rule checks whether the transformer has a rate function defined :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P7", indentation=3) passed = False if callable(self.rateFunction): try: currentTapPosition = state.retrieveValue(self.tapPositionKey) try: currentTransformerRate = self.rateFunction( currentTapPosition) passed = True logDebugCheckValues( "Transformer %s. Transformer rate function defined, tap position valid." % (self.name), passed, indentation=3) except: passed = False logDebugCheckValues( "Transformer %s. Transformer rate function defined, but tap position invalid." % (self.name), passed, indentation=3) except ValueNotStoredException, e: passed = True logDebugUnknownValues(e.message, indentation=3)
def consistencyCheckP2(self, state): """ This consistency rule checks whether the voltage equals on all meters of a bus. Meters with V=0 are excluded as they might be disconnected. :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P2", indentation=3) passed = True try: # check if all measured voltages on bus are approximately equal (or 0 V) allMeasuredVoltages = [ l.retrieveValue(state, self, "local", "voltage") for l in self.getAllConnectedLines() ] relevantMeasuredVoltages = [ v for v in allMeasuredVoltages if not isClose(v, 0.00) ] passed = isClose(min(relevantMeasuredVoltages), max(relevantMeasuredVoltages)) logDebugCheckValues( "Minimum V: %f (==) Maximum V: %f." % (min(relevantMeasuredVoltages), max(relevantMeasuredVoltages)), passed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, indentation=3)
def safetyCheckR8a(self, state): """ This safety rule checks whether the voltage set points are safe :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R8a", indentation=3) passed = True for l in self.getAllConnectedLines(): try: localVoltageSetPoint = l.retrieveValue(state, self, "local", "setPointV") allowedSetPointInterval = (l.nominalV * 0.90, l.nominalV * 1.10) currentPassed = allowedSetPointInterval[ 0] <= localVoltageSetPoint <= allowedSetPointInterval[1] passed = False if not currentPassed else passed logDebugCheckValues( "Line %s. Voltage set point = %fV (in [%5.2f,%5.2f]V)." % (l.name, localVoltageSetPoint, allowedSetPointInterval[0], allowedSetPointInterval[1]), currentPassed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, l.name, indentation=3)
def safetyCheckR2(self, state): """ This safety rule checks that the voltage is within its allowed interval around the nominal voltage :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R2", indentation=3) passed = True for l in self.getAllConnectedLines(): try: safeInterval = (l.nominalV * (1 - l.voltageBoundaryFactor), l.nominalV * (1 + l.voltageBoundaryFactor)) localVoltage = l.retrieveValue(state, self, "local", "voltage") if not isZero(localVoltage): currentPassed = safeInterval[ 0] <= localVoltage <= safeInterval[1] passed = False if not currentPassed else passed logDebugCheckValues( "Line %s. Local: V=%f (in [%3.2f;%3.2f])." % (l.name, localVoltage, safeInterval[0], safeInterval[1]), currentPassed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, l.name, indentation=3)
def consistencyCheckP1(self, state): """ This consistency rule checks whether Kirchhoff's current law holds at the bus. :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P1", indentation=3) passed = True try: # compare sum of ingoing current with sum of outgoing current sumOfIngoingCurrent = sum([ l.retrieveValue(state, self, "local", "current") for l in self.linesIn ]) sumOfOutgoingCurrent = sum([ l.retrieveValue(state, self, "local", "current") for l in self.linesOut ]) passed = isClose(sumOfIngoingCurrent, sumOfOutgoingCurrent) logDebugCheckValues( "Ingoing current: %f (==) Outgoing current: %f." % (sumOfIngoingCurrent, sumOfOutgoingCurrent), passed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, indentation=3)
def safetyCheckR4(self, state): """ This safety rule checks whether all lines connected to fuses and protective relays have current below the cutting current :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R4", indentation=3) passed = True for l in self.getAllConnectedLines(): localFuse = l.getLocalComponent(self, "local", "fuse") if localFuse: try: currentNow = localFuse.connectedLine.retrieveValue( state, self, "local", "current") if currentNow > localFuse.cuttingI: try: localMeter = l.getLocalComponent( self, "local", "meter") currentFuseDelayAgo = state.retrieveValueBefore( localMeter.currentKey, time.time() - localFuse.cuttingT) if currentFuseDelayAgo > localFuse.cuttingI: currentPassed = False logDebugCheckValues( "Line %s. Fuse found. Fuse broken? Current over %d seconds (fuse delay) above fuse current limit (%f < %f)." % (l.name, localFuse.cuttingT, currentNow, localFuse.cuttingI), currentPassed, indentation=3) else: currentPassed = False logDebugCheckValues( "Line %s. Fuse found. Current not okay (%f < %f), but was okay before fuse delay (%d seconds ago)." % (l.name, currentNow, localFuse.cuttingI, localFuse.cuttingT), currentPassed, indentation=3) except ValueNotStoredException, e: currentPassed = False logDebugCheckValues( "Line %s. Fuse found. Current not okay (%f < %f). Current %d seconds ago unknown." % (l.name, currentNow, localFuse.cuttingI, localFuse.cuttingT), currentPassed, indentation=3) else: currentPassed = True logDebugCheckValues( "Line %s. Fuse found. Current okay (%f < %f)." % (l.name, currentNow, localFuse.cuttingI), currentPassed, indentation=3) except ValueNotStoredException, e: currentPassed = True logDebugUnknownValues(e.message, l.name, indentation=3) logDebugCheckValues( "Line %s. Fuse found. Current unknown." % (l.name), currentPassed, indentation=3)
def safetyCheckR5b(self, state): """ This safety rule checks whether the transformer rate is safe on actual voltage :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R5b", indentation=3) passed = True if callable(self.rateFunction): try: measuredInVoltage = self.linesIn[0].retrieveValue( state, self, "local", "voltage") nominalOutVoltage = self.linesOut[0].nominalV currentTapPosition = state.retrieveValue(self.tapPositionKey) if isZero(measuredInVoltage): currentPassed = True passed = False if not currentPassed else passed logDebugCheckValues( "Transformer %s. Actual input voltage: %fV. Nominal output voltage: %fV. Input voltage is zero." % (self.name, measuredInVoltage, nominalOutVoltage), currentPassed, indentation=3) else: try: currentTransformerRate = self.rateFunction( currentTapPosition) actualTransformedOutVoltage = measuredInVoltage / float( currentTransformerRate) nominalSafeInterval = ( nominalOutVoltage * (1 - self.linesOut[0].voltageBoundaryFactor), nominalOutVoltage * (1 + self.linesOut[0].voltageBoundaryFactor)) if nominalSafeInterval[ 0] <= actualTransformedOutVoltage <= nominalSafeInterval[ 1]: currentPassed = True else: currentPassed = False passed = False if not currentPassed else passed logDebugCheckValues( "Transformer %s. Actual input voltage: %fV. Nominal output voltage: %fV. Transformed actual output voltage: %fV (should be in [%3.2f;%3.2f])." % (self.name, measuredInVoltage, nominalOutVoltage, actualTransformedOutVoltage, nominalSafeInterval[0], nominalSafeInterval[1]), currentPassed, indentation=3) except IndexError: currentPassed = False passed = False if not currentPassed else passed logDebugCheckValues( "Transformer %s. Discrete tap function, tap position %d has no rate defined." % (self.name, int(round(currentTapPosition))), currentPassed, indentation=3) except ValueNotStoredException, e: passed = True logDebugUnknownValues(e.message, indentation=3)
def consistencyCheckP6b(self, state): """ This consistency rule checks whether the transformation rate is consistent with the current measurement. :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P6b", indentation=3) passed = True if callable(self.rateFunction): try: measuredInCurrent = self.linesIn[0].retrieveValue( state, self, "local", "current") measuredOutCurrent = self.linesOut[0].retrieveValue( state, self, "local", "current") currentTapPosition = state.retrieveValue(self.tapPositionKey) if isZero(measuredInCurrent): passed = True logDebugCheckValues( "Transformer %s. No incoming or outgoing current." % (self.name), passed, indentation=3) else: try: currentTransformerRate = self.rateFunction( currentTapPosition) expectedMeasuredTransformedOutCurrent = measuredInCurrent * float( currentTransformerRate) if isClose(expectedMeasuredTransformedOutCurrent, measuredOutCurrent): passed = True else: passed = False logDebugCheckValues( "Transformer %s. Measured input current: %fA. Measured output current: %fA. Expected output current: %fA." % (self.name, measuredInCurrent, measuredOutCurrent, expectedMeasuredTransformedOutCurrent), passed, indentation=3) except IndexError: passed = False logDebugCheckValues( "Transformer %s. Discrete tap function, tap position %d has no rate defined." % (self.name, int(round(currentTapPosition))), passed, indentation=3) except ZeroDivisionError: passed = False logDebugCheckValues( "Transformer %s. Measured input current: %fA. Measured output current: %fA. (Division by zero, not consistent)." % (self.name, measuredInCurrent, measuredOutCurrent), passed, indentation=3) except ValueNotStoredException, e: passed = True logDebugUnknownValues(e.message, indentation=3)
def safetyCheckR9a(self, state): """ This safety rule checks that static interlocks are not violated. :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R9a", indentation=3) passed = True for l in self.getAllConnectedLines(): try: localSwitch = l.getLocalComponent(self, "local", "switch") if not l.retrieveValue(state, self, "local", "switchState"): if localSwitch and localSwitch.interlocks: for interlock in localSwitch.interlocks: if isinstance(interlock, StaticInterlock): try: switchStates = [ state.retrieveValue(s.stateKey) for s in interlock.interlockedSwitches ] if sum( switchStates ) >= interlock.guaranteedClosedSwitches: currentPassed = True else: currentPassed = False passed = False if not currentPassed else passed logDebugCheckValues( "Open switch on line %s. Switch is interlocked. Interlock switch states: %s (>= %d)." % (l.name, str(switchStates), interlock.guaranteedClosedSwitches), currentPassed, indentation=3) except ValueNotStoredException, e: currentPassed = True logDebugUnknownValues(e.message, l.name, indentation=3) else: currentPassed = True logDebugCheckValues( "Open switch %s found at Bus %s, but no interlocks defined for that switch." % (localSwitch.name, self.name), currentPassed, indentation=3) else: currentPassed = True logDebugCheckValues("Local switch %s at Bus %s closed." % (localSwitch.name, self.name), currentPassed, indentation=3)
def consistencyCheckP6a(self, state): """ This consistency rule checks whether the transformation rate is consistent with the voltage measurement. :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P6a", indentation=3) passed = True if callable(self.rateFunction): try: measuredInVoltage = self.linesIn[0].retrieveValue( state, self, "local", "voltage") measuredOutVoltage = self.linesOut[0].retrieveValue( state, self, "local", "voltage") currentTapPosition = state.retrieveValue(self.tapPositionKey) if isZero(measuredOutVoltage): passed = True logDebugCheckValues( "Transformer %s. Measured input voltage: %fV. Measured output voltage: %fV. Output voltage zero!" % (self.name, measuredInVoltage, measuredOutVoltage), passed, indentation=3) else: try: currentTransformerRate = self.rateFunction( currentTapPosition) expectedMeasuredTransformedOutVoltage = measuredInVoltage / float( currentTransformerRate) if isClose(expectedMeasuredTransformedOutVoltage, measuredOutVoltage): passed = True else: passed = False logDebugCheckValues( "Transformer %s. Measured input voltage: %fV. Measured output voltage: %fV. Expected output voltage: %fV." % (self.name, measuredInVoltage, measuredOutVoltage, expectedMeasuredTransformedOutVoltage), passed, indentation=3) except IndexError: passed = False logDebugCheckValues( "Transformer %s. Discrete tap function, tap position %d has no rate defined. " % (self.name, int(round(currentTapPosition))), passed, indentation=3) except ValueNotStoredException, e: passed = True logDebugUnknownValues(e.message, indentation=3)
def safetyCheckR7(self, state): """ This safety rule checks whether the global generated power equals the global consumed power :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R7", indentation=2) passed = True try: sumOfGeneratedPower = sum( [state.retrieveValue(g.generatedPowerKey) for g in getAllComponentsOfType(Generator)]) sumOfConsumedPower = (-1) * sum( [state.retrieveValue(c.consumedPowerKey) for c in getAllComponentsOfType(Consumer)]) passed = isClose(sumOfGeneratedPower, sumOfConsumedPower) logDebugCheckValues("Global Generated power: %f (==) Global Consumed power: %f." % (sumOfGeneratedPower, sumOfConsumedPower), passed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, indentation=3)
def safetyCheckR6(self, state): """ This safety rule checks whether all consumers are connected to the power grid :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R6", indentation=2) passed = True for l in getAllComponentsOfType(Consumer): if len(l.linesIn) == 0: try: consumedPower = (-1) * state.retrieveValue(l.consumedPowerKey) if isZero(consumedPower): currentPassed = True passed = False if not currentPassed else passed logDebugCheckValues("Consumer %s connected to no line, and no power consumed. %fW" % (l.name, consumedPower), currentPassed, indentation=3) else: currentPassed = False passed = False if not currentPassed else passed logDebugCheckValues("Consumer %s connected to no line, but power consumed. %fW" % (l.name, consumedPower), currentPassed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, l.name, indentation=3) elif len(l.linesIn) == 1: try: consumedPower = (-1) * state.retrieveValue(l.consumedPowerKey) localVoltage = l.linesIn[0].retrieveValue(state, l, "local", "voltage") localSwitch = l.linesIn[0].retrieveValue(state, l, "local", "switchState") remoteSwitch = l.linesIn[0].retrieveValue(state, l, "remote", "switchState") currentPassed = localSwitch and remoteSwitch and not isZero(localVoltage) passed = False if not currentPassed else passed logDebugCheckValues("Consumer %s connected to power supply. Local Switch: %s (== True). Remote Switch: %s (== True). V=%f (>0) P=%fW." % (l.name, localSwitch, remoteSwitch, localVoltage, consumedPower), currentPassed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, l.name, indentation=3) try: consumedPower = (-1) * state.retrieveValue(l.consumedPowerKey) localVoltage = l.linesIn[0].retrieveValue(state, l, "local", "voltage") localSwitch = l.linesIn[0].retrieveValue(state, l, "local", "switchState") currentPassed = localSwitch and not isZero(localVoltage) passed = False if not currentPassed else passed logDebugCheckValues("Consumer %s connected to power supply. Local Switch: %s (== True). Remote Switch unknown. V=%f (>0) P=%fW." % (l.name, localSwitch, localVoltage, consumedPower), currentPassed, indentation=3) except ValueNotStoredException, e: pass
def safetyCheckR1(self, state): """ This safety rule checks that the current is below the maximal safe current threshold for a power line :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R1", indentation=3) passed = True for l in self.getAllConnectedLines(): try: localCurrent = l.retrieveValue(state, self, "local", "current") currentPassed = localCurrent <= l.maxI passed = False if not currentPassed else passed logDebugCheckValues("Line %s. A=%f (<= maxI = %f)." % (l.name, localCurrent, l.maxI), currentPassed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, l.name, indentation=3)
def consistencyCheckP5b(self, state): """ This consistency rule checks whether P = I * V holds for the consumer. :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P5b", indentation=3) passed = True try: l = self.linesIn[0] localVoltage = l.retrieveValue(state, self, "local", "voltage") localCurrent = l.retrieveValue(state, self, "local", "current") calculatedPower = localVoltage * localCurrent consumedPower = (-1) * state.retrieveValue(self.consumedPowerKey) passed = isClose(calculatedPower, consumedPower) logDebugCheckValues("Consumer %s. V=%f,A=%f. V*A=%f (==) P=%f." % (self.name, localVoltage, localCurrent, calculatedPower, consumedPower), passed, indentation=3) except ValueNotStoredException, e: logDebugUnknownValues(e.message, indentation=3)
def consistencyCheckP3(self, state): """ This consistency rule checks that the current is zero if a switch, fuse or protective relay has an open circuit. :param state: State object (observed or calculated) :return: True if consistency rule holds, False otherwise (violation) """ logCheckDescription("P3", indentation=3) passed = True openSwitchedLines = [] for l in self.getAllConnectedLines(): try: if l.getLocalComponent( self, "local", "switch") and not l.retrieveValue( state, self, "local", "switchState"): openSwitchedLines.append(l) elif l.getLocalComponent( self, "remote", "switch") and not l.retrieveValue( state, self, "remote", "switchState"): openSwitchedLines.append(l) elif l.getLocalComponent( self, "local", "fuse") and not l.retrieveValue( state, self, "local", "fuseState"): openSwitchedLines.append(l) elif l.getLocalComponent( self, "remote", "fuse") and not l.retrieveValue( state, self, "remote", "fuseState"): openSwitchedLines.append(l) elif l.getLocalComponent( self, "local", "protectiveRelay") and not l.retrieveValue( state, self, "local", "protectiveRelayState"): openSwitchedLines.append(l) elif l.getLocalComponent( self, "remote", "protectiveRelay") and not l.retrieveValue( state, self, "remote", "protectiveRelayState"): openSwitchedLines.append(l) except ValueNotStoredException, e: logDebugUnknownValues(e.message, l.name, indentation=3)
def safetyCheckR3(self, state): """ This safety rule checks whether all fuses and protective relays are closed. :param state: State object (observed or calculated) :return: True if safety rule holds, False otherwise (violation) """ logCheckDescription("R3", indentation=3) passed = True for l in self.getAllConnectedLines(): localFuse = l.getLocalComponent(self, "local", "fuse") if localFuse: try: fuseState = state.retrieveValue(localFuse.stateKey) if not fuseState: currentPassed = False logDebugCheckValues( "Line %s. Fuse found. Fuse molten." % (l.name), currentPassed, indentation=3) else: currentPassed = True logDebugCheckValues("Line %s. Fuse found. Fuse okay." % (l.name), currentPassed, indentation=3) except ValueNotStoredException, e: currentPassed = True logDebugUnknownValues(e.message, l.name, indentation=3) logDebugCheckValues( "Line %s. Fuse found. Fuse state unknown." % (l.name), currentPassed, indentation=3) else: currentPassed = True logDebugCheckValues("Line %s. No local fuse." % (l.name), currentPassed, indentation=3) passed = False if not currentPassed else passed localProtectiveRelay = l.getLocalComponent(self, "local", "protectiveRelay") if localProtectiveRelay: try: protectiveRelayState = state.retrieveValue( localProtectiveRelay.stateKey) if not protectiveRelayState: currentPassed = False logDebugCheckValues( "Line %s. Protective relay found. Protective relay open." % (l.name), currentPassed, indentation=3) else: currentPassed = True logDebugCheckValues( "Line %s. Protective relay found. Protective relay closed." % (l.name), currentPassed, indentation=3) except ValueNotStoredException, e: currentPassed = True logDebugUnknownValues(e.message, l.name, indentation=3) logDebugCheckValues( "Line %s. Protective relay found. Protective relay state unknown." % (l.name), currentPassed, indentation=3)