diff --git a/.mvn/lombok-config-copy.marker b/.mvn/lombok-config-copy.marker new file mode 100644 index 0000000..e69de29 diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..4fa8250 --- /dev/null +++ b/lombok.config @@ -0,0 +1 @@ +import target/configs/powsybl-build-tools.jar!powsybl-build-tools/lombok.config diff --git a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitRunContext.java b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitRunContext.java index dd3db65..2c35a5f 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitRunContext.java +++ b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitRunContext.java @@ -6,8 +6,12 @@ */ package org.gridsuite.voltageinit.server.service; +import com.powsybl.commons.reporter.Reporter; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.Setter; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -15,6 +19,7 @@ /** * @author Etienne Homer */ +@AllArgsConstructor @Getter public class VoltageInitRunContext { @@ -36,15 +41,13 @@ public class VoltageInitRunContext { private final Map voltageLevelsIdsRestricted; + @Setter private Reporter rootReporter; + public VoltageInitRunContext(UUID networkUuid, String variantId, String receiver, UUID reportUuid, String reporterId, String reportType, String userId, UUID parametersUuid, Map voltageLevelsIdsRestricted) { - this.networkUuid = Objects.requireNonNull(networkUuid); - this.variantId = variantId; - this.receiver = receiver; - this.reportUuid = reportUuid; - this.reporterId = reporterId; - this.reportType = reportType; - this.userId = userId; - this.parametersUuid = parametersUuid; - this.voltageLevelsIdsRestricted = voltageLevelsIdsRestricted; + this(Objects.requireNonNull(networkUuid), variantId, receiver, reportUuid, reporterId, reportType, userId, parametersUuid, voltageLevelsIdsRestricted, Reporter.NO_OP); + } + + public VoltageInitRunContext(UUID networkUuid, String variantId, String receiver, UUID reportUuid, String reporterId, String reportType, String userId, UUID parametersUuid) { + this(networkUuid, variantId, receiver, reportUuid, reporterId, reportType, userId, parametersUuid, new HashMap<>()); } } diff --git a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitService.java b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitService.java index 5332dc7..e37aff0 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitService.java +++ b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitService.java @@ -50,7 +50,7 @@ public VoltageInitService(NotificationService notificationService, } public UUID runAndSaveResult(UUID networkUuid, String variantId, String receiver, UUID reportUuid, String reporterId, String userId, String reportType, UUID parametersUuid) { - VoltageInitRunContext runContext = new VoltageInitRunContext(networkUuid, variantId, receiver, reportUuid, reporterId, reportType, userId, parametersUuid, new HashMap<>()); + VoltageInitRunContext runContext = new VoltageInitRunContext(networkUuid, variantId, receiver, reportUuid, reporterId, reportType, userId, parametersUuid); Objects.requireNonNull(runContext); var resultUuid = uuidGeneratorService.generate(); diff --git a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitWorkerService.java b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitWorkerService.java index 9564f3f..129c9ed 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitWorkerService.java +++ b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitWorkerService.java @@ -8,10 +8,8 @@ import com.google.common.collect.Sets; import com.powsybl.commons.PowsyblException; -import com.powsybl.commons.reporter.Report; import com.powsybl.commons.reporter.Reporter; import com.powsybl.commons.reporter.ReporterModel; -import com.powsybl.commons.reporter.TypedValue; import com.powsybl.iidm.network.Bus; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.VariantManagerConstants; @@ -113,21 +111,6 @@ private Network getNetwork(UUID networkUuid, String variantId) { return network; } - public static void addRestrictedVoltageLevelReport(Map voltageLevelsIdsRestricted, Reporter reporter) { - if (!voltageLevelsIdsRestricted.isEmpty()) { - String joinedVoltageLevelsIds = voltageLevelsIdsRestricted.entrySet() - .stream() - .map(entry -> entry.getKey() + " : " + entry.getValue()) - .collect(Collectors.joining(", ")); - - reporter.report(Report.builder() - .withKey("restrictedVoltageLevels") - .withDefaultMessage(String.format("The modifications to the low limits for certain voltage levels have been restricted to avoid negative voltage limits: %s", joinedVoltageLevelsIds)) - .withSeverity(TypedValue.WARN_SEVERITY) - .build()); - } - } - private Pair run(VoltageInitRunContext context, UUID resultUuid) throws Exception { Objects.requireNonNull(context); @@ -136,18 +119,16 @@ private Pair run(VoltageInitRunContext context, UUID re getNetwork(context.getNetworkUuid(), context.getVariantId())); AtomicReference rootReporter = new AtomicReference<>(Reporter.NO_OP); - Reporter reporter = Reporter.NO_OP; if (context.getReportUuid() != null) { String rootReporterId = context.getReporterId() == null ? VOLTAGE_INIT_TYPE_REPORT : context.getReporterId() + "@" + context.getReportType(); rootReporter.set(new ReporterModel(rootReporterId, rootReporterId)); - reporter = rootReporter.get().createSubReporter(context.getReportType(), VOLTAGE_INIT_TYPE_REPORT, VOLTAGE_INIT_TYPE_REPORT, context.getReportUuid().toString()); + context.setRootReporter(rootReporter.get().createSubReporter(context.getReportType(), VOLTAGE_INIT_TYPE_REPORT, VOLTAGE_INIT_TYPE_REPORT, context.getReportUuid().toString())); // Delete any previous VoltageInit computation logs voltageInitObserver.observe("report.delete", () -> reportService.deleteReport(context.getReportUuid(), context.getReportType())); } CompletableFuture future = runVoltageInitAsync(context, network, resultUuid); if (context.getReportUuid() != null) { - addRestrictedVoltageLevelReport(context.getVoltageLevelsIdsRestricted(), reporter); voltageInitObserver.observe("report.send", () -> reportService.sendReport(context.getReportUuid(), rootReporter.get())); } diff --git a/src/main/java/org/gridsuite/voltageinit/server/service/parameters/VoltageInitParametersService.java b/src/main/java/org/gridsuite/voltageinit/server/service/parameters/VoltageInitParametersService.java index 1fee025..3eb0914 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/service/parameters/VoltageInitParametersService.java +++ b/src/main/java/org/gridsuite/voltageinit/server/service/parameters/VoltageInitParametersService.java @@ -6,15 +6,25 @@ */ package org.gridsuite.voltageinit.server.service.parameters; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import com.google.common.annotations.VisibleForTesting; +import com.powsybl.commons.reporter.Report; +import com.powsybl.commons.reporter.Reporter; +import com.powsybl.commons.reporter.TypedValue; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.VoltageLevel; import com.powsybl.openreac.parameters.input.OpenReacParameters; import com.powsybl.openreac.parameters.input.VoltageLimitOverride; +import com.powsybl.openreac.parameters.input.VoltageLimitOverride.VoltageLimitType; import com.powsybl.openreac.parameters.input.algo.ReactiveSlackBusesMode; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.mutable.MutableInt; import org.gridsuite.voltageinit.server.dto.parameters.FilterEquipments; import org.gridsuite.voltageinit.server.dto.parameters.IdentifiableAttributes; import org.gridsuite.voltageinit.server.dto.parameters.VoltageInitParametersInfos; @@ -24,6 +34,7 @@ import org.gridsuite.voltageinit.server.repository.parameters.VoltageInitParametersRepository; import org.gridsuite.voltageinit.server.service.VoltageInitRunContext; import org.gridsuite.voltageinit.server.util.VoltageLimitParameterType; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -37,6 +48,7 @@ public class VoltageInitParametersService { private static final Logger LOGGER = LoggerFactory.getLogger(VoltageInitParametersService.class); + private static final DecimalFormat VOLTAGE_FORMAT = new DecimalFormat("0.0\u202FkV", DecimalFormatSymbols.getInstance(Locale.ROOT)); private final FilterService filterService; @@ -91,35 +103,49 @@ private Map resolveVoltageLevelLimits(VoltageInitRun return voltageLevelLimits; } - private void fillSpecificVoltageLimits(List specificVoltageLimits, Map voltageLevelModificationLimits, Map voltageLevelDefaultLimits, VoltageLevel voltageLevel, Map voltageLevelsIdsRestricted) { + private static void fillSpecificVoltageLimits(List specificVoltageLimits, + final MutableInt missingVoltageLimitsCounter, + final MutableInt voltageLimitModificationsCounter, + Map voltageLevelModificationLimits, + Map voltageLevelDefaultLimits, + VoltageLevel voltageLevel, + Map voltageLevelsIdsRestricted) { boolean isLowVoltageLimitModificationSet = voltageLevelModificationLimits.containsKey(voltageLevel.getId()) && voltageLevelModificationLimits.get(voltageLevel.getId()).getLowVoltageLimit() != null; boolean isHighVoltageLimitModificationSet = voltageLevelModificationLimits.containsKey(voltageLevel.getId()) && voltageLevelModificationLimits.get(voltageLevel.getId()).getHighVoltageLimit() != null; boolean isLowVoltageLimitDefaultSet = voltageLevelDefaultLimits.containsKey(voltageLevel.getId()) && voltageLevelDefaultLimits.get(voltageLevel.getId()).getLowVoltageLimit() != null; boolean isHighVoltageLimitDefaultSet = voltageLevelDefaultLimits.containsKey(voltageLevel.getId()) && voltageLevelDefaultLimits.get(voltageLevel.getId()).getHighVoltageLimit() != null; - setLowVoltageLimit(specificVoltageLimits, voltageLevelModificationLimits, voltageLevelDefaultLimits, isLowVoltageLimitModificationSet, isLowVoltageLimitDefaultSet, voltageLevel, voltageLevelsIdsRestricted); - setHighVoltageLimit(specificVoltageLimits, voltageLevelModificationLimits, voltageLevelDefaultLimits, isHighVoltageLimitModificationSet, isHighVoltageLimitDefaultSet, voltageLevel); + final CounterToIncrement counterToIncrementLow = generateLowVoltageLimit(specificVoltageLimits, voltageLevelModificationLimits, voltageLevelDefaultLimits, isLowVoltageLimitModificationSet, isLowVoltageLimitDefaultSet, voltageLevel, voltageLevelsIdsRestricted); + final CounterToIncrement counterToIncrementHigh = generateHighVoltageLimit(specificVoltageLimits, voltageLevelModificationLimits, voltageLevelDefaultLimits, isHighVoltageLimitModificationSet, isHighVoltageLimitDefaultSet, voltageLevel); + if (counterToIncrementLow == CounterToIncrement.DEFAULT || counterToIncrementLow == CounterToIncrement.BOTH || + counterToIncrementHigh == CounterToIncrement.DEFAULT || counterToIncrementHigh == CounterToIncrement.BOTH) { + missingVoltageLimitsCounter.increment(); + } + if (counterToIncrementLow == CounterToIncrement.MODIFICATION || counterToIncrementLow == CounterToIncrement.BOTH || + counterToIncrementHigh == CounterToIncrement.MODIFICATION || counterToIncrementHigh == CounterToIncrement.BOTH) { + voltageLimitModificationsCounter.increment(); + } } - private void setLowVoltageLimit(List specificVoltageLimits, - Map voltageLevelModificationLimits, - Map voltageLevelDefaultLimits, - boolean isLowVoltageLimitModificationSet, - boolean isLowVoltageLimitDefaultSet, - VoltageLevel voltageLevel, - Map voltageLevelsIdsRestricted) { + private static CounterToIncrement generateLowVoltageLimit(List specificVoltageLimits, + Map voltageLevelModificationLimits, + Map voltageLevelDefaultLimits, + boolean isLowVoltageLimitModificationSet, + boolean isLowVoltageLimitDefaultSet, + VoltageLevel voltageLevel, + Map voltageLevelsIdsRestricted) { double newLowVoltageLimit; double lowVoltageLimit = voltageLevel.getLowVoltageLimit(); if (!Double.isNaN(lowVoltageLimit) && isLowVoltageLimitModificationSet) { double lowVoltageLimitModification = voltageLevelModificationLimits.get(voltageLevel.getId()).getLowVoltageLimit(); - if (lowVoltageLimit + lowVoltageLimitModification < 0) { newLowVoltageLimit = lowVoltageLimit * -1; voltageLevelsIdsRestricted.put(voltageLevel.getId(), newLowVoltageLimit); } else { newLowVoltageLimit = lowVoltageLimitModification; } - specificVoltageLimits.add(new VoltageLimitOverride(voltageLevel.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, true, newLowVoltageLimit)); + specificVoltageLimits.add(new VoltageLimitOverride(voltageLevel.getId(), VoltageLimitType.LOW_VOLTAGE_LIMIT, true, newLowVoltageLimit)); + return CounterToIncrement.MODIFICATION; } else if (Double.isNaN(lowVoltageLimit) && isLowVoltageLimitDefaultSet) { double voltageLimit = voltageLevelDefaultLimits.get(voltageLevel.getId()).getLowVoltageLimit() + (isLowVoltageLimitModificationSet ? voltageLevelModificationLimits.get(voltageLevel.getId()).getLowVoltageLimit() : 0.); @@ -129,27 +155,42 @@ private void setLowVoltageLimit(List specificVoltageLimits } else { newLowVoltageLimit = voltageLimit; } - specificVoltageLimits.add( - new VoltageLimitOverride(voltageLevel.getId(), - VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT, - false, - newLowVoltageLimit - )); + specificVoltageLimits.add(new VoltageLimitOverride(voltageLevel.getId(), VoltageLimitType.LOW_VOLTAGE_LIMIT, false, newLowVoltageLimit)); + if (isLowVoltageLimitModificationSet) { + return CounterToIncrement.BOTH; + } + return CounterToIncrement.DEFAULT; } + return CounterToIncrement.NONE; } - private void setHighVoltageLimit(List specificVoltageLimits, Map voltageLevelModificationLimits, Map voltageLevelDefaultLimits, boolean isHighVoltageLimitModificationSet, boolean isHighVoltageLimitDefaultSet, VoltageLevel voltageLevel) { + private static CounterToIncrement generateHighVoltageLimit(List specificVoltageLimits, + Map voltageLevelModificationLimits, + Map voltageLevelDefaultLimits, + boolean isHighVoltageLimitModificationSet, + boolean isHighVoltageLimitDefaultSet, + VoltageLevel voltageLevel) { if (!Double.isNaN(voltageLevel.getHighVoltageLimit()) && isHighVoltageLimitModificationSet) { - specificVoltageLimits.add(new VoltageLimitOverride(voltageLevel.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, voltageLevelModificationLimits.get(voltageLevel.getId()).getHighVoltageLimit())); + specificVoltageLimits.add(new VoltageLimitOverride(voltageLevel.getId(), VoltageLimitType.HIGH_VOLTAGE_LIMIT, true, voltageLevelModificationLimits.get(voltageLevel.getId()).getHighVoltageLimit())); + return CounterToIncrement.MODIFICATION; } else if (Double.isNaN(voltageLevel.getHighVoltageLimit()) && isHighVoltageLimitDefaultSet) { - specificVoltageLimits.add(new VoltageLimitOverride(voltageLevel.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, voltageLevelDefaultLimits.get(voltageLevel.getId()).getHighVoltageLimit() + (isHighVoltageLimitModificationSet ? voltageLevelModificationLimits.get(voltageLevel.getId()).getHighVoltageLimit() : 0.))); + specificVoltageLimits.add(new VoltageLimitOverride(voltageLevel.getId(), VoltageLimitType.HIGH_VOLTAGE_LIMIT, false, voltageLevelDefaultLimits.get(voltageLevel.getId()).getHighVoltageLimit() + (isHighVoltageLimitModificationSet ? voltageLevelModificationLimits.get(voltageLevel.getId()).getHighVoltageLimit() : 0.))); + if (isHighVoltageLimitModificationSet) { + return CounterToIncrement.BOTH; + } else { + return CounterToIncrement.DEFAULT; + } + } else { + return CounterToIncrement.NONE; } } @Transactional(readOnly = true) public OpenReacParameters buildOpenReacParameters(VoltageInitRunContext context, Network network) { - AtomicReference startTime = new AtomicReference<>(); - startTime.set(System.nanoTime()); + AtomicReference startTime = new AtomicReference<>(System.nanoTime()); + final Reporter reporter = context.getRootReporter().createSubReporter("VoltageInitParameters", "VoltageInit parameters", Map.of( + "parameters_id", new TypedValue(Objects.toString(context.getParametersUuid()), "ID") + )); Optional voltageInitParametersEntity = Optional.empty(); if (context.getParametersUuid() != null) { @@ -161,6 +202,8 @@ public OpenReacParameters buildOpenReacParameters(VoltageInitRunContext context, List constantQGenerators = new ArrayList<>(); List variableTwoWindingsTransformers = new ArrayList<>(); List variableShuntCompensators = new ArrayList<>(); + final MutableInt missingVoltageLimitsCounter = new MutableInt(0); + final MutableInt voltageLimitModificationsCounter = new MutableInt(0); voltageInitParametersEntity.ifPresent(voltageInitParameters -> { if (voltageInitParameters.getVoltageLimits() != null) { @@ -173,8 +216,13 @@ public OpenReacParameters buildOpenReacParameters(VoltageInitRunContext context, .toList()); network.getVoltageLevelStream() - .filter(voltageLevel -> voltageLevelDefaultLimits.keySet().contains(voltageLevel.getId()) || voltageLevelModificationLimits.keySet().contains(voltageLevel.getId())) - .forEach(voltageLevel -> fillSpecificVoltageLimits(specificVoltageLimits, voltageLevelModificationLimits, voltageLevelDefaultLimits, voltageLevel, context.getVoltageLevelsIdsRestricted())); + .filter(voltageLevel -> voltageLevelDefaultLimits.containsKey(voltageLevel.getId()) || voltageLevelModificationLimits.containsKey(voltageLevel.getId())) + .forEach(voltageLevel -> fillSpecificVoltageLimits(specificVoltageLimits, + missingVoltageLimitsCounter, voltageLimitModificationsCounter, + voltageLevelModificationLimits, voltageLevelDefaultLimits, + voltageLevel, context.getVoltageLevelsIdsRestricted())); + + logRestrictedVoltageLevels(reporter, context.getVoltageLevelsIdsRestricted()); } constantQGenerators.addAll(toEquipmentIdsList(context.getNetworkUuid(), context.getVariantId(), voltageInitParameters.getConstantQGenerators())); @@ -186,11 +234,13 @@ public OpenReacParameters buildOpenReacParameters(VoltageInitRunContext context, .addVariableTwoWindingsTransformers(variableTwoWindingsTransformers) .addVariableShuntCompensators(variableShuntCompensators); + logVoltageLimitsModifications(reporter, network, parameters.getSpecificVoltageLimits()); + logVoltageLimitsModificationCounters(reporter, missingVoltageLimitsCounter, voltageLimitModificationsCounter); + //The optimizer will attach reactive slack variables to all buses parameters.setReactiveSlackBusesMode(ReactiveSlackBusesMode.ALL); - long nanoTime = System.nanoTime(); - LOGGER.info("Parameters built in {}s", TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime.getAndSet(nanoTime))); + LOGGER.info("Parameters built in {}s", TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime.get())); return parameters; } @@ -207,4 +257,82 @@ private List toEquipmentIdsList(UUID networkUuid, String variantId, List ); return new ArrayList<>(ids); } + + private static void logRestrictedVoltageLevels(final Reporter reporter, final Map voltageLevelsIdsRestricted) { + if (!voltageLevelsIdsRestricted.isEmpty()) { + reporter.report(Report.builder() + .withKey("restrictedVoltageLevels") + .withDefaultMessage("The modifications to the low limits for certain voltage levels have been restricted to avoid negative voltage limits: ${joinedVoltageLevelsIds}") + .withValue("joinedVoltageLevelsIds", voltageLevelsIdsRestricted + .entrySet() + .stream() + .map(entry -> entry.getKey() + " : " + VOLTAGE_FORMAT.format(ObjectUtils.defaultIfNull(entry.getValue(), Double.NaN))) + .collect(Collectors.joining(", "))) + .withSeverity(TypedValue.WARN_SEVERITY) + .build()); + } + } + + private static void logVoltageLimitsModificationCounters(final Reporter reporter, + final MutableInt counterMissingVoltageLimits, + final MutableInt counterVoltageLimitModifications) { + reporter.report(Report.builder() + .withKey("missingVoltageLimits") + .withDefaultMessage("Missing voltage limits of ${nbMissingVoltageLimits} voltage levels have been replaced with user-defined default values.") + .withValue("nbMissingVoltageLimits", counterMissingVoltageLimits.longValue()) + .withSeverity(TypedValue.INFO_SEVERITY) + .build()); + reporter.report(Report.builder() + .withKey("voltageLimitModifications") + .withDefaultMessage("Voltage limits of ${nbVoltageLimitModifications} voltage levels have been modified according to user input.") + .withValue("nbVoltageLimitModifications", counterVoltageLimitModifications.longValue()) + .withSeverity(TypedValue.INFO_SEVERITY) + .build()); + } + + private static void logVoltageLimitsModifications(final Reporter reporter, + final Network network, + final List specificVoltageLimits) { + specificVoltageLimits + .stream() + .collect(HashMap>::new, + (map, voltageLimitOverride) -> map + .computeIfAbsent(voltageLimitOverride.getVoltageLevelId(), key -> new EnumMap<>(VoltageLimitType.class)) + .put(voltageLimitOverride.getVoltageLimitType(), voltageLimitOverride), + (map, map2) -> map2.forEach((id, newLimits) -> map.merge(id, newLimits, (newLimit1, newLimit2) -> { + newLimit1.putAll(newLimit2); + return newLimit1; + }) + )) + .forEach((id, voltageLimits) -> { + final VoltageLevel voltageLevel = network.getVoltageLevel(id); + final double initialLowVoltageLimit = voltageLevel.getLowVoltageLimit(); + final double initialHighVoltage = voltageLevel.getHighVoltageLimit(); + reporter.report(Report.builder() + .withKey("voltageLimitModified") + .withDefaultMessage("Voltage limits of ${voltageLevelId} modified: low voltage limit = ${lowVoltageLimit}, high voltage limit = ${highVoltageLimit}") + .withTypedValue("voltageLevelId", voltageLevel.getId(), TypedValue.VOLTAGE_LEVEL) + .withTypedValue("lowVoltageLimit", computeRelativeVoltageLevel(initialLowVoltageLimit, voltageLimits.get(VoltageLimitType.LOW_VOLTAGE_LIMIT)), TypedValue.VOLTAGE) + .withTypedValue("highVoltageLimit", computeRelativeVoltageLevel(initialHighVoltage, voltageLimits.get(VoltageLimitType.HIGH_VOLTAGE_LIMIT)), TypedValue.VOLTAGE) + .withSeverity(TypedValue.TRACE_SEVERITY) + .build()); + }); + } + + private static String computeRelativeVoltageLevel(final double initialVoltageLimit, @Nullable final VoltageLimitOverride override) { + if (override == null) { + return VOLTAGE_FORMAT.format(initialVoltageLimit); + } else { + double voltage = (override.isRelative() ? initialVoltageLimit : 0.0) + override.getLimit(); + return VOLTAGE_FORMAT.format(initialVoltageLimit) + " → " + VOLTAGE_FORMAT.format(voltage); + } + } + + /** + * We count modifications per substation only once in {@link #filterService}, not twice + */ + @VisibleForTesting + enum CounterToIncrement { + NONE, DEFAULT, MODIFICATION, BOTH + } } diff --git a/src/test/java/org/gridsuite/voltageinit/server/VoltageInitParametersTest.java b/src/test/java/org/gridsuite/voltageinit/server/VoltageInitParametersTest.java index a7542ce..37f2649 100644 --- a/src/test/java/org/gridsuite/voltageinit/server/VoltageInitParametersTest.java +++ b/src/test/java/org/gridsuite/voltageinit/server/VoltageInitParametersTest.java @@ -7,34 +7,12 @@ package org.gridsuite.voltageinit.server; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.powsybl.commons.reporter.Report; -import com.powsybl.commons.reporter.ReporterModel; -import com.powsybl.commons.reporter.TypedValue; -import com.powsybl.iidm.network.IdentifiableType; -import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.VariantManagerConstants; -import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; -import com.powsybl.network.store.client.NetworkStoreService; -import com.powsybl.network.store.client.PreloadingStrategy; -import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; -import com.powsybl.openreac.parameters.input.OpenReacParameters; -import com.powsybl.openreac.parameters.input.VoltageLimitOverride; import org.gridsuite.voltageinit.server.dto.parameters.FilterEquipments; -import org.gridsuite.voltageinit.server.dto.parameters.IdentifiableAttributes; import org.gridsuite.voltageinit.server.dto.parameters.VoltageInitParametersInfos; import org.gridsuite.voltageinit.server.dto.parameters.VoltageLimitInfos; -import org.gridsuite.voltageinit.server.entities.parameters.FilterEquipmentsEmbeddable; import org.gridsuite.voltageinit.server.entities.parameters.VoltageInitParametersEntity; -import org.gridsuite.voltageinit.server.entities.parameters.VoltageLimitEntity; import org.gridsuite.voltageinit.server.repository.parameters.VoltageInitParametersRepository; -import org.gridsuite.voltageinit.server.service.VoltageInitRunContext; -import org.gridsuite.voltageinit.server.service.VoltageInitService; -import org.gridsuite.voltageinit.server.service.VoltageInitWorkerService; -import org.gridsuite.voltageinit.server.service.parameters.FilterService; -import org.gridsuite.voltageinit.server.service.parameters.VoltageInitParametersService; -import org.gridsuite.voltageinit.server.util.VoltageLimitParameterType; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -42,18 +20,17 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.transaction.annotation.Transactional; -import java.util.*; +import java.util.List; +import java.util.UUID; import static org.gridsuite.voltageinit.utils.assertions.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.BDDMockito.given; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -70,68 +47,18 @@ public class VoltageInitParametersTest { private static final String URI_PARAMETERS_GET_PUT = URI_PARAMETERS_BASE + "/"; - private static final UUID NETWORK_UUID = UUID.fromString("7928181c-7977-4592-ba19-88027e4254e4"); - private static final String VARIANT_ID_1 = "variant_1"; - private static final UUID FILTER_UUID_1 = UUID.fromString("1a3d23a6-7a4c-11ee-b962-0242ac120002"); - private static final UUID FILTER_UUID_2 = UUID.fromString("f5c30082-7a4f-11ee-b962-0242ac120002"); - private static final String FILTER_1 = "FILTER_1"; - private static final String FILTER_2 = "FILTER_2"; - - private Network network; - - @Autowired - VoltageInitService voltageInitService; - - @Autowired - VoltageInitParametersService voltageInitParametersService; - @Autowired - protected MockMvc mockMvc; + private MockMvc mockMvc; @Autowired - protected ObjectMapper mapper; + private ObjectMapper mapper; @Autowired private VoltageInitParametersRepository parametersRepository; - @MockBean - private NetworkStoreService networkStoreService; - - @MockBean - private FilterService filterService; - @Before - public void setup() { - network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl()); - network.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, VARIANT_ID_1); - network.getVariantManager().setWorkingVariant(VARIANT_ID_1); - given(networkStoreService.getNetwork(NETWORK_UUID, PreloadingStrategy.COLLECTION)).willReturn(network); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - - network.getVoltageLevel("VLGEN").setLowVoltageLimit(10.); - network.getVoltageLevel("VLGEN").setHighVoltageLimit(20.); - network.getVoltageLevel("VLHV1").setHighVoltageLimit(20.); - network.getVoltageLevel("VLHV2").setLowVoltageLimit(10.); - List equipmentsList1 = new ArrayList<>(); - List identifiableAttributes = new ArrayList<>(); - identifiableAttributes.add(new IdentifiableAttributes("VLGEN", IdentifiableType.VOLTAGE_LEVEL, null)); - identifiableAttributes.add(new IdentifiableAttributes("VLHV1", IdentifiableType.VOLTAGE_LEVEL, null)); - identifiableAttributes.add(new IdentifiableAttributes("VLHV2", IdentifiableType.VOLTAGE_LEVEL, null)); - identifiableAttributes.add(new IdentifiableAttributes("VLLOAD", IdentifiableType.VOLTAGE_LEVEL, null)); - equipmentsList1.add(new FilterEquipments(FILTER_UUID_1, FILTER_1, identifiableAttributes, List.of())); - - List equipmentsList2 = new ArrayList<>(); - List identifiableAttributes2 = new ArrayList<>(); - identifiableAttributes2.add(new IdentifiableAttributes("VLLOAD", IdentifiableType.VOLTAGE_LEVEL, null)); - equipmentsList2.add(new FilterEquipments(FILTER_UUID_2, FILTER_2, identifiableAttributes2, List.of())); - given(filterService.exportFilters(List.of(FILTER_UUID_1), NETWORK_UUID, VARIANT_ID_1)).willReturn(equipmentsList1); - given(filterService.exportFilters(List.of(FILTER_UUID_2), NETWORK_UUID, VARIANT_ID_1)).willReturn(equipmentsList2); - - parametersRepository.deleteAll(); - } - @After - public void tearOff() { + public void cleanDB() { parametersRepository.deleteAll(); } @@ -239,12 +166,11 @@ public void testDuplicate() throws Exception { } /** Save parameters into the repository and return its UUID. */ - protected UUID saveAndRetunId(VoltageInitParametersInfos parametersInfos) { - parametersRepository.save(parametersInfos.toEntity()); - return parametersRepository.findAll().get(0).getId(); + private UUID saveAndRetunId(VoltageInitParametersInfos parametersInfos) { + return parametersRepository.save(parametersInfos.toEntity()).getId(); } - protected VoltageInitParametersInfos buildParameters() { + private static VoltageInitParametersInfos buildParameters() { return VoltageInitParametersInfos.builder() .voltageLimitsDefault(List.of()) .voltageLimitsModification(List.of()) @@ -265,7 +191,7 @@ protected VoltageInitParametersInfos buildParameters() { .build(); } - protected VoltageInitParametersInfos buildParametersUpdate() { + private static VoltageInitParametersInfos buildParametersUpdate() { return VoltageInitParametersInfos.builder() .voltageLimitsModification(List.of(VoltageLimitInfos.builder() .priority(0) @@ -298,87 +224,4 @@ protected VoltageInitParametersInfos buildParametersUpdate() { .build())) .build(); } - - @Test - public void testBuildSpecificVoltageLimits() { - VoltageLimitEntity voltageLimit = new VoltageLimitEntity(UUID.randomUUID(), 5., 10., 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); - VoltageLimitEntity voltageLimit2 = new VoltageLimitEntity(UUID.randomUUID(), 44., 88., 1, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_2, FILTER_2))); - - VoltageInitParametersEntity voltageInitParameters = new VoltageInitParametersEntity(UUID.randomUUID(), null, "", List.of(voltageLimit, voltageLimit2), null, null, null); - parametersRepository.save(voltageInitParameters); - VoltageInitRunContext context = new VoltageInitRunContext(NETWORK_UUID, VARIANT_ID_1, null, null, null, "", "", parametersRepository.findAll().get(0).getId(), new HashMap<>()); - OpenReacParameters openReacParameters = voltageInitParametersService.buildOpenReacParameters(context, network); - assertEquals(4, openReacParameters.getSpecificVoltageLimits().size()); - //No override should be relative since there are no voltage limit modification - assertThat(openReacParameters.getSpecificVoltageLimits().stream().allMatch(voltageLimitOverride -> !voltageLimitOverride.isRelative())).isTrue(); - //VLHV1, VLHV2 and VLLOAD should be applied default voltage limits since those are missing one or both limits - assertThat(openReacParameters.getSpecificVoltageLimits().stream().anyMatch(voltageLimitOverride -> "VLHV1".equals(voltageLimitOverride.getVoltageLevelId()))).isTrue(); - assertEquals(1, openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLHV1".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).count()); - assertThat(openReacParameters.getSpecificVoltageLimits().stream().anyMatch(voltageLimitOverride -> "VLHV2".equals(voltageLimitOverride.getVoltageLevelId()))).isTrue(); - assertEquals(1, openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLHV2".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).count()); - assertThat(openReacParameters.getSpecificVoltageLimits().stream().anyMatch(voltageLimitOverride -> "VLLOAD".equals(voltageLimitOverride.getVoltageLevelId()))).isTrue(); - assertEquals(1, openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLLOAD".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).count()); - assertEquals(1, openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLLOAD".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).count()); - //The voltage limits attributed to VLLOAD should respectively be 44. and 88. since the priority of FILTER_2, related to VLLOAD, is higher than FILTER_1 - assertEquals(44., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLLOAD".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - assertEquals(88., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLLOAD".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - - //We now add limit modifications in additions to defaults settings - VoltageLimitEntity voltageLimit3 = new VoltageLimitEntity(UUID.randomUUID(), -1., -2., 0, VoltageLimitParameterType.MODIFICATION, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); - voltageInitParameters.setVoltageLimits(List.of(voltageLimit, voltageLimit2, voltageLimit3)); - parametersRepository.save(voltageInitParameters); - context = new VoltageInitRunContext(NETWORK_UUID, VARIANT_ID_1, null, null, null, "", "", parametersRepository.findAll().get(1).getId(), new HashMap<>()); - openReacParameters = voltageInitParametersService.buildOpenReacParameters(context, network); - //There should nox be relative overrides since voltage limit modification are applied - assertThat(openReacParameters.getSpecificVoltageLimits().stream().allMatch(voltageLimitOverride -> !voltageLimitOverride.isRelative())).isFalse(); - //Limits that weren't impacted by default settings are now impacted by modification settings - assertEquals(8, openReacParameters.getSpecificVoltageLimits().size()); - //VLGEN has both it limits set so it should now be impacted by modifications override - assertEquals(-1., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLGEN".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - assertEquals(-2., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLGEN".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - //Because of the modification setting the voltage limits attributed to VLLOAD should now respectively be 43. and 86. - assertEquals(43., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLLOAD".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - assertEquals(86., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLLOAD".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - - // We need to check for the case of relative = true with the modification less than 0 => the new low voltage limit = low voltage limit * -1 - VoltageLimitEntity voltageLimit4 = new VoltageLimitEntity(UUID.randomUUID(), -20.0, 10.0, 0, VoltageLimitParameterType.MODIFICATION, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); - voltageInitParameters.setVoltageLimits(List.of(voltageLimit4)); - parametersRepository.save(voltageInitParameters); - context = new VoltageInitRunContext(NETWORK_UUID, VARIANT_ID_1, null, null, null, "", "", parametersRepository.findAll().get(2).getId(), new HashMap<>()); - openReacParameters = voltageInitParametersService.buildOpenReacParameters(context, network); - //There should have relative true overrides since voltage limit modification are applied for VLGEN - assertTrue(openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLGEN".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).map(VoltageLimitOverride::isRelative).findFirst().get()); - assertEquals(4, openReacParameters.getSpecificVoltageLimits().size()); - // The low voltage limit must be impacted by the modification of the value - assertEquals(-10., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLGEN".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - - // We need to check for the case of relative = false with the modification less than 0 => the new low voltage limit = 0 - VoltageLimitEntity voltageLimit5 = new VoltageLimitEntity(UUID.randomUUID(), 10.0, 10.0, 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); - voltageInitParameters.setVoltageLimits(List.of(voltageLimit4, voltageLimit5)); - parametersRepository.save(voltageInitParameters); - context = new VoltageInitRunContext(NETWORK_UUID, VARIANT_ID_1, null, null, null, "", "", parametersRepository.findAll().get(3).getId(), new HashMap<>()); - openReacParameters = voltageInitParametersService.buildOpenReacParameters(context, network); - //There should have relative false overrides since voltage limit modification are applied for VLHV1 - assertFalse(openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLHV1".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).map(VoltageLimitOverride::isRelative).findFirst().get()); - // The low voltage limit must be impacted by the modification of the value - assertEquals(0., openReacParameters.getSpecificVoltageLimits().stream().filter(voltageLimitOverride -> "VLHV1".equals(voltageLimitOverride.getVoltageLevelId()) && VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT.equals(voltageLimitOverride.getVoltageLimitType())).findAny().get().getLimit()); - } - - @Test - public void testAddRestrictedVoltageLevelReport() { - Map restrictedVoltageLevel = new HashMap<>(); - restrictedVoltageLevel.put("vl", 10.0); - ReporterModel reporter = new ReporterModel("test", "test"); - VoltageInitWorkerService.addRestrictedVoltageLevelReport(restrictedVoltageLevel, reporter); - assertEquals("restrictedVoltageLevels", reporter.getReports().stream().findFirst().get().getReportKey()); - assertEquals("The modifications to the low limits for certain voltage levels have been restricted to avoid negative voltage limits: vl : 10.0", - reporter.getReports().stream().findFirst().get().getDefaultMessage()); - Optional> typedValues = reporter.getReports().stream() - .map(Report::getValues) - .findFirst() - .flatMap(values -> values.entrySet().stream().findFirst()); - assertEquals("reportSeverity", typedValues.map(Map.Entry::getKey).get()); - assertEquals("WARN", typedValues.map(value -> value.getValue().getValue()).get()); - } } - diff --git a/src/test/java/org/gridsuite/voltageinit/server/service/parameters/ParametersTest.java b/src/test/java/org/gridsuite/voltageinit/server/service/parameters/ParametersTest.java new file mode 100644 index 0000000..5cbb9b8 --- /dev/null +++ b/src/test/java/org/gridsuite/voltageinit/server/service/parameters/ParametersTest.java @@ -0,0 +1,271 @@ +/** + * 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/. + */ +package org.gridsuite.voltageinit.server.service.parameters; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.powsybl.commons.reporter.ReporterModel; +import com.powsybl.iidm.network.IdentifiableType; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.VariantManagerConstants; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.network.store.client.NetworkStoreService; +import com.powsybl.network.store.client.PreloadingStrategy; +import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; +import com.powsybl.openreac.parameters.input.OpenReacParameters; +import com.powsybl.openreac.parameters.input.VoltageLimitOverride; +import com.powsybl.openreac.parameters.input.VoltageLimitOverride.VoltageLimitType; +import lombok.extern.slf4j.Slf4j; +import org.assertj.core.api.Condition; +import org.assertj.core.api.ListAssert; +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; +import org.gridsuite.voltageinit.server.dto.parameters.FilterEquipments; +import org.gridsuite.voltageinit.server.dto.parameters.IdentifiableAttributes; +import org.gridsuite.voltageinit.server.entities.parameters.FilterEquipmentsEmbeddable; +import org.gridsuite.voltageinit.server.entities.parameters.VoltageInitParametersEntity; +import org.gridsuite.voltageinit.server.entities.parameters.VoltageLimitEntity; +import org.gridsuite.voltageinit.server.service.VoltageInitRunContext; +import org.gridsuite.voltageinit.server.util.VoltageLimitParameterType; +import org.gridsuite.voltageinit.utils.TestUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.skyscreamer.jsonassert.Customization; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.skyscreamer.jsonassert.comparator.CustomComparator; +import org.skyscreamer.jsonassert.comparator.JSONComparator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureTestEntityManager; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.io.InputStream; +import java.io.StringWriter; +import java.io.Writer; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.condition.NestableCondition.nestable; +import static org.assertj.core.condition.VerboseCondition.verboseCondition; +import static org.mockito.BDDMockito.given; + +@ExtendWith({ MockitoExtension.class, SoftAssertionsExtension.class }) +@SpringBootTest +@AutoConfigureTestEntityManager +@Transactional(propagation = Propagation.REQUIRES_NEW) +@Slf4j +class ParametersTest { + private static final UUID NETWORK_UUID = UUID.fromString("7928181c-7977-4592-ba19-88027e4254e4"); + private static final String VARIANT_ID_1 = "variant_1"; + private static final UUID FILTER_UUID_1 = UUID.fromString("1a3d23a6-7a4c-11ee-b962-0242ac120002"); + private static final UUID FILTER_UUID_2 = UUID.fromString("f5c30082-7a4f-11ee-b962-0242ac120002"); + private static final String FILTER_1 = "FILTER_1"; + private static final String FILTER_2 = "FILTER_2"; + private static final UUID REPORT_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000"); + + private static final JSONComparator REPORTER_COMPARATOR = new CustomComparator(JSONCompareMode.NON_EXTENSIBLE, + // ignore field having uuid changing each run + new Customization("reportTree.subReporters[*].taskValues.parameters_id.value", (o1, o2) -> (o1 == null) == (o2 == null)) + ); + + private Network network; + + @Autowired + private VoltageInitParametersService voltageInitParametersService; + + @Autowired + private TestEntityManager entityManager; + + @Autowired + private ObjectMapper mapper; + + @MockBean + private NetworkStoreService networkStoreService; + + @MockBean + private FilterService filterService; + + @BeforeEach + public void setup() { + network = EurostagTutorialExample1Factory.create(new NetworkFactoryImpl()); + network.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, VARIANT_ID_1); + network.getVariantManager().setWorkingVariant(VARIANT_ID_1); + given(networkStoreService.getNetwork(NETWORK_UUID, PreloadingStrategy.COLLECTION)).willReturn(network); + + network.getVoltageLevel("VLGEN").setLowVoltageLimit(10.); + network.getVoltageLevel("VLGEN").setHighVoltageLimit(20.); + network.getVoltageLevel("VLHV1").setHighVoltageLimit(20.); + network.getVoltageLevel("VLHV2").setLowVoltageLimit(10.); + given(filterService.exportFilters(List.of(FILTER_UUID_1), NETWORK_UUID, VARIANT_ID_1)).willReturn(List.of( + new FilterEquipments(FILTER_UUID_1, FILTER_1, List.of( + new IdentifiableAttributes("VLGEN", IdentifiableType.VOLTAGE_LEVEL, null), + new IdentifiableAttributes("VLHV1", IdentifiableType.VOLTAGE_LEVEL, null), + new IdentifiableAttributes("VLHV2", IdentifiableType.VOLTAGE_LEVEL, null), + new IdentifiableAttributes("VLLOAD", IdentifiableType.VOLTAGE_LEVEL, null) + ), List.of()) + )); + given(filterService.exportFilters(List.of(FILTER_UUID_2), NETWORK_UUID, VARIANT_ID_1)).willReturn(List.of( + new FilterEquipments(FILTER_UUID_2, FILTER_2, List.of(new IdentifiableAttributes("VLLOAD", IdentifiableType.VOLTAGE_LEVEL, null)), List.of()) + )); + } + + private static Consumer assertVoltageLimitOverride(final String levelId, final VoltageLimitType limitType) { + return assertVoltageLimitOverride(levelId, limitType, null); + } + + @SuppressWarnings("unchecked") + private static Consumer assertVoltageLimitOverride(final String levelId, final VoltageLimitType limitType, final Double limit) { + return voltageLimitOverride -> assertThat(voltageLimitOverride).as("voltageLimit override") + .is(nestable("VoltageLimitOverride", Stream.>of( + verboseCondition(actual -> levelId.equals(actual.getVoltageLevelId()), + "to have voltageLevelId=\"" + Objects.toString(levelId, "") + "\"", + actual -> " but is actually \"" + Objects.toString(actual.getVoltageLevelId(), "") + "\""), + verboseCondition(actual -> limitType.equals(actual.getVoltageLimitType()), + "to have voltageLimitType=\"" + Objects.toString(limitType, "") + "\"", + actual -> " but is actually \"" + Objects.toString(actual.getVoltageLimitType(), "") + "\""), + limit == null ? null : verboseCondition(actual -> limit.equals(actual.getLimit()), + "to have limit=" + limit, actual -> " but is actually " + actual.getLimit()) + ).filter(Objects::nonNull).toArray(Condition[]::new))); + } + + private ListAssert testsBuildSpecificVoltageLimitsCommon(List voltageLimits, String reportFilename) throws Exception { + final VoltageInitParametersEntity voltageInitParameters = entityManager.persistFlushFind( + new VoltageInitParametersEntity(null, null, "", voltageLimits, null, null, null) + ); + final VoltageInitRunContext context = new VoltageInitRunContext(NETWORK_UUID, VARIANT_ID_1, null, REPORT_UUID, null, "", "", voltageInitParameters.getId()); + context.setRootReporter(new ReporterModel("VoltageInit", "VoltageInit")); + final OpenReacParameters openReacParameters = voltageInitParametersService.buildOpenReacParameters(context, network); + log.debug("openReac build parameters report: {}", mapper.writeValueAsString(context.getRootReporter())); + JSONAssert.assertEquals("build parameters logs", TestUtils.resourceToString(reportFilename), mapper.writeValueAsString(context.getRootReporter()), REPORTER_COMPARATOR); + return assertThat(openReacParameters.getSpecificVoltageLimits()).as("SpecificVoltageLimits"); + } + + @DisplayName("buildSpecificVoltageLimits: No voltage limit modification") + @Test + void testsBuildSpecificVoltageLimitsSimple() throws Exception { + final VoltageLimitEntity voltageLimit = new VoltageLimitEntity(null, 5., 10., 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); + final VoltageLimitEntity voltageLimit2 = new VoltageLimitEntity(null, 44., 88., 1, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_2, FILTER_2))); + testsBuildSpecificVoltageLimitsCommon(List.of(voltageLimit, voltageLimit2), "reporter_buildOpenReacParameters.json") + .hasSize(4) + //No override should be relative since there is no voltage limit modification + .noneMatch(VoltageLimitOverride::isRelative) + //VLHV1, VLHV2 and VLLOAD should be applied default voltage limits since those are missing one or both limits + .satisfiesExactlyInAnyOrder( + assertVoltageLimitOverride("VLHV1", VoltageLimitType.LOW_VOLTAGE_LIMIT), + assertVoltageLimitOverride("VLHV2", VoltageLimitType.HIGH_VOLTAGE_LIMIT), + //The voltage limits attributed to VLLOAD should respectively be 44. and 88. since the priority of FILTER_2, related to VLLOAD, is higher than FILTER_1 + assertVoltageLimitOverride("VLLOAD", VoltageLimitType.LOW_VOLTAGE_LIMIT, 44.), + assertVoltageLimitOverride("VLLOAD", VoltageLimitType.HIGH_VOLTAGE_LIMIT, 88.) + ); + } + + @DisplayName("buildSpecificVoltageLimits: With voltage limit modifications") + @Test + void testsBuildSpecificVoltageLimitsWithLimitModifications() throws Exception { + final VoltageLimitEntity voltageLimit = new VoltageLimitEntity(null, 5., 10., 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); + final VoltageLimitEntity voltageLimit2 = new VoltageLimitEntity(null, 44., 88., 1, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_2, FILTER_2))); + final VoltageLimitEntity voltageLimit3 = new VoltageLimitEntity(null, -1., -2., 0, VoltageLimitParameterType.MODIFICATION, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); + //We now add limit modifications in additions to defaults settings + testsBuildSpecificVoltageLimitsCommon(List.of(voltageLimit, voltageLimit2, voltageLimit3), "reporter_buildOpenReacParameters_withLimitModifications.json") + //Limits that weren't impacted by default settings are now impacted by modification settings + .hasSize(8) + //There should (not?) be relative overrides since voltage limit modification are applied + .anyMatch(VoltageLimitOverride::isRelative) + //VLGEN has both it limits set so it should now be impacted by modifications override + .satisfiesOnlyOnce(assertVoltageLimitOverride("VLGEN", VoltageLimitType.LOW_VOLTAGE_LIMIT, -1.)) + .satisfiesOnlyOnce(assertVoltageLimitOverride("VLGEN", VoltageLimitType.HIGH_VOLTAGE_LIMIT, -2.)) + //Because of the modification setting the voltage limits attributed to VLLOAD should now respectively be 43. and 86. + .satisfiesOnlyOnce(assertVoltageLimitOverride("VLLOAD", VoltageLimitType.LOW_VOLTAGE_LIMIT, 43.)) + .satisfiesOnlyOnce(assertVoltageLimitOverride("VLLOAD", VoltageLimitType.HIGH_VOLTAGE_LIMIT, 86.)); + } + + @DisplayName("buildSpecificVoltageLimits: Case relative true overrides") + @Test + void testsBuildSpecificVoltageLimitsCaseRelativeTrue() throws Exception { + final VoltageLimitEntity voltageLimit4 = new VoltageLimitEntity(null, -20.0, 10.0, 0, VoltageLimitParameterType.MODIFICATION, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); + // We need to check for the case of relative = true with the modification less than 0 => the new low voltage limit = low voltage limit * -1 + testsBuildSpecificVoltageLimitsCommon(List.of(voltageLimit4), "reporter_buildOpenReacParameters_caseRelativeTrue.json") + .hasSize(4) + // isRelative: There should have relative true overrides since voltage limit modification are applied for VLGEN + // getLimit: The low voltage limit must be impacted by the modification of the value + .containsOnlyOnce(new VoltageLimitOverride("VLGEN", VoltageLimitType.LOW_VOLTAGE_LIMIT, true, -10.0)); + //note: VoltageLimitOverride implement equals() correctly, so we can use it + } + + @DisplayName("buildSpecificVoltageLimits: Case relative false overrides") + @Test + void testsBuildSpecificVoltageLimitsCaseRelativeFalse() throws Exception { + final VoltageLimitEntity voltageLimit4 = new VoltageLimitEntity(null, -20.0, 10.0, 0, VoltageLimitParameterType.MODIFICATION, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); + final VoltageLimitEntity voltageLimit5 = new VoltageLimitEntity(null, 10.0, 10.0, 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(FILTER_UUID_1, FILTER_1))); + // We need to check for the case of relative = false with the modification less than 0 => the new low voltage limit = 0 + testsBuildSpecificVoltageLimitsCommon(List.of(voltageLimit4, voltageLimit5), "reporter_buildOpenReacParameters_caseRelativeFalse.json") + .hasSize(8) + // isRelative: There should have relative false overrides since voltage limit modification are applied for VLHV1 + // getLimit: The low voltage limit must be impacted by the modification of the value + .containsOnlyOnce(new VoltageLimitOverride("VLHV1", VoltageLimitType.LOW_VOLTAGE_LIMIT, false, 0.0)); + } + + @DisplayName("buildSpecificVoltageLimits: fourSubstations study") + @Test + void testsBuildSpecificVoltageLimitsWithFourSubstationStudy() throws Exception { + Mockito.reset(networkStoreService, filterService); //don't use @BeforeEach setup() situation + + try (final InputStream data = this.getClass().getClassLoader().getResourceAsStream("fourSubstations_no_voltage_levels_for_S3VL1_S4VL1_S4VL2.xiidm")) { + network = Network.read("fourSubstations.xiidm", data); + } + final UUID networkUuid = UUID.randomUUID(); + final String variantId = UUID.randomUUID().toString(); + network.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, variantId); + network.getVariantManager().setWorkingVariant(variantId); + given(networkStoreService.getNetwork(networkUuid, PreloadingStrategy.COLLECTION)).willReturn(network); + + final UUID filterUuidS3VL1 = UUID.randomUUID(); + final String filterIdS3VL1 = "FILTER_S3VL1"; + final UUID filterUuidS4VL1 = UUID.randomUUID(); + final String filterIdS4VL1 = "FILTER_S4VL1"; + final UUID filterUuidS4VL2 = UUID.randomUUID(); + final String filterIdS4VL2 = "FILTER_S4VL2"; + given(filterService.exportFilters(List.of(filterUuidS3VL1), networkUuid, variantId)).willReturn(List.of( + new FilterEquipments(filterUuidS3VL1, filterIdS3VL1, List.of(new IdentifiableAttributes("S3VL1", IdentifiableType.VOLTAGE_LEVEL, null)), List.of()) + )); + given(filterService.exportFilters(List.of(filterUuidS4VL1), networkUuid, variantId)).willReturn(List.of( + new FilterEquipments(filterUuidS4VL1, filterIdS4VL1, List.of(new IdentifiableAttributes("S4VL1", IdentifiableType.VOLTAGE_LEVEL, null)), List.of()) + )); + given(filterService.exportFilters(List.of(filterUuidS4VL2), networkUuid, variantId)).willReturn(List.of( + new FilterEquipments(filterUuidS4VL2, filterIdS4VL2, List.of(new IdentifiableAttributes("S4VL2", IdentifiableType.VOLTAGE_LEVEL, null)), List.of()) + )); + + final VoltageLimitEntity vl1 = new VoltageLimitEntity(null, 50.0, 500.0, 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(filterUuidS3VL1, filterIdS3VL1))); + final VoltageLimitEntity vl2 = new VoltageLimitEntity(null, 60.0, 600.0, 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(filterUuidS4VL1, filterIdS4VL1))); + final VoltageLimitEntity vl3 = new VoltageLimitEntity(null, 70.0, 700.0, 0, VoltageLimitParameterType.DEFAULT, List.of(new FilterEquipmentsEmbeddable(filterUuidS4VL2, filterIdS4VL2))); + final VoltageLimitEntity vl4 = new VoltageLimitEntity(null, -20.0, 10.0, 0, VoltageLimitParameterType.MODIFICATION, List.of(new FilterEquipmentsEmbeddable(filterUuidS3VL1, filterIdS3VL1))); + final VoltageInitParametersEntity voltageInitParameters = entityManager.persistFlushFind( + new VoltageInitParametersEntity(null, null, "", List.of(vl1, vl2, vl3, vl4), null, null, null) + ); + + final VoltageInitRunContext context = new VoltageInitRunContext(networkUuid, variantId, null, REPORT_UUID, null, "", "", voltageInitParameters.getId()); + context.setRootReporter(new ReporterModel("VoltageInit", "VoltageInit")); + final OpenReacParameters openReacParameters = voltageInitParametersService.buildOpenReacParameters(context, network); + if (log.isDebugEnabled()) { + log.debug("openReac build parameters report: {}", mapper.writeValueAsString(context.getRootReporter())); + final Writer writer = new StringWriter(); + ((ReporterModel) context.getRootReporter()).export(writer); + log.debug("openReac report: {}", writer.toString()); + } + JSONAssert.assertEquals("build parameters logs", TestUtils.resourceToString("reporter_fourSubstations_noVoltageLimits.json"), mapper.writeValueAsString(context.getRootReporter()), REPORTER_COMPARATOR); + } +} diff --git a/src/test/java/org/gridsuite/voltageinit/service/ReportServiceTest.java b/src/test/java/org/gridsuite/voltageinit/service/ReportServiceTest.java index ab1f996..e2056ca 100644 --- a/src/test/java/org/gridsuite/voltageinit/service/ReportServiceTest.java +++ b/src/test/java/org/gridsuite/voltageinit/service/ReportServiceTest.java @@ -30,10 +30,12 @@ import static org.gridsuite.voltageinit.utils.TestUtils.resourceToString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.util.UUID; /** @@ -65,8 +67,8 @@ private void configureWireMockServer(String reportJson) { } @Before - public void setUp() throws IOException { - String reportJson = resourceToString("/report.json"); + public void setUp() throws IOException, URISyntaxException { + String reportJson = resourceToString("report.json"); server = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort()); server.start(); WireMock.configureFor("localhost", server.port()); diff --git a/src/test/java/org/gridsuite/voltageinit/utils/TestUtils.java b/src/test/java/org/gridsuite/voltageinit/utils/TestUtils.java index 20032d2..1168742 100644 --- a/src/test/java/org/gridsuite/voltageinit/utils/TestUtils.java +++ b/src/test/java/org/gridsuite/voltageinit/utils/TestUtils.java @@ -7,11 +7,11 @@ package org.gridsuite.voltageinit.utils; -import com.google.common.io.ByteStreams; -import org.junit.platform.commons.util.StringUtils; - import java.io.IOException; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; /** * @author Anis Touri @@ -19,10 +19,10 @@ public final class TestUtils { private TestUtils() { + throw new RuntimeException("Utility class can't be instantiated"); } - public static String resourceToString(String resource) throws IOException { - String content = new String(ByteStreams.toByteArray(TestUtils.class.getResourceAsStream(resource)), StandardCharsets.UTF_8); - return StringUtils.replaceWhitespaceCharacters(content, ""); + public static String resourceToString(final String resource) throws IOException, URISyntaxException { + return Files.readString(Paths.get(ClassLoader.getSystemClassLoader().getResource(resource).toURI()), StandardCharsets.UTF_8).trim(); } } diff --git a/src/test/resources/fourSubstations_no_voltage_levels_for_S3VL1_S4VL1_S4VL2.xiidm b/src/test/resources/fourSubstations_no_voltage_levels_for_S3VL1_S4VL1_S4VL2.xiidm new file mode 100644 index 0000000..d3c2ff7 --- /dev/null +++ b/src/test/resources/fourSubstations_no_voltage_levels_for_S3VL1_S4VL1_S4VL2.xiidm @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/reporter_buildOpenReacParameters.json b/src/test/resources/reporter_buildOpenReacParameters.json new file mode 100644 index 0000000..76bdeec --- /dev/null +++ b/src/test/resources/reporter_buildOpenReacParameters.json @@ -0,0 +1,115 @@ +{ + "version": "1.0", + "reportTree": { + "taskKey": "VoltageInit", + "subReporters": [ + { + "taskKey": "VoltageInitParameters", + "taskValues": { + "parameters_id": { + "value": "11111111-1111-1111-1111-111111111111", + "type": "ID" + } + }, + "reports": [ + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV2", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 10.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "10.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV1", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "20.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 5.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLLOAD", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 88.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 44.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "missingVoltageLimits", + "values": { + "nbMissingVoltageLimits": { + "value": 3 + }, + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + } + } + }, + { + "reportKey": "voltageLimitModifications", + "values": { + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + }, + "nbVoltageLimitModifications": { + "value": 0 + } + } + } + ] + } + ] + }, + "dics": { + "default": { + "voltageLimitModifications": "Voltage limits of ${nbVoltageLimitModifications} voltage levels have been modified according to user input.", + "VoltageInitParameters": "VoltageInit parameters", + "VoltageInit": "VoltageInit", + "missingVoltageLimits": "Missing voltage limits of ${nbMissingVoltageLimits} voltage levels have been replaced with user-defined default values.", + "voltageLimitModified": "Voltage limits of ${voltageLevelId} modified: low voltage limit = ${lowVoltageLimit}, high voltage limit = ${highVoltageLimit}" + } + } +} diff --git a/src/test/resources/reporter_buildOpenReacParameters_caseRelativeFalse.json b/src/test/resources/reporter_buildOpenReacParameters_caseRelativeFalse.json new file mode 100644 index 0000000..e6e7b3e --- /dev/null +++ b/src/test/resources/reporter_buildOpenReacParameters_caseRelativeFalse.json @@ -0,0 +1,149 @@ +{ + "version": "1.0", + "reportTree": { + "taskKey": "VoltageInit", + "subReporters": [ + { + "taskKey": "VoltageInitParameters", + "taskValues": { + "parameters_id": { + "value": "11111111-1111-1111-1111-111111111111", + "type": "ID" + } + }, + "reports": [ + { + "reportKey": "restrictedVoltageLevels", + "values": { + "reportSeverity": { + "value": "WARN", + "type": "SEVERITY" + }, + "joinedVoltageLevelsIds": { + "value": "VLHV2 : -10.0 kV, VLHV1 : 0.0 kV, VLGEN : -10.0 kV, VLLOAD : 0.0 kV" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV2", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 20.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "10.0 kV → 0.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV1", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "20.0 kV → 30.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 0.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLGEN", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "20.0 kV → 30.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "10.0 kV → 0.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLLOAD", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 20.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 0.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "missingVoltageLimits", + "values": { + "nbMissingVoltageLimits": { + "value": 3 + }, + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + } + } + }, + { + "reportKey": "voltageLimitModifications", + "values": { + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + }, + "nbVoltageLimitModifications": { + "value": 4 + } + } + } + ] + } + ] + }, + "dics": { + "default": { + "restrictedVoltageLevels": "The modifications to the low limits for certain voltage levels have been restricted to avoid negative voltage limits: ${joinedVoltageLevelsIds}", + "voltageLimitModifications": "Voltage limits of ${nbVoltageLimitModifications} voltage levels have been modified according to user input.", + "VoltageInitParameters": "VoltageInit parameters", + "VoltageInit": "VoltageInit", + "missingVoltageLimits": "Missing voltage limits of ${nbMissingVoltageLimits} voltage levels have been replaced with user-defined default values.", + "voltageLimitModified": "Voltage limits of ${voltageLevelId} modified: low voltage limit = ${lowVoltageLimit}, high voltage limit = ${highVoltageLimit}" + } + } +} diff --git a/src/test/resources/reporter_buildOpenReacParameters_caseRelativeTrue.json b/src/test/resources/reporter_buildOpenReacParameters_caseRelativeTrue.json new file mode 100644 index 0000000..11e4c78 --- /dev/null +++ b/src/test/resources/reporter_buildOpenReacParameters_caseRelativeTrue.json @@ -0,0 +1,128 @@ +{ + "version": "1.0", + "reportTree": { + "taskKey": "VoltageInit", + "subReporters": [ + { + "taskKey": "VoltageInitParameters", + "taskValues": { + "parameters_id": { + "value": "11111111-1111-1111-1111-111111111111", + "type": "ID" + } + }, + "reports": [ + { + "reportKey": "restrictedVoltageLevels", + "values": { + "reportSeverity": { + "value": "WARN", + "type": "SEVERITY" + }, + "joinedVoltageLevelsIds": { + "value": "VLHV2 : -10.0 kV, VLGEN : -10.0 kV" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV2", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "10.0 kV → 0.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV1", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "20.0 kV → 30.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLGEN", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "20.0 kV → 30.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "10.0 kV → 0.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "missingVoltageLimits", + "values": { + "nbMissingVoltageLimits": { + "value": 0 + }, + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + } + } + }, + { + "reportKey": "voltageLimitModifications", + "values": { + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + }, + "nbVoltageLimitModifications": { + "value": 3 + } + } + } + ] + } + ] + }, + "dics": { + "default": { + "restrictedVoltageLevels": "The modifications to the low limits for certain voltage levels have been restricted to avoid negative voltage limits: ${joinedVoltageLevelsIds}", + "voltageLimitModifications": "Voltage limits of ${nbVoltageLimitModifications} voltage levels have been modified according to user input.", + "VoltageInitParameters": "VoltageInit parameters", + "VoltageInit": "VoltageInit", + "missingVoltageLimits": "Missing voltage limits of ${nbMissingVoltageLimits} voltage levels have been replaced with user-defined default values.", + "voltageLimitModified": "Voltage limits of ${voltageLevelId} modified: low voltage limit = ${lowVoltageLimit}, high voltage limit = ${highVoltageLimit}" + } + } +} diff --git a/src/test/resources/reporter_buildOpenReacParameters_withLimitModifications.json b/src/test/resources/reporter_buildOpenReacParameters_withLimitModifications.json new file mode 100644 index 0000000..b849d44 --- /dev/null +++ b/src/test/resources/reporter_buildOpenReacParameters_withLimitModifications.json @@ -0,0 +1,136 @@ +{ + "version": "1.0", + "reportTree": { + "taskKey": "VoltageInit", + "subReporters": [ + { + "taskKey": "VoltageInitParameters", + "taskValues": { + "parameters_id": { + "value": "11111111-1111-1111-1111-111111111111", + "type": "ID" + } + }, + "reports": [ + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV2", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 8.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "10.0 kV → 9.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLHV1", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "20.0 kV → 18.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 4.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLGEN", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "20.0 kV → 18.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "10.0 kV → 9.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "VLLOAD", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 86.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 43.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "missingVoltageLimits", + "values": { + "nbMissingVoltageLimits": { + "value": 3 + }, + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + } + } + }, + { + "reportKey": "voltageLimitModifications", + "values": { + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + }, + "nbVoltageLimitModifications": { + "value": 4 + } + } + } + ] + } + ] + }, + "dics": { + "default": { + "voltageLimitModifications": "Voltage limits of ${nbVoltageLimitModifications} voltage levels have been modified according to user input.", + "VoltageInitParameters": "VoltageInit parameters", + "VoltageInit": "VoltageInit", + "missingVoltageLimits": "Missing voltage limits of ${nbMissingVoltageLimits} voltage levels have been replaced with user-defined default values.", + "voltageLimitModified": "Voltage limits of ${voltageLevelId} modified: low voltage limit = ${lowVoltageLimit}, high voltage limit = ${highVoltageLimit}" + } + } +} diff --git a/src/test/resources/reporter_fourSubstations_noVoltageLimits.json b/src/test/resources/reporter_fourSubstations_noVoltageLimits.json new file mode 100644 index 0000000..19c7c68 --- /dev/null +++ b/src/test/resources/reporter_fourSubstations_noVoltageLimits.json @@ -0,0 +1,115 @@ +{ + "version": "1.0", + "reportTree": { + "taskKey": "VoltageInit", + "subReporters": [ + { + "taskKey": "VoltageInitParameters", + "taskValues": { + "parameters_id": { + "value": "11111111-1111-1111-11111111111111111", + "type": "ID" + } + }, + "reports": [ + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "S4VL1", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 600.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 60.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "S4VL2", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 700.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 70.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "voltageLimitModified", + "values": { + "voltageLevelId": { + "value": "S3VL1", + "type": "VOLTAGE_LEVEL" + }, + "reportSeverity": { + "value": "TRACE", + "type": "SEVERITY" + }, + "highVoltageLimit": { + "value": "NaN → 510.0 kV", + "type": "VOLTAGE" + }, + "lowVoltageLimit": { + "value": "NaN → 30.0 kV", + "type": "VOLTAGE" + } + } + }, + { + "reportKey": "missingVoltageLimits", + "values": { + "nbMissingVoltageLimits": { + "value": 3 + }, + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + } + } + }, + { + "reportKey": "voltageLimitModifications", + "values": { + "reportSeverity": { + "value": "INFO", + "type": "SEVERITY" + }, + "nbVoltageLimitModifications": { + "value": 1 + } + } + } + ] + } + ] + }, + "dics": { + "default": { + "voltageLimitModifications": "Voltage limits of ${nbVoltageLimitModifications} voltage levels have been modified according to user input.", + "VoltageInitParameters": "VoltageInit parameters", + "VoltageInit": "VoltageInit", + "missingVoltageLimits": "Missing voltage limits of ${nbMissingVoltageLimits} voltage levels have been replaced with user-defined default values.", + "voltageLimitModified": "Voltage limits of ${voltageLevelId} modified: low voltage limit = ${lowVoltageLimit}, high voltage limit = ${highVoltageLimit}" + } + } +}