LimitReduction.java
/**
* Copyright (c) 2024, 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
*/
package com.powsybl.security.limitreduction;
import com.google.common.collect.ImmutableList;
import com.powsybl.commons.PowsyblException;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.iidm.criteria.NetworkElementCriterion;
import com.powsybl.iidm.criteria.duration.LimitDurationCriterion;
import com.powsybl.iidm.network.LimitType;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* <p>This class represents a reduction that should be applied to operational limits of a certain type.</p>
* <p>A reduced limit is computed as <code>original limit * limitReduction.value</code>.</p>
* <p>It may also contain restrictions indicating in which conditions it should be applied. If no restriction is defined
* the limit reduction is applied to all limits of the defined type.</p>
* <p>The possible restrictions are:
* <ul>
* <li><code>monitoringOnly</code>: use <code>true</code> if the limit reduction is applied when reporting the limit violations only.
* Use <code>false</code> if it is applied also inside the conditions of operator strategies. The default value is <code>false</code>.</li>
* <li><code>contingencyContext</code>: the contingency context in which the limit reduction is applied (in pre-contingency only, after every contingency, etc.);</li>
* <li><code>networkElementCriteria</code>: criteria a network element should respect for the limit reduction to be applied on its limits;</li>
* <li><code>limitDurationCriteria</code>: criteria based on limit overload acceptable durations. Through these criteria, we can defined if
* the reduction is applied on the permanent limit and/or on a temporary limit if it acceptable duration is within a specific range.</li>
* </ul>
* </p>
* @author Olivier Perrin {@literal <olivier.perrin at rte-france.com>}
*/
public class LimitReduction {
private final LimitType limitType;
private final double value;
private final boolean monitoringOnly;
private final ContingencyContext contingencyContext;
private final List<NetworkElementCriterion> networkElementCriteria;
private final List<LimitDurationCriterion> durationCriteria;
private boolean isSupportedLimitType(LimitType limitType) {
return limitType == LimitType.CURRENT
|| limitType == LimitType.ACTIVE_POWER
|| limitType == LimitType.APPARENT_POWER;
}
/**
* <p>Create a limit reduction applying on each operational limits of a given type.</p>
* <p>This reduction is applied for a contingency context ALL and for limit violations reporting and operator strategy conditions.</p>
*
* @param limitType the type of the limits to reduce.
* @param value the value of the reduction (reduced limits are equal to <code>original limit * reduction value</code>).
*/
public LimitReduction(LimitType limitType, double value) {
this(limitType, value, false);
}
/**
* <p>Create a limit reduction applying on each limits of a given type, for monitoring only or monitoring/action
* depending on the <code>monitoringOnly</code> parameter.</p>
* <p>This reduction is applied for a contingency context ALL.</p>
*
* @param limitType the type of the limits to reduce
* @param value the value of the reduction (reduced limits are equal to <code>original limit * reduction value</code>).
* @param monitoringOnly <code>true</code> if the reduction is applied only for monitoring only, <code>false</code> otherwise.
*/
public LimitReduction(LimitType limitType, double value, boolean monitoringOnly) {
this(limitType, value, monitoringOnly, ContingencyContext.all(), Collections.emptyList(), Collections.emptyList());
}
/**
* <p>Initialize a builder for creating more specific limit reductions (indicate a contingency context or criteria
* on network elements or on limit durations).</p>
*
* @param limitType the type of the limits to reduce.
* @param value the value of the reduction (reduced limits are equal to <code>original limit * reduction value</code>).
* @return a builder used to create a {@link LimitReduction}.
*/
public static LimitReduction.Builder builder(LimitType limitType, double value) {
return new Builder(limitType, value);
}
/**
* <p>Builder used to create a {@link LimitReduction}.</p>
* <p>The default values for the {@link LimitReduction} are the following:
* <ul>
* <li><code>monitoringOnly</code>: <code>false</code>. The limit reduction is applied for monitoring limit violations and conditions of operator strategies;</li>
* <li><code>contingencyContext</code>: {@link ContingencyContext#all()}. The limit reduction is used on pre-contingency state and after each contingency state.</li>
* <li><code>networkElementCriteria</code>: {@link Collections#emptyList()}. The limit reduction is applied on each network element (that holds a limit on this type).</li>
* <li><code>limitDurationCriteria</code>: {@link Collections#emptyList()}. The limit reduction is applied for all permanent and temporary limits.</li>
* </ul>
* </p>
*/
public static class Builder {
private final LimitType limitType;
private final double value;
private boolean monitoringOnly = false;
private ContingencyContext contingencyContext = ContingencyContext.all();
private List<NetworkElementCriterion> networkElementCriteria = Collections.emptyList();
private List<LimitDurationCriterion> limitDurationCriteria = Collections.emptyList();
protected Builder(LimitType limitType, double value) {
this.limitType = limitType;
this.value = value;
}
/**
* <p>Define if the limit reduction is applied only for limit violations report or also inside conditions of operator strategies.</p>
* <p>By default, the limit reduction is apply for both steps.</p>
*
* @param monitoringOnly <code>true</code> if the limit reduction is applied for monitoring only, <code>false</code> otherwise.
* @return the current {@link Builder}
*/
public Builder withMonitoringOnly(boolean monitoringOnly) {
this.monitoringOnly = monitoringOnly;
return this;
}
/**
* <p>Define in which contingency context the limit reduction is applied.</p>
* <p>By default, the limit reduction is used in pre-contingency state and after each contingency state.</p>
*
* @param contingencyContext the contingency context of the limit reduction to be applied.
* @return the current {@link Builder}
*/
public Builder withContingencyContext(ContingencyContext contingencyContext) {
this.contingencyContext = Objects.requireNonNull(contingencyContext);
return this;
}
/**
* <p>Define criteria on network elements.</p>
* <p>By default, the limit reduction is applied on each network element that holds a limit of the good type.</p>
* <p>This method is not cumulative and clean previous definitions.</p>
*
* @param networkElementCriteria criteria on network elements on which the limit reduction is applied.
* @return the current {@link Builder}
*/
public Builder withNetworkElementCriteria(NetworkElementCriterion... networkElementCriteria) {
return withNetworkElementCriteria(List.of(networkElementCriteria));
}
/**
* <p>Define criteria on network elements.</p>
* <p>By default, the limit reduction is applied on each network element that holds a limit of the good type.</p>
* <p>This method is not cumulative and clean previous definitions.</p>
*
* @param networkElementCriteria criteria on network elements on which the limit reduction is applied.
* @return the current {@link Builder}
*/
public Builder withNetworkElementCriteria(List<NetworkElementCriterion> networkElementCriteria) {
this.networkElementCriteria = ImmutableList.copyOf(Objects.requireNonNull(networkElementCriteria));
return this;
}
/**
* <p>Define criteria on permanent limit and/or on acceptable durations of temporary limits within a specific range.</p>
* <p>By default, the limit reduction is applied for all permanent and temporary limits of the good type.</p>
* <p>This method is not cumulative and clean previous definitions.</p>
*
* @param limitDurationCriteria criteria to restrict the limit reduction to specific durations.
* @return the current {@link Builder}
*/
public Builder withLimitDurationCriteria(LimitDurationCriterion... limitDurationCriteria) {
return withLimitDurationCriteria(List.of(limitDurationCriteria));
}
/**
* <p>Define criteria on permanent limit and/or on acceptable durations of temporary limits within a specific range.</p>
* <p>By default, the limit reduction is applied for all permanent and temporary limits of the good type.</p>
* <p>This method is not cumulative and clean previous definitions.</p>
*
* @param limitDurationCriteria criteria to restrict the limit reduction to specific durations.
* @return the current {@link Builder}
*/
public Builder withLimitDurationCriteria(List<LimitDurationCriterion> limitDurationCriteria) {
this.limitDurationCriteria = ImmutableList.copyOf(Objects.requireNonNull(limitDurationCriteria));
return this;
}
/**
* <p>Build the {@link LimitReduction} with the defined parameters.</p>
* @return a new {@link LimitReduction}
*/
public LimitReduction build() {
return new LimitReduction(limitType, value, monitoringOnly, contingencyContext,
networkElementCriteria, limitDurationCriteria);
}
}
private LimitReduction(LimitType limitType, double value, boolean monitoringOnly,
ContingencyContext contingencyContext,
List<NetworkElementCriterion> networkElementCriteria,
List<LimitDurationCriterion> limitDurationCriteria) {
if (isSupportedLimitType(limitType)) {
this.limitType = limitType;
} else {
throw new PowsyblException(limitType + " is not a supported limit type for limit reduction");
}
if (value > 1. || value < 0.) {
throw new PowsyblException("Limit reduction value should be in [0;1]");
}
this.value = value;
this.monitoringOnly = monitoringOnly;
this.contingencyContext = contingencyContext;
this.networkElementCriteria = networkElementCriteria;
this.durationCriteria = limitDurationCriteria;
}
public LimitType getLimitType() {
return limitType;
}
public double getValue() {
return value;
}
/**
* <p>Indicate if the limit reduction is applied only to report limit violations (<code>true</code>),
* or if also affects the conditions of operator strategies (<code>false</code>).</p>
*
* @return <code>true</code> if the limit reduction is applied only for monitoring, <code>false</code> otherwise.
*/
public boolean isMonitoringOnly() {
return monitoringOnly;
}
/**
* <p>Indicate the limit reduction contingency context.</p>
*
* @return the {@link ContingencyContext} of the limit reduction.
*/
public ContingencyContext getContingencyContext() {
return contingencyContext;
}
/**
* <p>Indicate the criteria on network elements candidate for the limit reduction.</p>
*
* @return the list of the {@link NetworkElementCriterion} candidate for the limit reduction.
*/
public List<NetworkElementCriterion> getNetworkElementCriteria() {
return networkElementCriteria;
}
/**
* <p>Indicate criteria on operational limit acceptable durations.</p>
*
* @return the list of the {@link LimitDurationCriterion} of the limit reduction.
*/
public List<LimitDurationCriterion> getDurationCriteria() {
return durationCriteria;
}
}