Source code for pypowsybl.security.impl.security

# Copyright (c) 2023, RTE (http://www.rte-france.com)
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
#
import warnings
from typing import Union, List
import pypowsybl.loadflow
from pypowsybl import _pypowsybl
from pypowsybl._pypowsybl import ContingencyContextType, ConditionType, ViolationType, Side
from pypowsybl._pypowsybl import PostContingencyComputationStatus as ComputationStatus
from pypowsybl.network import Network
from pypowsybl.report import ReportNode
from .parameters import Parameters
from .security_analysis_result import SecurityAnalysisResult
from .contingency_container import ContingencyContainer

ComputationStatus.__name__ = 'ComputationStatus'
ComputationStatus.__module__ = __name__


class SecurityAnalysis(ContingencyContainer):
    """
    Allows to run a security analysis on a network.
    """

    def __init__(self, handle: _pypowsybl.JavaHandle):
        ContingencyContainer.__init__(self, handle)

[docs] def run_ac(self, network: Network, parameters: Union[Parameters, pypowsybl.loadflow.Parameters] = None, provider: str = '', reporter: ReportNode = None, report_node: ReportNode = None) -> SecurityAnalysisResult: """ Runs an AC security analysis. Args: network: Network on which the security analysis will be computed parameters: Security analysis parameters provider: Name of the security analysis implementation provider to be used, will use default provider if empty. reporter: deprecated, use report_node instead report_node: the reporter to be used to create an execution report, default is None (no report) Returns: A security analysis result, containing information about violations and monitored elements """ if reporter is not None: warnings.warn("Use of deprecated attribute reporter. Use report_node instead.", DeprecationWarning) report_node = reporter security_parameters = Parameters(load_flow_parameters=parameters) if isinstance(parameters, pypowsybl.loadflow.Parameters) else parameters p = security_parameters._to_c_parameters() if security_parameters is not None else Parameters()._to_c_parameters() # pylint: disable=protected-access return SecurityAnalysisResult( _pypowsybl.run_security_analysis(self._handle, network._handle, p, provider, False, None if report_node is None else report_node._report_node)) # pylint: disable=protected-access
[docs] def run_dc(self, network: Network, parameters: Union[Parameters, pypowsybl.loadflow.Parameters] = None, provider: str = '', reporter: ReportNode = None, report_node: ReportNode = None) -> SecurityAnalysisResult: """ Runs a DC security analysis. Args: network: Network on which the security analysis will be computed parameters: Security analysis parameters provider: Name of the security analysis implementation provider to be used, will use default provider if empty. reporter: deprecated, use report_node instead report_node: the reporter to be used to create an execution report, default is None (no report) Returns: A security analysis result, containing information about violations and monitored elements """ if reporter is not None: warnings.warn("Use of deprecated attribute reporter. Use report_node instead.", DeprecationWarning) report_node = reporter security_parameters = Parameters(load_flow_parameters=parameters) if isinstance(parameters, pypowsybl.loadflow.Parameters) else parameters p = security_parameters._to_c_parameters() if security_parameters is not None else Parameters()._to_c_parameters() # pylint: disable=protected-access return SecurityAnalysisResult( _pypowsybl.run_security_analysis(self._handle, network._handle, p, provider, True, # pylint: disable=protected-access None if report_node is None else report_node._report_node)) # pylint: disable=protected-access
[docs] def add_monitored_elements(self, contingency_context_type: ContingencyContextType = ContingencyContextType.ALL, contingency_ids: Union[List[str], str] = None, branch_ids: List[str] = None, voltage_level_ids: List[str] = None, three_windings_transformer_ids: List[str] = None) -> None: """ Add elements to be monitored by the security analysis. The security analysis result will provide additional information for those elements, like the power and current values. Args: contingency_context_type: Defines if the elements should be monitored for all state, only N situation or only specific contingencies contingency_ids: list of contingencies for which we want to monitor additional elements branch_ids: list of branches to be monitored voltage_level_ids: list of voltage levels to be monitored three_windings_transformer_ids: list of 3 winding transformers to be monitored """ if contingency_context_type in (ContingencyContextType.ALL, ContingencyContextType.NONE) and contingency_ids: raise ValueError('Contingencies list must be empty when defining monitored elements ' 'for NONE or ALL contingencies') if three_windings_transformer_ids is None: three_windings_transformer_ids = [] if branch_ids is None: branch_ids = [] if voltage_level_ids is None: voltage_level_ids = [] if contingency_ids is None: contingency_ids = [''] elif isinstance(contingency_ids, str): contingency_ids = [contingency_ids] _pypowsybl.add_monitored_elements(self._handle, contingency_context_type, branch_ids, voltage_level_ids, three_windings_transformer_ids, contingency_ids)
[docs] def add_precontingency_monitored_elements(self, branch_ids: List[str] = None, voltage_level_ids: List[str] = None, three_windings_transformer_ids: List[str] = None) -> None: """ Add elements to be monitored by the security analysis on precontingency state. The security analysis result will provide additional information for those elements, like the power and current values. Args: branch_ids: list of branches to be monitored voltage_level_ids: list of voltage levels to be monitored three_windings_transformer_ids: list of 3 winding transformers to be monitored """ return self.add_monitored_elements(ContingencyContextType.NONE, branch_ids=branch_ids, voltage_level_ids=voltage_level_ids, three_windings_transformer_ids=three_windings_transformer_ids)
[docs] def add_postcontingency_monitored_elements(self, contingency_ids: Union[List[str], str], branch_ids: List[str] = None, voltage_level_ids: List[str] = None, three_windings_transformer_ids: List[str] = None) -> None: """ Add elements to be monitored by the security analysis for specific contingencies. The security analysis result will provide additional information for those elements, like the power and current values. Args: contingency_ids: list of contingencies for which we want to monitor additional elements branch_ids: list of branches to be monitored voltage_level_ids: list of voltage levels to be monitored three_windings_transformer_ids: list of 3 winding transformers to be monitored """ return self.add_monitored_elements(ContingencyContextType.SPECIFIC, contingency_ids, branch_ids, voltage_level_ids, three_windings_transformer_ids)
[docs] def add_load_active_power_action(self, action_id: str, load_id: str, is_relative: bool, active_power: float) -> None: """ Add a load action, modifying the load active power Args: action_id: unique ID for the action load_id: load identifier is_relative: whether the active power change specified is absolute, or relative to current load active power active_power: the active power change """ _pypowsybl.add_load_active_power_action(self._handle, action_id, load_id, is_relative, active_power)
[docs] def add_load_reactive_power_action(self, action_id: str, load_id: str, is_relative: bool, reactive_power: float) -> None: """ Add a load action, modifying the load reactive power Args: action_id: unique ID for the action load_id: load identifier is_relative: whether the reactive power change specified is absolute, or relative to current load reactive power reactive_power: the reactive power change """ _pypowsybl.add_load_reactive_power_action(self._handle, action_id, load_id, is_relative, reactive_power)
[docs] def add_generator_active_power_action(self, action_id: str, generator_id: str, is_relative: bool, active_power: float) -> None: """ Add a generator action, modifying the generator active power Args: action_id: unique ID for the action generator_id: generator identifier is_relative: whether the active power change specified is absolute, or relative to current generator active power active_power: the active power change """ _pypowsybl.add_generator_active_power_action(self._handle, action_id, generator_id, is_relative, active_power)
[docs] def add_switch_action(self, action_id: str, switch_id: str, open: bool) -> None: """ Add a switch action, modifying the switch open/close status Args: action_id: unique ID for the action switch_id: switch identifier open: True to open the switch, False to close """ _pypowsybl.add_switch_action(self._handle, action_id, switch_id, open)
def add_phase_tap_changer_position_action(self, action_id: str, transformer_id: str, is_relative: bool, tap_position: int, side: Side = Side.NONE) -> None: """ Add a phase tap changer tap position action, modifying the tap position of the tap changer Args: action_id: unique ID for the action transformer_id: transformer identifier is_relative: True means the provided tap_position will be added to the current tap position, False means the provided tap_position will replace the previous one. tap_position: The tap position (either a delta if is_relative is true, or the final value if is_relative if false) side: Side of the tap changer (for three windings transformers) """ _pypowsybl.add_phase_tap_changer_position_action(self._handle, action_id, transformer_id, is_relative, tap_position, side) def add_ratio_tap_changer_position_action(self, action_id: str, transformer_id: str, is_relative: bool, tap_position: int, side: Side = Side.NONE) -> None: """ Add a ratio tap changer tap position action, modifying the tap position of the tap changer Args: action_id: unique ID for the action transformer_id: transformer identifier is_relative: True means the provided tap_position will be added to the current tap position, False means the provide tap_position will replace the previous one. tap_position: The tap position (either a delta if is_relative is true, or the final value if is_relative if false) side: Side of the tap changer (for three windings transformers) """ _pypowsybl.add_ratio_tap_changer_position_action(self._handle, action_id, transformer_id, is_relative, tap_position, side) def add_shunt_compensator_position_action(self, action_id: str, shunt_id: str, section: int) -> None: """ Add a shunt compensator section action, modifying the section of the shunt compensator Args: action_id: unique ID for the action shunt_id: transformer identifier section: The new section of the shunt compensator """ _pypowsybl.add_shunt_compensator_position_action(self._handle, action_id, shunt_id, section)
[docs] def add_operator_strategy(self, operator_strategy_id: str, contingency_id: str, action_ids: List[str], condition_type: ConditionType = ConditionType.TRUE_CONDITION, violation_subject_ids: List[str] = None, violation_types: List[ViolationType] = None) -> None: """ Add an operator strategy to the specified contingency Args: operator_strategy_id: unique ID for the operator strategy contingency_id: the contingency on which the operator strategy applies action_ids: the list of actions to be applied as part of the strategy condition_type: the type of condition violation_subject_ids: identifiers of network elements monitored to apply the operator strategy violation_types: type of violations to consider to apply the operator strategy """ if violation_types is None: violation_types = [] if violation_subject_ids is None: violation_subject_ids = [] _pypowsybl.add_operator_strategy(self._handle, operator_strategy_id, contingency_id, action_ids, condition_type, violation_subject_ids, violation_types)