Skip to content

Migration guide v6.2.0

Nicolas Rol edited this page Jul 19, 2024 · 23 revisions

Breaking Change Breaking changes for all users

IIDM

Reactive power control mode for ration tap changers

ValidationUtil.checkRatioTapChangerRegulation methods take an additional parameter: regulationMode, the regulation mode (note that targetV parameter was also renamed in regulationValue).

Besides, if you have defined your own IIDM implementation, please refer to this section.

Notification system for extensions

If you have defined your own implementation of NetworkListener without inheriting DefaultNetworkListener, you should implement the following methods:

  • void onUpdate(Identifiable<?> identifiable, String attribute, String variantId, Object oldValue, Object newValue)
    • This method previsouly existed with a default implementation which was removed
  • void onExtensionCreation(Extension<?> extension)
  • void onExtensionAfterRemoval(Identifiable<?> identifiable, String extensionName)
  • void onExtensionBeforeRemoval(Extension<?> extension)
  • void onExtensionUpdate(Extension<?> extendable, String attribute, Object oldValue, Object newValue)

Secondary voltage control notifications

The SecondaryVoltageControl extension was refactored to use the newly introduced notification system for extensions.

To create a new SecondaryVoltageControl extension, you should now use a builder:

  • Before:
SecondaryVoltageControl control = network.newExtension(SecondaryVoltageControlAdder.class)
         .addControlZone(new ControlZone("z1",
                                         new PilotPoint(List.of("NLOAD"), 15d),
                                         List.of(new ControlUnit("GEN", false), new ControlUnit("GEN2"))))
         .add();
  • After:
SecondaryVoltageControl control = network.newExtension(SecondaryVoltageControlAdder.class)
             .newControlZone()
                 .withName("z1")
                 .newPilotPoint()
                     .withBusbarSectionsOrBusesIds(List.of("NLOAD"))
                     .withTargetV(15d)
                 .add()
                 .newControlUnit()
                     .withId("GEN")
                     .withParticipate(false)
                 .add()
                 .newControlUnit()
                     .withId("GEN2")
                 .add()
             .add()
         .add();

Besides, if you have defined your own IIDM implementation, please refer to this section.

Permanent limit mandatory

We did it! From this version, we add a check to ensure that when a connectable has temporary loading limits, it has a defined permanent limit. Note that it does not mean that a permanent limit is required for all equipments that could have one. In order to ensure compatibility with previous IIDM version, if the permanent limit is missing, we fix it with a percentage of the lowest (in value) temporary limit, by default 100%. This percentage is configurable at import: for a different value, please use iidm.import.xml.missing-permanent-limit-percentage parameter.

Breaking changes are the following:

ValidationUtil.checkPermanentLimit now takes an additional parameter:

  • Collection<LoadingLimits.TemporaryLimit> temporaryLimits: the temporary limits defined for the same LoadingLimits object.

The readActivePowerLimits, readApparentPowerLimits and readCurrentLimits methods of ConnectableSerDeUtil now take 2 additional parameters:

  • IidmVersion iidmVersion: the IIDM version of the network being deserialized;
  • ImportOptions options: the import options to apply when deserializing the network.

Besides, if you have defined your own IIDM implementation, please refer to this section.

Connection/disconnection notifications

When using the default IIDM implementation, at terminal connection/disconnection:

  • the "connection" notifications that were emitted are replaced:
    • at connection by:
      • a "beginConnect" notification before the connection. Its oldValue contains the previous connection state of the terminal;
      • a "endConnect" notification after the connection. Its newValue contains the final connection state of the terminal;
    • at disconnection by:
      • a "beginDisconnect" notification before the disconnection. Its oldValue contains true if the terminal was previously disconnected, false otherwise;
      • a "endDisconnect" notification after the disconnection. Its newValue contains true if the terminal is now disconnected, false otherwise;
  • the "connected" notifications are replaced by "connected" + side number notifications. The content of their oldValue and newValue attributes is unchanged.

Besides, if you have defined your own IIDM implementation, please refer to this section.

Serialization/deserialization changes due to binary export/import

Starting from this release, if you wrote your own extensions, you should pay attention in its serialization/deserialization to follow this rule: if a parameter is optional in the XML you should not include the previous if clause:

  • TreeDataWriter::writeOptionalIntAttribute, and then read it with TreeDataReader::readOptionalIntAttribute,
  • TreeDataWriter::writeOptionalDoubleAttribute, and then read it with TreeDataReader::readOptionalDoubleAttribute,
  • TreeDataWriter::writeOptionalBooleanAttribute, and then read it with TreeDataReader::readOptionalBooleanAttribute.

