RaUsageLimits.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/.
*/
package com.powsybl.openrao.data.crac.api;
import com.powsybl.openrao.commons.OpenRaoException;
import java.util.*;
import static com.powsybl.openrao.commons.logs.OpenRaoLoggerProvider.BUSINESS_WARNS;
/**
* @author Martin Belthle {@literal <martin.belthle at rte-france.com>}
*/
public class RaUsageLimits {
private static final int DEFAULT_MAX_RA = Integer.MAX_VALUE;
private static final int DEFAULT_MAX_TSO = Integer.MAX_VALUE;
private static final Map<String, Integer> DEFAULT_MAX_TOPO_PER_TSO = new HashMap<>();
private static final Map<String, Integer> DEFAULT_MAX_PST_PER_TSO = new HashMap<>();
private static final Map<String, Integer> DEFAULT_MAX_RA_PER_TSO = new HashMap<>();
private static final Map<String, Integer> DEFAULT_MAX_ELEMENTARY_ACTIONS_PER_TSO = new HashMap<>();
private int maxRa = DEFAULT_MAX_RA;
private int maxTso = DEFAULT_MAX_TSO;
private final Set<String> maxTsoExclusion = new HashSet<>();
private Map<String, Integer> maxTopoPerTso = DEFAULT_MAX_TOPO_PER_TSO;
private Map<String, Integer> maxPstPerTso = DEFAULT_MAX_PST_PER_TSO;
private Map<String, Integer> maxRaPerTso = DEFAULT_MAX_RA_PER_TSO;
private Map<String, Integer> maxElementaryActionsPerTso = DEFAULT_MAX_ELEMENTARY_ACTIONS_PER_TSO;
public void setMaxRa(int maxRa) {
if (maxRa < 0) {
BUSINESS_WARNS.warn("The value {} provided for max number of RAs is smaller than 0. It will be set to 0 instead.", maxRa);
this.maxRa = 0;
} else {
this.maxRa = maxRa;
}
}
public void setMaxTso(int maxTso) {
if (maxTso < 0) {
BUSINESS_WARNS.warn("The value {} provided for max number of TSOs is smaller than 0. It will be set to 0 instead.", maxTso);
this.maxTso = 0;
} else {
this.maxTso = maxTso;
}
}
public void setMaxTopoPerTso(Map<String, Integer> maxTopoPerTso) {
if (Objects.isNull(maxTopoPerTso)) {
this.maxTopoPerTso = new HashMap<>();
} else {
Map<String, Integer> updatedMaxTopoPerTso = replaceNegativeValues(maxTopoPerTso);
crossCheckMaxCraPerTsoParameters(this.maxRaPerTso, updatedMaxTopoPerTso, this.maxPstPerTso);
this.maxTopoPerTso = updatedMaxTopoPerTso;
}
}
public void setMaxPstPerTso(Map<String, Integer> maxPstPerTso) {
if (Objects.isNull(maxPstPerTso)) {
this.maxPstPerTso = new HashMap<>();
} else {
Map<String, Integer> updatedMaxPstPerTso = replaceNegativeValues(maxPstPerTso);
crossCheckMaxCraPerTsoParameters(this.maxRaPerTso, this.maxTopoPerTso, updatedMaxPstPerTso);
this.maxPstPerTso = updatedMaxPstPerTso;
}
}
public void setMaxRaPerTso(Map<String, Integer> maxRaPerTso) {
if (Objects.isNull(maxRaPerTso)) {
this.maxRaPerTso = new HashMap<>();
} else {
Map<String, Integer> updatedMaxRaPerTso = replaceNegativeValues(maxRaPerTso);
crossCheckMaxCraPerTsoParameters(updatedMaxRaPerTso, this.maxTopoPerTso, this.maxPstPerTso);
this.maxRaPerTso = updatedMaxRaPerTso;
}
}
public void setMaxElementaryActionsPerTso(Map<String, Integer> maxElementaryActionsPerTso) {
this.maxElementaryActionsPerTso = Objects.isNull(maxElementaryActionsPerTso) ? new HashMap<>() : replaceNegativeValues(maxElementaryActionsPerTso);
}
public int getMaxRa() {
return maxRa;
}
public int getMaxTso() {
return maxTso;
}
public Map<String, Integer> getMaxTopoPerTso() {
return maxTopoPerTso;
}
public Map<String, Integer> getMaxPstPerTso() {
return maxPstPerTso;
}
public Map<String, Integer> getMaxRaPerTso() {
return maxRaPerTso;
}
public Map<String, Integer> getMaxElementaryActionsPerTso() {
return maxElementaryActionsPerTso;
}
public Set<String> getMaxTsoExclusion() {
return maxTsoExclusion;
}
private Map<String, Integer> replaceNegativeValues(Map<String, Integer> limitsPerTso) {
limitsPerTso.forEach((tso, limit) -> {
if (limit < 0) {
BUSINESS_WARNS.warn("The value {} provided for max number of RAs for TSO {} is smaller than 0. It will be set to 0 instead.", limit, tso);
limitsPerTso.put(tso, 0);
}
});
return limitsPerTso;
}
private static void crossCheckMaxCraPerTsoParameters(Map<String, Integer> maxRaPerTso, Map<String, Integer> maxTopoPerTso, Map<String, Integer> maxPstPerTso) {
Set<String> tsos = new HashSet<>();
tsos.addAll(maxRaPerTso.keySet());
tsos.addAll(maxTopoPerTso.keySet());
tsos.addAll(maxPstPerTso.keySet());
tsos.forEach(tso -> {
if (maxTopoPerTso.containsKey(tso)
&& maxRaPerTso.getOrDefault(tso, DEFAULT_MAX_RA) < maxTopoPerTso.get(tso)) {
throw new OpenRaoException(String.format("TSO %s has a maximum number of allowed RAs smaller than the number of allowed topological RAs. This is not supported.", tso));
}
if (maxPstPerTso.containsKey(tso)
&& maxRaPerTso.getOrDefault(tso, DEFAULT_MAX_RA) < maxPstPerTso.get(tso)) {
throw new OpenRaoException(String.format("TSO %s has a maximum number of allowed RAs smaller than the number of allowed PST RAs. This is not supported.", tso));
}
});
}
public void addTsoToExclude(String tso) {
maxTsoExclusion.add(tso);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RaUsageLimits raUsageLimits = (RaUsageLimits) o;
return raUsageLimits.maxRa == this.maxRa
&& raUsageLimits.maxTso == this.maxTso
&& raUsageLimits.maxRaPerTso.equals(this.maxRaPerTso)
&& raUsageLimits.maxPstPerTso.equals(this.maxPstPerTso)
&& raUsageLimits.maxTopoPerTso.equals(this.maxTopoPerTso);
}
@Override
public int hashCode() {
return super.hashCode();
}
}