# Angle monitoring

Contents

## Introduction

Some CRAC files can define angle constraints on network elements.
These are constraints that monitor that the current phase shift between two network elements does not exceed a given threshold.
FARAO allows modelling these constraints in AngleCnec objects.
However, modelling the impact of remedial actions on angle values is highly complex and non-linear. This is why CASTOR does not inherently support angle constraints.
The AngleMonitoring package allows monitoring angle values after a RAO has been run, and activating re-dispatch remedial actions in case of constrained elements.

## The Java API

You can easily call the angle monitoring module using the JAVA API:

1. Build an AngleMonitoring object using:
public AngleMonitoring(Crac crac, Network network, RaoResult raoResult, CimGlskDocument cimGlskDocument)


With:

• crac: the CRAC object used for the RAO, and containing AngleCnecs to be monitored.
• network: the network to be monitored.
• raoResult: the RaoResult object containing selected remedial actions (that shall be applied on the network before monitoring angle values)
• cimGlskDocument: the CIM GLSK document that will allow proper application of re-dispatch remedial actions.
2. Run the monitoring algorithm using the constructed object’s following method:
public AngleMonitoringResult run(String loadFlowProvider, LoadFlowParameters loadFlowParameters, int numberOfLoadFlowsInParallel, OffsetDateTime glskOffsetDateTime)


With:

• loadFlowProvider: the name of the load-flow computer to use. This should refer to a PowSyBl load flow provider implementation
• numberOfLoadFlowsInParallel: the number of contingencies to monitor in parallel, allowing a maximum utilization of your computing resources (set it to your number of available CPUs).
• glskOffsetDateTime: the timestamp for which the computation is made, as it is necessary to correctly read relevant values from the CIM GLSK file.

💡 NOTE
For now, only CIM GLSK format is supported by the angle monitoring module

Here is a complete example:

Crac crac = ...
Network network = ...
RaoResult raoResult = Rao.find(...).run(...)
CimGlskDocument glsk = ...
OffsetDateTime glskOffsetDateTime = ...


## The angle monitoring result

### JSON import & export

The AngleMonitoringResult can be written to and read from a JSON file.
Example:

// Export
AngleMonitoringResult angleMonitoringResult = ...
OutputStream os = ...
new AngleMonitoringResultExporter().export(angleMonitoringResult, os);

// Import
InputStream is = ...
Crac crac = ...
AngleMonitoringResult angleMonitoringResult2 =new AngleMonitoringResultImporter().importAngleMonitoringResult(is, crac);


### Contents

The AngleMonitoringResult object contains the results of the angle monitoring algorithm.

#### Status

The AngleMonitoringResult describes the security status of the network in regard to the angle constraints defined in the CRAC:

• SECURE: the network is secure; no angle thresholds are violated
• UNSECURE: the network is not secure; at least one angle CNEC has an angle constraint
• DIVERGENT: the load-flow computation diverged; angle monitoring could not be run normally
• UNKNOWN: the angle monitoring failed for any other reason
// get the overall status (one of 4 values above)
public Status getStatus()

// know which value it has
public boolean isSecure()
public boolean isUnsecure()
public boolean isDivergent()
public boolean isUnknown()


Example:

{
"type": "ANGLE_MONITORING_RESULT",
"status": "SECURE",
...
}


#### Applied CRAs

Since the angle monitoring [algorithm]{#algorithm} can apply CRAs, these methods detail which ones were selected.

// get activated network actions for each state
public Map<State, Set<NetworkAction>> getAppliedCras()

// get activated network actions for a given state
public Set<NetworkAction> getAppliedCras(State state)

// get activated network action IDs for a given state ID
public Set<String> getAppliedCras(String stateId)


Example:

"applied-cras": [
{
"instant": "curative",
"contingency": "co1",
"remedial-actions": [
"na2"
]
},
{
"instant": "preventive",
"remedial-actions": [
"na1"
]
}
]


#### Angle values

The following methods return the angle values for angle CNECs after applying angle CRAs.

// get the angle value for a given CNEC, and a given angle unit
public double getAngle(AngleCnec angleCnec, Unit unit)

// get all angle results (an AngleResult contains an AngleCnec and its angle value)
public Set<AngleResult> getAngleCnecsWithAngle()


Example:

  "angle-cnec-quantities-in-degrees": [
{
"instant": "preventive",
"cnec-id": "ac1",
"quantity": 2.3
},
{
"instant": "curative",
"contingency": "co1",
"cnec-id": "ac2",
"quantity": 4.6
}
]


### Printing the result

You can get a human-readable report of the angle monitoring algorithm, using the following method of the AngleMonitoringResult object:

public List<String> printConstraints()


### Complete JSON example

{
"type": "ANGLE_MONITORING_RESULT",
"status": "SECURE",
"angle-cnec-quantities-in-degrees": [
{
"instant": "preventive",
"cnec-id": "ac1",
"quantity": 2.3
},
{
"instant": "curative",
"contingency": "co1",
"cnec-id": "ac2",
"quantity": 4.6
}
],
"applied-cras": [
{
"instant": "curative",
"contingency": "co1",
"remedial-actions": [
"na2"
]
},
{
"instant": "preventive",
"remedial-actions": [
"na1"
]
}
]
}


## The angle monitoring algorithm

Here is a detailed description of how the angle monitoring algorithm operates:

• Apply optimal preventive remedial actions from RaoResult on the network
• From the CRAC, get the set of states on which AngleCnecs exist
• For each of these states, monitor angles:
• Use a new copy of the network
• If the state is not preventive,
• apply the contingency on the network
• from the RaoResult, apply on the network the optimal remedial actions decided by the RAO (automatic and curative)
• If it diverges, return the following content for this state, then move on to the next state:
• the angles of the angle CNECs equal to NaN
• no applied remedial actions
• status DIVERGENT
• Compute the angles for all angle CNECs, as the maximum phase difference between the 2 voltage levels (1)
• Angle in degrees = 180 / pi * (max(angle on buses of exporting voltage level) - min(angle on buses of importing voltage level))
• Compare the angles to their thresholds. For the AngleCnecs that have an angle overshoot, get the associated remedial actions (2)
• If the AngleCnec has no associated RA, then the angle constraint cannot be remedied: move on to the next AngleCnec.
• If the state is preventive, do not apply any PRA (it would be incoherent with the RAO results). Move on to the next state.
• For every RA:
• If the remedial action is not a network action, do not apply it (if it’s a RangeAction, we cannot know which set-point to use). Move on to the next RA.
• If the RA is a network action, apply it on the network.
• If any injection-set-point RA was applied, create and apply the re-dispatch that shall compensate the loss of generation / load (3):
• The amount of power to re-dispatch is the net sum (generation - load) of power generations & loads affected by the RAs, before changing the set-points
• The GLSK to use shall be the same as the one used for the whole process
• Exclude from the re-dispatching all the generators & loads that were modified by an injection-set-point RA, since they should not be affected
• If any RA was applied, recompute the load-flow
• If it diverges, return the following content for this state, then move on to the next state:
• the angles of the AngleCnecs equal to what was computed in step (1)
• no applied remedial actions
• security DIVERGENT
• Re-compute all angle values (4)
• Create an [AngleMonitoringResult]{#result} with angles computed in (4), list of applied remedial actions in (2), and secure flag set to SECURE if there is no more overshoot (after re-verifying thresholds)
• Assemble all the state-specific AngleMonitoringResults in one overall AngleMonitoringResult