Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permanent limit is now mandatory in IIDM #2636

Merged
merged 38 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b2c507f
Make permanent limit mandatory in IIDM.
annetill Jul 5, 2023
8a978f2
Adapt CGMES import. No limits at all if permanent limit is missing.
annetill Jul 6, 2023
9b677f0
Merge branch 'main' into patl-mandatory
annetill Jul 6, 2023
f59046c
log an error for loading limit sets missing a permanent limit; remove…
zamarrenolm Jul 7, 2023
88ec372
keep the context, report as ignored
zamarrenolm Jul 7, 2023
76c4a1f
Merge branch 'main' into patl-mandatory
zamarrenolm Jul 7, 2023
ec80d69
Merge branch 'main' into patl-mandatory
annetill Nov 9, 2023
a192a71
Merge branch 'main' into patl-mandatory
annetill Nov 14, 2023
49077dc
Merge branch 'main' into patl-mandatory
So-Fras Nov 23, 2023
f55950e
First attempt at moving permanent limit check from iidm to cgmes-conv…
So-Fras Nov 30, 2023
fc40d6d
Add 1.12 xsd, IidmVersion and set current version to 1.12
flo-dup Dec 4, 2023
0009bab
Create 1.12 test references for versioned unit tests
flo-dup Dec 4, 2023
946210a
Create 1.12 json unit test references
flo-dup Dec 4, 2023
145f693
Create iidm equipment unit test reference
flo-dup Dec 4, 2023
55fe19f
Update non-versioned unit tests
flo-dup Dec 4, 2023
dffd0db
Update AbstractVersionableNetworkExtensionSerDe classes
flo-dup Dec 4, 2023
0b7b83b
Merge branch 'main' into evolution_xiidm/1.12
annetill Dec 15, 2023
e812c00
Merge branch 'evolution_xiidm/1.12' into patl-mandatory
So-Fras Dec 15, 2023
18daeff
Put lowest tatl coefficient as a percentage in cgmes import properties
So-Fras Dec 15, 2023
e816bac
Prepare permanent limit check for iidm 1.12
So-Fras Dec 15, 2023
87d4a2d
Merge branch 'main' into evolution_xiidm/1.12
annetill Dec 18, 2023
32a62f6
Fix.
annetill Dec 18, 2023
5be68b0
Fixing the fix
flo-dup Dec 19, 2023
d823938
Fixing further
flo-dup Dec 19, 2023
dcf73e4
Merge branch 'evolution_xiidm/1.12' into patl-mandatory
annetill Dec 19, 2023
bb7261f
Try to fix a little bit.
annetill Dec 19, 2023
57f253d
Fix bug
olperr1 Jan 5, 2024
6e62a7f
Extract missing permanent limit fix method in a new class ('LoadingLi…
olperr1 Jan 5, 2024
ed065dd
Fix reported messages + add unit tests
olperr1 Jan 8, 2024
9b1cf8b
Add unit tests on IIDM import
olperr1 Jan 8, 2024
6f781d6
Refactoring to fix the limits before they are added to the network
olperr1 Jan 8, 2024
792aab3
Move checks regarding limits from AbstractLoadingLimitsAdder to Abstr…
So-Fras Jan 9, 2024
2e1906c
Update iidm/iidm-api/src/main/java/com/powsybl/iidm/network/Validatio…
So-Fras Jan 9, 2024
00b34c2
Update iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/Abs…
So-Fras Jan 9, 2024
9dd529a
Merge branch 'main' into patl-mandatory
olperr1 Jan 10, 2024
b226516
code review
olperr1 Jan 15, 2024
c2b89b8
Code review
olperr1 Jan 16, 2024
b8d229e
Merge branch 'main' into patl-mandatory
olperr1 Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,14 @@ private Conversion.Config config(Properties p) {
getFormat(),
p,
DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER,
defaultValueConfig))
.setMissingPermanentLimitPercentage(
Parameter.readDouble(
getFormat(),
p,
MISSING_PERMANENT_LIMIT_PERCENTAGE_PARAMETER,
defaultValueConfig));

