Skip to content

Migration guide v6.3.0

rcourtier edited this page Apr 5, 2024 · 26 revisions

Breaking Change Breaking changes for all users

Reporter new API: ReportNode

Starting from this release, Reporter and Report interfaces have been merged into a ReportNode interface, which contains the same features. The com.powsybl.commons.reporter package has been renamed into com.powsybl.commons.report, hence the corresponding imports are impacted.

  • The root ReportNode can be build thanks to the builder provided by ReportNode.newRootReportNode(),
  • A ReportNode can be added within another ReportNode thanks to the adder provided by reportNode.newReportNode().

The mentioned adder and builder share the same methods, with the following correspondence to former ReportBuilder methods:

  • withMessageTemplate(String messageKey, String messageTemplate) corresponds to reportBuilder.withKey(messageKey).withDefaultMessage(messageTemplate)
  • the withTypedValue(key, value, type) methods keep the same signature as in the former ReportBuilder
  • the withUntypedValue(key, value, type) methods corresponds to reportBuilder.withValue(key, value, type)
  • withSeverity(TypedValue severity), which corresponds to reportBuilder.withSeverity(TypedValue severity)
  • withSeverity(String severity), which corresponds to reportBuilder.withSeverity(new TypedValue(severity, TypedValue.SEVERITY)

Here are some replacement examples to help you migrate:

Previously adding a report with a builder, now adding a child ReportNode with an adder

reporter.report(Report.builder()
        .withKey("keyId")
        .withDefaultMessage("New report with typed value ${typedValue}, untyped value ${untypedValue} and severity ${reportSeverity}")
        .withTypedValue("typedValue", 20, "type")
        .withValue("untypedValue", 3.)
        .withSeverity(TypedValue.INFO_SEVERITY)
        .build());

with

ReportNode childReportNode = reportNode.newReportNode()
        .withMessageTemplate("keyId", "New report with typed value ${typedValue}, untyped value ${untypedValue} and severity ${reportSeverity}")
        .withTypedValue("typedValue", 20, "type")
        .withUntypedValue("untypedValue", 3.)
        .withSeverity(TypedValue.INFO_SEVERITY)
        .add();

Include an existing reporter / reportNode in another one

reporter.report(reportNode);

with

reporter.include(reportNode);

Note that the included ReportNode needs to be a root.

Previously adding a report / sub-reporter with createSubReporter / report, now adding a child ReportNode with an adder

Replace

Reporter subReporter = reporter.createSubReporter(taskKey, defaultName);

or

reporter.report(reportKey, defaultMessage);

with

ReportNode childReportNode = reportNode.newReportNode()
        .withMessageTemplate(reportKey, defaultMessage)
        .add();

The replacements are similar for the other Reporter::createSubReporter and Reporter::report methods.

Create a root Reporter / ReportNode

Replace the root creation

Reporter reporter = new ReporterModel(taskKey, defaultName, Maps.of(valueKey, new TypedValue(value, type)));

with

ReportNode rootReportNode = ReportNode.newRootReportNode()
        .withMessageTemplate(taskKey, defaultName)
        .withTypedValue(valueKey, value, type)
        .build();

ReporterContext changes

As a side-effect, the ReporterContext interface has been renamed into ReportNodeContext, and all the methods have been renamed. You need to replace the call to

  • ReporterContext::peekReporter by ReportNodeContext::peekReportNode
  • ReporterContext::getReporter by ReportNodeContext::getReportNode
  • ReporterContext::pushReporter by ReportNodeContext::pushReportNode
  • ReporterContext::popReportNode by ReportNodeContext::popReportNode

The implementations have also been renamed:

  • SimpleReporterContext into SimpleReportNodeContext
  • MultiThreadReporterContext into MultiThreadReportNodeContext

Lastly, Networks::allowReporterContextMultiThreadAccess has therefore been renamed into Networks::allowReportNodeContextMultiThreadAccess.

LoadFlow

In the LoadFlowParameters, the default value of writeSlackBus parameter is now true. This is a functional change, that could lead to differences during unit and integration tests.

Contingencies

New module powsybl-iidm-criteria

Some criteria used for contingency definition were moved in a dedicated new module: powsybl-iidm-criteria.

If you used the following classes, you should add the new module in your project dependencies and update your import statements:

  • previously in the com.powsybl.contingency.contingency.list.criterion package, now in com.powsybl.iidm.criteria:
    • Criterion
    • PropertyCriterion
    • RegexCriterion
    • SingleCountryCriterion
    • SingleNominalVoltageCriterion
    • ThreeNominalVoltageCriterion
    • TwoCountriesCriterion
    • TwoNominalVoltageCriterion
  • previously in the com.powsybl.contingency.json package, now in com.powsybl.iidm.criteria.json:
    • CriterionDeserializer
    • CriterionSerializer

More robust VoltageIntervals

Generalities

SingleNominalVoltageCriterion.VoltageInterval was renommed as VoltageInterval.

The following methods of VoltageInterval were renamed to match the bean methods syntax:

  • getLowClosed() => isLowClosed()
  • getHighClosed() => isHighClosed()

Intervals with only one bound

Intervals with only one bound are now considered as valid. This have the following impacts:

VoltageInterval.getNominalVoltageLowBound() and VoltageInterval.getNominalVoltageHighBound() now return an Optional<Double> instead of a Double to indicated if a bound was defined or not.

The concept of "null interval" was removed, as for the VoltageInterval.isNull() method. If you need to indicate that an interval was not set, use a "null" value instead.

As a consequence, getVoltageInterval...() methods of TwoNominalVoltageCriterion and ThreeNominalVoltageCriterion now return an Optional<VoltageInterval> instead of a VoltageInterval.

New ways to create an interval

The historical constructor was removed. Instead, you can use either the build() static method which returns a builder, or one of the greaterThan, lowerThan and between static methods which return an interval with one or both bounds.

For instance, you can replace:

new VoltageInterval(200.0, 230.0, true, true)

by either

VoltageInterval.builder()
    .setLowBound(200.0, true)
    .setHighBound(230.0, true)
    .build()

or

VoltageInterval.between(200.0, 230.0, true, true)

IIDM

Support of validation level for missing permanent limit

The following utilitary methods:

  • ValidationUtil.checkLoadingLimits(...);
  • ValidationUtil.checkPermanentLimit(...);

now take two additional parameters:

  • boolean throwException: should the method throw an exception when a missing permanent limit is detected?
  • ReportNode reportNode: the reportNode to use to log potential errors. You can use ReportNode.NO_OP if you are not interested by this log.

Security analysis

Limit reduction

SecurityAnalysisProvider.run(…) now takes an additional parameter: List<LimitReduction> limitReductions. You need to add this parameter to your own SecurityAnalysisProvider implementations.

Differences from version 6.3.0-alpha-1

When you used the constructor with all the parameters to create a "LimitReduction", you should use the builder. Default values for the characteristics are:

  • monitoringOnly: false;
  • contingencyContext: ContingencyContext.all();
  • networkElementCriteria: Collections.emptyList();
  • limitDurationCriteria: Collections.emptyList().

Thus, you can omit setting one of the characteristics if you used its default value.

For instance:

       LimitReduction limitReduction = new LimitReduction(LimitType.APPARENT_POWER, 0.5, false,
                ContingencyContext.all(),
                Collections.emptyList(),
                List.of(durationCriterion1, durationCriterion2));

could be rewritten in

       LimitReduction limitReduction = LimitReduction.builder(LimitType.APPARENT_POWER, 0.5)
                .withLimitDurationCriteria(durationCriterion1, durationCriterion2)
                .build();

Note:

  • monitoringOnly, networkElementCriteria and contingencyContext are not specified as their default values are used;
  • the with...Criteria(...) methods take either a List or varArgs. You could thus omit the encapsulating List.of() for ease of use. But in either case, the previously definied criteria are replaced by the given ones.

Limit reduction value

  • LimitViolation.getLimitReduction now returns a double instead of a float;
  • If you have defined your own IIDM implementation, you should change the type of the limitReductionValue parameter from float to double in the checkPermanentLimit… and checkTemporaryLimit… methods of your Branch's and ThreeWindingTransformer's implementations;
  • If you have a custom LimitViolationDetector's implementation, you should change the type of the limitReductionValue parameter from float to double in the checkPermanentLimit and checkTemporaryLimit methods;
  • AbstractBranchActionExpressionNode.getLimitReduction() now returns a double instead of a float.

New modules for actions

The actions previously spread out in powsybl-core have been regrouped into the module powsybl-action. If you were using either one of them, you will have to change your imports and dependencies accordingly:

  • Package com.powsybl.security.action moved to com.powsybl.action in the new module powsybl-action-api;
  • Package com.powsybl.security.json.action moved to com.powsybl.action.json;
  • The action part of SecurityAnalysisJsonModule has been relocated to the class ActionJsonModule and moved from com.powsybl.security.json to com.powsybl.action.json. The rest of SecurityAnalysisJsonModule stays the same;
  • Module with artifactId powsybl-action renamed powsybl-action-ial;
  • Module with artifactId powsybl-action-dsl renamed powsybl-action-ial-dsl and packages moved accordingly;
  • Module with artifactId powsybl-action-dsl-spi renamed powsybl-action-ial-dsl-spi and packages moved accordingly;
  • Module with artifactId powsybl-action-simulator renamed powsybl-action-ial-simulator and packages moved accordingly;
  • Module with artifactId powsybl-action-util renamed powsybl-action-ial-util and packages moved accordingly.

Conditional actions results

Compatibility is supported. OperatorStrategyResult object contains now a list of ConditionalActionsResult objects instead of only the results on final state of the simulation. Each ConditionActionsResult groups the result after applying the list of actions described in a ConditionalActions if the condition is satisfied. For an operator strategy with a single ConditionalActions object ConditionalActionsResult will have a single object containing the same results as before this feature. For operator strategy with multiple ConditionalActions objects, ConditionalActionsResult will have one result per ConditionalActions object and the last one in the list represents the last stage.

Sensitivity analysis

Bus reactive power

New BUS_REACTIVE_POWER sensitivity function type has been added in sensitivity factor. You need to add a default behavior in switch cases or add a behavior to the new enum value.

CGMES conversion

New CgmesMetadataModels extension

A new CgmesMetadataModels extension has been added, whose purpose is to store metadata information present in the Model node of the instance files. Please refer to IEC 61970-552 for more details about these metadata. The CgmesMetadataModels may contain several instances of CgmesMetadataModel, one per CgmesSubset (EQ, TP, SV, SSH...). The CgmesMetadataModel class now replaces the former classes CgmesSshMetadata and CgmesSvMetadata which have been removed in this version.

To retrieve the Ssh and Sv metadata associated to the network (after reading a CGMES case for instance), this must now be done as follow:

CgmesMetadataModels modelsExtension = network.getExtension(CgmesMetadataModels.class);
CgmesMetadataModel sshModel = modelsExtension.getModelForSubset(CgmesSubset.STEADY_STATE_HYPOTHESIS).orElseThrow();
CgmesMetadataModel svModel = modelsExtension.getModelForSubset(CgmesSubset.STATE_VARIABLES).orElseThrow();
String sshDescription = sshModel.getDescription();
int svVersion = svModel.getVersion(); 

Please note: network.getExtension(CgmesMetadataModels.class) can return a null value. getModelForSubset returns an optional.

To create a new CgmesMetadataModels extension (to set metadata information for a CGMES export for instance), this must be done as follow:

network.newExtension(CgmesMetadataModelsAdder.class)
        .newModel()
        .setSubset(CgmesSubset.STEADY_STATE_HYPOTHESIS)
        .setId("sshId")
        .setDescription("SSH description")
        .setModelingAuthoritySet("http://powsybl.org")
        .setVersion(1)
        .addProfile("http://steady-state-hypothesis")
        .add()
        .add();

Time Series

Default version number for unversioned TimeSeries

If you used the default TimeSeriesCsvConfig by calling new TimeSeriesCsvConfig() and imported some versioned TimeSeries with a version number at 0 (old default value for unversioned TimeSeries), it will now consider them as versioned TimeSeries since the new default value has been set to -1.

If you still want to import TimeSeries with a version number and have them considered as unversioned TimeSeries, you have to use the version number -1. However, it will now throw an exception. You need to replace your call from new TimeSeriesCsvConfig() to new TimeSeriesCsvConfig(ZoneId.systemDefault(), TimeSeriesConstants.DEFAULT_SEPARATOR, true, TimeFormat.DATE_TIME, DEFAULT_MAX_COLUMNS, false) in order to keep it working (you will still get warnings) or change your TimeSeries version number to another value if it's not meant to be an unversioned one.

Also, a third parameter was added to the static method parseCsv(BufferedReader reader, TimeSeriesCsvConfig timeSeriesCsvConfig): you have to use parseCsv(BufferedReader reader, TimeSeriesCsvConfig timeSeriesCsvConfig, ReportNode reportNode) now.


Custom IIDM Impl Breaking changes for custom IIDM implementations maintainers

IIDM

Pairing key setter for dangling lines

If you have defined your own IIDM implementation, you should implement the following methods in your DanglingLine implementations: DanglingLine setPairingKey(String pairingKey). Note that in the in-memory implementation, setting the paring key is allowed only for unpaired dangling lines. An exception is thrown otherwise.

Clone this wiki locally