More generally, the write methods of TreeDataWriter should not be enclosed in a if clause. This is needed to have a compact binary format, where the value is stored without the attribute name. As there are always exceptions, two exceptions to this rule:

  1. a TreeDataWriter.writeStartNode() - TreeDataWriter.writeEndNode() code block can be enclosed in a if clause (the start node names are stored in the binary file)
  2. attributes which are written or not based on a previous parameter read can be enclosed in a if clause. For instance, the topology kind implies to write either a node or a bus/connectableBus.

Before:

if (shouldBeWritten()) {
   writer.writeIntAttribute("attributeX", x);
}
Optional.ofNullable(y).ifPresent(y1 -> writer.writeDoubleAttribute("attributeY", y1));

After:

writer.writeOptionalIntAttribute("attributeX", shouldBeWritten() ? x : null);
writer.writeOptionalDoubleAttribute("attributeY", y); // with y nullable

Tip: You can search the usages of TreeDataWriter and NetworkSerializerContext to find where the serialization/deserialization is implied.

Security analysis

Terminals connection action

The LineConnectionAction has been removed and replaced by TerminalsConnectionAction. With this new remedial action, we can open or close one Terminal, given by an element id and a side (instance of ThreeSide). The side is optional: in that case, the remedial action means that the terminals of the element will be all opened or all closed. The element can be any connectable (line, transformers, injection, etc.). If the element is a TieLine, terminals refer to the underlying dangling lines' terminals. If the element is a HvdcLine, the terminals refer to the converter stations' terminals. In case of a two-terminal element, remember to use utility method to convert a ThreeSide in a TwoSide if you apply the remedial action on the network.


Custom IIDM Impl Breaking changes for custom IIDM implementations maintainers

IIDM

Automation systems: Overload management systems

If you have defined your own IIDM implementation, you should implement the following methods:

  • in your Network implementations:

    • Iterable<OverloadManagementSystem> getOverloadManagementSystems()
    • Stream<OverloadManagementSystem> getOverloadManagementSystemStream()
    • int getOverloadManagementSystemCount()
    • OverloadManagementSystem getOverloadManagementSystem(String id)
  • in your Substation implementation:

    • OverloadManagementSystemAdder newOverloadManagementSystem()
    • Iterable<OverloadManagementSystem> getOverloadManagementSystems()
    • Stream<OverloadManagementSystem> getOverloadManagementSystemStream()
    • int getOverloadManagementSystemCount()

New "Ground" injection

If you have defined your own IIDM implementation, you should implement the following methods:

  • in your Network implementations:

    • Iterable<Ground> getGrounds()
    • Stream<Ground> getGroundStream()
    • int getGroundCount()
    • Ground getGround(String id)
  • in your VoltageLevel implementation:

    • GroundAdder newGround()
    • Iterable<Ground> getGrounds()
    • Stream<Ground> getGroundStream()
    • int getGroundCount()
  • in your TopologyVisitor implementation:

    • void visitGround(Ground connectable)

Reactive power control mode for ration tap changers

If you have defined your own IIDM implementation, you should implement the following methods:

  • in your RatioTapChanger implementations:

    • RegulationMode getRegulationMode()
    • RatioTapChanger setRegulationMode(RatioTapChanger.RegulationMode regulationMode)
    • double getRegulationValue()
    • RatioTapChanger setRegulationValue(double regulationValue)
  • in your RatioTapChangerAdder implementations:

    • RatioTapChangerAdder setRegulationMode(RatioTapChanger.RegulationMode regulationMode)
    • RatioTapChangerAdder setRegulationValue(double regulationValue)

Steps replacement on a tap changer

If you have defined your own IIDM implementation, you should implement the following methods:

  • In your PhaseTapChanger and RatioTapChanger implementations:
    • ... stepsReplacer().

Secondary voltage control notifications

If you have defined your own implementation of the SecondaryVoltageControl extension, you should:

  • define custom implementations for PilotPoint, ControlUnitand ControlZone, and their respective adders. The default implementations which were provided were transferred in iidm-impl to benefit from the notification system;
  • remove your implementation of SecondaryVoltageControlAdder.addControlZone(ControlZone controlZone);
  • implement SecondaryVoltageControlAdder.newControlZone().

The easiest way to do it is to can take your inspiration from the implementation classes located in iidm-impl.

Permanent limit mandatory

If your project defines custom IIDM implementations, you should implement the following methods:

  • In LoadingLimitsAdder implementations:
    • double getTemporaryLimitValue(String name)
    • int getTemporaryLimitAcceptableDuration(String name)
    • double getLowestTemporaryLimitValue()
    • Collection<String> getTemporaryLimitNames()
    • void removeTemporaryLimit(String name)
    • String getOwnerId()