String namingStrategy = Parameter.readString(getFormat(), p, NAMING_STRATEGY_PARAMETER, defaultValueConfig);

// Build the naming strategy with the default uuid namespace for creating name-based uuids
Expand Down Expand Up @@ -554,6 +561,7 @@ private void copyStream(ReadOnlyDataSource from, DataSource to, String fromName,
public static final String STORE_CGMES_CONVERSION_CONTEXT_AS_NETWORK_EXTENSION = "iidm.import.cgmes.store-cgmes-conversion-context-as-network-extension";
public static final String IMPORT_NODE_BREAKER_AS_BUS_BREAKER = "iidm.import.cgmes.import-node-breaker-as-bus-breaker";
public static final String DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED = "iidm.import.cgmes.disconnect-dangling-line-if-boundary-side-is-disconnected";
public static final String MISSING_PERMANENT_LIMIT_PERCENTAGE = "iidm.import.cgmes.missing-permanent-limit-percentage";
public static final String IMPORT_CGM_WITH_SUBNETWORKS = "iidm.import.cgmes.cgm-with-subnetworks";
public static final String IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY = "iidm.import.cgmes.cgm-with-subnetworks-defined-by";

Expand Down Expand Up @@ -674,6 +682,12 @@ private void copyStream(ReadOnlyDataSource from, DataSource to, String fromName,
SubnetworkDefinedBy.MODELING_AUTHORITY.name(),
Arrays.stream(SubnetworkDefinedBy.values()).map(Enum::name).collect(Collectors.toList()));

public static final Parameter MISSING_PERMANENT_LIMIT_PERCENTAGE_PARAMETER = new Parameter(
MISSING_PERMANENT_LIMIT_PERCENTAGE,
ParameterType.DOUBLE,
"Percentage applied to lowest TATL limit to use as PATL when PATL is missing",
100.);

private static final List<Parameter> STATIC_PARAMETERS = List.of(
ALLOW_UNSUPPORTED_TAP_CHANGERS_PARAMETER,
CHANGE_SIGN_FOR_SHUNT_REACTIVE_POWER_FLOW_INITIAL_STATE_PARAMETER,
Expand All @@ -694,7 +708,8 @@ private void copyStream(ReadOnlyDataSource from, DataSource to, String fromName,
IMPORT_NODE_BREAKER_AS_BUS_BREAKER_PARAMETER,
DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER,
IMPORT_CGM_WITH_SUBNETWORKS_PARAMETER,
IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY_PARAMETER);
IMPORT_CGM_WITH_SUBNETWORKS_DEFINED_BY_PARAMETER,
MISSING_PERMANENT_LIMIT_PERCENTAGE_PARAMETER);

private final Parameter boundaryLocationParameter;
private final Parameter preProcessorsParameter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,18 @@ public void setXfmr3StructuralRatio(Xfmr3StructuralRatioInterpretationAlternativ
xfmr3StructuralRatio = alternative;
}

public double getMissingPermanentLimitPercentage() {
return missingPermanentLimitPercentage;
}

public Config setMissingPermanentLimitPercentage(double missingPermanentLimitPercentage) {
if (missingPermanentLimitPercentage < 0 || missingPermanentLimitPercentage > 100) {
throw new IllegalArgumentException("Missing permanent limit percentage must be between 0 and 100.");
}
this.missingPermanentLimitPercentage = missingPermanentLimitPercentage;
return this;
}

public CgmesImport.FictitiousSwitchesCreationMode getCreateFictitiousSwitchesForDisconnectedTerminalsMode() {
return createFictitiousSwitchesForDisconnectedTerminalsMode;
}
Expand Down Expand Up @@ -1018,6 +1030,8 @@ public boolean disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected() {
private Xfmr3RatioPhaseInterpretationAlternative xfmr3RatioPhase = Xfmr3RatioPhaseInterpretationAlternative.NETWORK_SIDE;
private Xfmr3ShuntInterpretationAlternative xfmr3Shunt = Xfmr3ShuntInterpretationAlternative.NETWORK_SIDE;
private Xfmr3StructuralRatioInterpretationAlternative xfmr3StructuralRatio = Xfmr3StructuralRatioInterpretationAlternative.STAR_BUS_SIDE;

private double missingPermanentLimitPercentage = 100;
}

private final CgmesModel cgmes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*/
package com.powsybl.cgmes.conversion;

import com.google.common.collect.Iterables;
import com.powsybl.iidm.network.LoadingLimits;
import com.powsybl.iidm.network.LoadingLimitsAdder;

import java.util.HashMap;
Expand All @@ -34,15 +32,9 @@ public class LoadingLimitsMapping {
void addAll() {
for (Map.Entry<String, LoadingLimitsAdder<?, ?>> entry : adders.entrySet()) {
if (!Double.isNaN(entry.getValue().getPermanentLimit()) || entry.getValue().hasTemporaryLimits()) {
LoadingLimits limits = entry.getValue().add();
if (Double.isNaN(limits.getPermanentLimit())) {
double fixedPermanentLimit = Iterables.get(limits.getTemporaryLimits(), 0).getValue();
context.fixed("Operational Limit Set of " + entry.getKey(),
"An operational limit set without permanent limit is considered with permanent limit" +
"equal to lowest TATL value",
Double.NaN, fixedPermanentLimit);
limits.setPermanentLimit(fixedPermanentLimit);
}
entry.getValue()
.fixLimits(context.config().getMissingPermanentLimitPercentage(), context::fixed)
.add();
}
}
adders.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.io.IOException;
import java.nio.file.FileSystem;
Expand All @@ -40,6 +43,7 @@
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.powsybl.iidm.network.PhaseTapChanger.RegulationMode.CURRENT_LIMITER;
import static com.powsybl.iidm.network.StaticVarCompensator.RegulationMode.*;
Expand Down Expand Up @@ -362,15 +366,30 @@ void microBEMissingShuntRegulatingControlId() {
assertEquals(shunt.getTerminal(), shunt.getRegulatingTerminal());
}

@Test
void microBEUndefinedPatl() {
Network network = new CgmesImport().importData(CgmesConformity1ModifiedCatalog.microGridBaseCaseBEUndefinedPatl().dataSource(),
@ParameterizedTest(name = "{1}")
@MethodSource("getMicroBEUndefinedPatlParameters")
void microBEUndefinedPatl(double expectedPermanentLimitValue, Double percentage) {
InMemoryPlatformConfig platformConfig = new InMemoryPlatformConfig(fileSystem);
if (percentage != null) {
platformConfig.createModuleConfig("import-export-parameters-default-value")
.setStringProperty(CgmesImport.MISSING_PERMANENT_LIMIT_PERCENTAGE, percentage.toString());
}

Network network = new CgmesImport(platformConfig).importData(CgmesConformity1ModifiedCatalog.microGridBaseCaseBEUndefinedPatl().dataSource(),
NetworkFactory.findDefault(), importParams);
Line line = network.getLine("ffbabc27-1ccd-4fdc-b037-e341706c8d29");
CurrentLimits limits = line.getCurrentLimits1().orElse(null);
assertNotNull(limits);
assertEquals(2, limits.getTemporaryLimits().size());
assertEquals(1312.0, limits.getPermanentLimit(), 0.0);
assertEquals(expectedPermanentLimitValue, limits.getPermanentLimit(), 0.001);
}

static Stream<Arguments> getMicroBEUndefinedPatlParameters() {
return Stream.of(
Arguments.of(1312., null),
Arguments.of(1312., 100.),
Arguments.of(984., 75.)
);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
*/
package com.powsybl.iidm.network;

import com.powsybl.iidm.network.util.LoadingLimitsUtil;

import java.util.Collection;

/**
*
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
Expand All @@ -31,9 +35,100 @@ interface TemporaryLimitAdder<A> {

TemporaryLimitAdder<A> beginTemporaryLimit();

/**
* <p>Get the permanent limit to add.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @return the permanent limit
*/
double getPermanentLimit();

/**
* <p>Get the temporary limit value corresponding to the given acceptable duration.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @param acceptableDuration the acceptable duration
* @return the corresponding temporary limit value, or <code>Double.NaN</code> if none is defined.
*/
double getTemporaryLimitValue(int acceptableDuration);

/**
* <p>Get the temporary limit value corresponding to the given name.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @param name the temporary limit name
* @return the corresponding temporary limit value, or <code>Double.NaN</code> if none is defined.
*/
double getTemporaryLimitValue(String name);

/**
* <p>Get the temporary limit value corresponding to the given name.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @param name the temporary limit name
* @return the corresponding temporary limit value, or <code>Integer.MAX_VALUE</code> if none is defined.
*/
int getTemporaryLimitAcceptableDuration(String name);

/**
* <p>Get the lowest value of the temporary limits to create.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @return the lowest temporary limit value, or <code>Double.NaN</code> if no temporary limits are defined.
*/
double getLowestTemporaryLimitValue();

/**
* <p>Indicate if temporary limits to create are defined in the adder.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @return <code>true</code> if temporary limits to create are defined, <code>false</code> otherwise.
*/
boolean hasTemporaryLimits();

/**
* <p>Get the names of the temporary limits to create.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @return a collection containing the names of the defined temporary limits.
*/
Collection<String> getTemporaryLimitNames();

/**
* <p>Remove from the temporary limits to create the one(s) corresponding to the given name.</p>
* <p>This method doesn't throw any <code>Exception</code> if no corresponding temporary limits are found.</p>
* <p>This method is useful to fix permanent or temporary limits before calling {@link #add()}.</p>
* @param name a temporary limit name
*/
void removeTemporaryLimit(String name);

/**
* <p>Get the id of the network element on which the LoadingLimits should be added.</p>
* @return the id of the owner network element
*/
String getOwnerId();

/**
* <p>Fix the limits to create if needed, especially the permanent limit when it is not defined (equals <code>Double.NaN</code>).</p>
* @return the adder
* @see LoadingLimitsAdder#fixLimits(double, LoadingLimitsUtil.LimitFixLogger)
*/
default A fixLimits() {
return fixLimits(100., LoadingLimitsUtil.LimitFixLogger.NO_OP);
}

/**
* <p>Fix the limits to create if needed, especially the permanent limit when it is not defined (equals <code>Double.NaN</code>).</p>
* @param missingPermanentLimitPercentage the percentage to use to compute the permanentLimit if it is not defined.
* @return the adder
* @see LoadingLimitsAdder#fixLimits(double, LoadingLimitsUtil.LimitFixLogger)
*/
default A fixLimits(double missingPermanentLimitPercentage) {
return fixLimits(missingPermanentLimitPercentage, LoadingLimitsUtil.LimitFixLogger.NO_OP);
}

/**
* <p>Fix the limits to create if needed, especially the permanent limit when it is not defined (equals <code>Double.NaN</code>).</p>
* @param missingPermanentLimitPercentage the percentage to use to compute the permanentLimit if it is not defined.
* @param limitFixLogger a logger allowing to report the changes applied when fixing the permanent limit.
* @return the adder
* @see LoadingLimitsUtil#fixMissingPermanentLimit(LoadingLimitsAdder, double, String, LoadingLimitsUtil.LimitFixLogger)
*/
default A fixLimits(double missingPermanentLimitPercentage, LoadingLimitsUtil.LimitFixLogger limitFixLogger) {
LoadingLimitsUtil.fixMissingPermanentLimit(this, missingPermanentLimitPercentage, getOwnerId(), limitFixLogger);
return (A) this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* 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.iidm.network;

Expand Down Expand Up @@ -590,9 +591,8 @@ public static void checkConnected(Validable validable, Boolean connected) {
}
}

public static void checkPermanentLimit(Validable validable, double permanentLimit) {
// TODO: if (Double.isNaN(permanentLimit) || permanentLimit <= 0) {
if (permanentLimit <= 0) {
public static void checkPermanentLimit(Validable validable, double permanentLimit, Collection<LoadingLimits.TemporaryLimit> temporaryLimits) {
if (Double.isNaN(permanentLimit) && !temporaryLimits.isEmpty() || permanentLimit <= 0) {
throw new ValidationException(validable, "permanent limit must be defined and be > 0");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* 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.iidm.network.util;

import com.powsybl.iidm.network.LoadingLimits;
import com.powsybl.iidm.network.LoadingLimitsAdder;

import static java.lang.Integer.MAX_VALUE;

/**
* @author Olivier Perrin {@literal <olivier.perrin at rte-france.com>}
*/
public final class LoadingLimitsUtil {

private LoadingLimitsUtil() {
}

/**
* Interface for objects used to report the performed operation on limits when fixed by
* {@link #fixMissingPermanentLimit(LoadingLimitsAdder, double, String, LimitFixLogger)}.
*/
public interface LimitFixLogger {
LimitFixLogger NO_OP = (what, reason, wrongValue, fixedValue) -> { };

void log(String what, String reason, double wrongValue, double fixedValue);
}

/**
* <p>Compute a missing permanent limit accordingly to the temporary limits and to a given percentage.</p>
* @param limitsAdder the LoadingLimitsAdder which permanent limit should be fixed
* @param missingPermanentLimitPercentage The percentage to apply
*/
public static <L extends LoadingLimits, A extends LoadingLimitsAdder<L, A>> void fixMissingPermanentLimit(LoadingLimitsAdder<L, A> limitsAdder,
double missingPermanentLimitPercentage) {
fixMissingPermanentLimit(limitsAdder, missingPermanentLimitPercentage, "", LimitFixLogger.NO_OP);
}

/**
* <p>Compute a missing permanent limit accordingly to the temporary limits and to a given percentage.</p>
* @param adder the LoadingLimitsAdder which permanent limit should be fixed
* @param missingPermanentLimitPercentage The percentage to apply
* @param ownerId id of the limits' network element. It is only used for reporting purposes.
* @param limitFixLogger the object used to report the performed operation on the permanent limit.
*/
public static <L extends LoadingLimits, A extends LoadingLimitsAdder<L, A>> void fixMissingPermanentLimit(LoadingLimitsAdder<L, A> adder, double missingPermanentLimitPercentage,
String ownerId, LimitFixLogger limitFixLogger) {
if (!Double.isNaN(adder.getPermanentLimit())) {
return;
}

double lowestTemporaryLimitWithInfiniteAcceptableDuration = MAX_VALUE;
boolean hasTemporaryLimitWithInfiniteAcceptableDuration = false;
for (String name : adder.getTemporaryLimitNames()) {
if (adder.getTemporaryLimitAcceptableDuration(name) == MAX_VALUE) {
hasTemporaryLimitWithInfiniteAcceptableDuration = true;
lowestTemporaryLimitWithInfiniteAcceptableDuration =
Math.min(lowestTemporaryLimitWithInfiniteAcceptableDuration, adder.getTemporaryLimitValue(name));
adder.removeTemporaryLimit(name);
}
}

if (hasTemporaryLimitWithInfiniteAcceptableDuration) {
limitFixLogger.log("Operational Limits of " + ownerId,
"Operational limits without permanent limit is considered with permanent limit " +
"equal to lowest temporary limit value with infinite acceptable duration",
Double.NaN, lowestTemporaryLimitWithInfiniteAcceptableDuration);
adder.setPermanentLimit(lowestTemporaryLimitWithInfiniteAcceptableDuration);
} else {
double firstTemporaryLimit = adder.getLowestTemporaryLimitValue();
double percentage = missingPermanentLimitPercentage / 100.;
double fixedPermanentLimit = firstTemporaryLimit * percentage;
limitFixLogger.log("Operational Limits of " + ownerId,
"Operational limits without permanent limit is considered with permanent limit " +
"equal to lowest temporary limit value weighted by a coefficient of " + percentage + ".",
Double.NaN, fixedPermanentLimit);
adder.setPermanentLimit(fixedPermanentLimit);
}
}
}
Loading