Connectable connect/disconnect

Starting from this release the four following methods have been added to Connectable interface

boolean connect();
boolean connect(Predicate<Switch> isTypeSwitchToOperate);
boolean disconnect();
boolean disconnect(Predicate<Switch> isSwitchOpenable);

Hence, if you have defined your own implementation of Connectable, you need to implement these methods.

Please note that, if your connectable has multiple terminals, you have to connect/disconnect either all of them or none. Your implementation should not connect/disconnect only some of the terminals, to avoid having a connectable only partially connected.

Connection/disconnection notifications

If you have defined your own IIDM implementation, you should implement the following methods:

  • in your Terminal implementations:
    • ThreeSides getSide()

Operational limits groups

If you have defined your own IIDM implementation, you should:

  • implement the OperationalLimitGroup interface;

  • in your Branch implementations:

    • implement the following methods:
      Collection<OperationalLimitsGroup> getOperationalLimitsGroups1();
      Optional<String> getSelectedOperationalLimitsGroupId1();
      Optional<OperationalLimitsGroup> getOperationalLimitsGroup1(String id);
      Optional<OperationalLimitsGroup> getSelectedOperationalLimitsGroup1();
      OperationalLimitsGroup newOperationalLimitsGroup1(String id);
      void setSelectedOperationalLimitsGroup1(String id);
      void removeOperationalLimitsGroup1(String id);
      void cancelSelectedOperationalLimitsGroup1();
    
      Collection<OperationalLimitsGroup> getOperationalLimitsGroups2();
      Optional<String> getSelectedOperationalLimitsGroupId2();
      Optional<OperationalLimitsGroup> getOperationalLimitsGroup2(String id);
      Optional<OperationalLimitsGroup> getSelectedOperationalLimitsGroup2();
      OperationalLimitsGroup newOperationalLimitsGroup2(String id);
      void setSelectedOperationalLimitsGroup2(String id);
      void removeOperationalLimitsGroup2(String id);
      void cancelSelectedOperationalLimitsGroup2();
    • redefine your implementation of the following methods (note that for some of these, default methods are defined in the interface ancestors, you may just have to remove your own implementation):
      Optional<CurrentLimits> getCurrentLimits1();
      CurrentLimits getNullableCurrentLimits1();
      Optional<ActivePowerLimits> getActivePowerLimits1();
      ActivePowerLimits getNullableActivePowerLimits1();
      Optional<ApparentPowerLimits> getApparentPowerLimits1();
      ApparentPowerLimits getNullableApparentPowerLimits1();
      CurrentLimitsAdder newCurrentLimits1();
      ActivePowerLimitsAdder newActivePowerLimits1();
      ApparentPowerLimitsAdder newApparentPowerLimits1();
    
      Optional<CurrentLimits> getCurrentLimits2();
      CurrentLimits getNullableCurrentLimits2();
      Optional<ActivePowerLimits> getActivePowerLimits2();
      ActivePowerLimits getNullableActivePowerLimits2();
      Optional<ApparentPowerLimits> getApparentPowerLimits2();
      ApparentPowerLimits getNullableApparentPowerLimits2();
      CurrentLimitsAdder newCurrentLimits2();
      ActivePowerLimitsAdder newActivePowerLimits2();
      ApparentPowerLimitsAdder newApparentPowerLimits2();
  • in your TieLine and ThreeWindingsTransformer.Leg implementations:

    • implement the following methods:
      Collection<OperationalLimitsGroup> getOperationalLimitsGroups();
      Optional<String> getSelectedOperationalLimitsGroupId();
      Optional<OperationalLimitsGroup> getOperationalLimitsGroup(String id);
      Optional<OperationalLimitsGroup> getSelectedOperationalLimitsGroup();
      OperationalLimitsGroup newOperationalLimitsGroup1String id);
      void setSelectedOperationalLimitsGroup(String id);
      void removeOperationalLimitsGroup(String id);
      void cancelSelectedOperationalLimitsGroup();
    • redefine your implementation of the following methods (note that for some of these, default methods are defined in the interface ancestors, you may just have to remove your own implementation):
      Optional<CurrentLimits> getCurrentLimits();
      CurrentLimits getNullableCurrentLimits();
      Optional<ActivePowerLimits> getActivePowerLimits();
      ActivePowerLimits getNullableActivePowerLimits();
      Optional<ApparentPowerLimits> getApparentPowerLimits();
      ApparentPowerLimits getNullableApparentPowerLimits();
      CurrentLimitsAdder newCurrentLimits();
      ActivePowerLimitsAdder newActivePowerLimits();
      ApparentPowerLimitsAdder newApparentPowerLimits();
Clone this wiki locally