powsybl / powsybl-core

A framework to build power system oriented software

Home Page:https://www.powsybl.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CGMES: stability of generated UUID

annetill opened this issue · comments

Describe the current behavior

Doing a CGMES export on a network not coming from CGMES format, we have:
image
Generated mRID are not stable.

Describe the expected behavior

Generated mRID must be stable. We need a new naming strategy to handle this feature. This idea is to use a method that gives the mRID using the name of the identifiable to reach a deterministic behavior. In case of object without id, we have to think about build in name such as:

  • Line NGEN_NHV1 : ok
  • Terminal 1 of the line : NGEN_NHV1_terminal1
  • TRANSFO_phase_tap_changer_step_3 ...

Describe the motivation

No response

Extra Information

No response

commented

Current NamingStrategy should be able to keep track of the created/assigned UUIDs and reuse them in a subsequent export for most part of the objects (identifiables and objects related to identifiables), we only should have to save the mapping file created in the first export and give it as a parameter in later exports of the same network.

commented

The default naming strategy, AbstractCgmesAliasNamingStrategy, uses this code for obtaining "new" CGMES identifiers:

    private String getCgmesId(Identifiable<?> identifiable, String id, String aliasName) {
        if (idByUuid.containsValue(id)) {
            return idByUuid.inverse().get(id);
        }
        String uuid;
        Optional<String> uuidFromAlias = identifiable.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + aliasName);
        if (uuidFromAlias.isPresent()) {
            uuid = uuidFromAlias.get();
        } else if (CgmesExportUtil.isValidCimMasterRID(id)) {
            uuid = id;
        } else {
            uuid = CgmesExportUtil.getUniqueId();
            // Only store the IDs that have been created during the export
            idByUuid.put(uuid, id);
        }
        return uuid;
    }

If there is a mapping stored, return it.
If there is an alias stored, return it.
If the original IIDM identifier is a valid CGMES mRID, return it.
If not, create a new one and store it in the mapping.

Current NamingStrategy should be able to keep track of the created/assigned UUIDs and reuse them in a subsequent export for most part of the objects (identifiables and objects related to identifiables), we only should have to save the mapping file created in the first export and give it as a parameter in later exports of the same network.

@zamarrenolm an alternative solution, that is the one implemented in Convergence would be to use the UUID.nameUUIDFromBytes fonction that is able to generate an UUID from a string in a stable way. That would be much simpler for a user perspective because we could achieve a CGMES fully generated using UUIDs as mrIDs and with stability without any additionnal configuration. Indeed like in the current strategy if the IIDM ID is already a UUID we take it as it is.
As explained by @annetill, for CGMES objects that do not have an identified equivalent in IIDM, we could make it as a derivation of the initial IIDM object ID like for a line NGEN_NHV1 -> UUID.nameUUIDFromBytes("NGEN_NHV1" + "_terminal1"). We just have to define a IIDM ID string derivation strategy for all of the CGMES resources.
This solution would also have the advantage to keep compat with actual Convergence CGMES export and to not break mrID stability when switching to powsybl.

I would also remove all of the other naming strategies because this one would cover all cases (I guess...)

commented

I would also remove all of the other naming strategies because this one would cover all cases (I guess...)

In addition to looking into NamingStrategy, we will have to change the CgmesExportUtil.getUniqueId. This is the single point where new identifiers are created for preparing an export of a network that does not come from CGMES format.

Just keep in mind that valid identifiers may be stored in aliases and properties of the IIDM objects, and must be used. This is the way we keep identifiers for CGMES objects that do not have IIDM equivalents when the network original format is CGMES.

commented

I would also remove all of the other naming strategies because this one would cover all cases (I guess...)

In addition to looking into NamingStrategy, we will have to change the CgmesExportUtil.getUniqueId. This is the single point where new identifiers are created for preparing an export of a network that does not come from CGMES format.

Just keep in mind that valid identifiers may be stored in aliases and properties of the IIDM objects, and must be used. This is the way we keep identifiers for CGMES objects that do not have IIDM equivalents when the network original format is CGMES.

To clarify, I will try to explain the current strategy for export:

  • We need to export networks that come from CGMES and "pure" IIDM networks (or coming from other formats).
  • During CGMES export, we rely on aliases and properties to store identifiers of objects that do not have IIDM equivalents.
  • To prepare the CGMES export, we ensure that the network contains all the required aliases/properties of related objects that we will need later. This is done in CgmesExportContext::addIidmMappings. This is the place where we may call multiple times the CgmesExportUtil.getUniqueId.

Just keep in mind that valid identifiers may be stored in aliases and properties of the IIDM objects, and must be used. This is the way we keep identifiers for CGMES objects that do not have IIDM equivalents when the network original format is CGMES.

you are right for CGMES technical objects, when coming from a CGMES and that we have properties and aliases we will first look at it before generating one like in current naming strategy.

commented

@annetill , @geofjamg @colinepiloquet : An important comment about the proposed change for UUID stability:

I agree on simplifying the current design of naming strategy, and relying on UUIDs created from text hashes is a great idea. I am in favor of it.

Just want to point out that:

The current implementation, based on a persistent map, allows for "decoding" the UUIDs created during export to CGMES and potentially recover the original IDs. That is: if you import back the exported CGMES files, and provide the CSV file written during the export, the re-imported Network will be built using the original IDs. The proposed method to obtain UUID.nameUUIDFromBytes does not allow to go back to the original bytes if only the resulting UUID is given, so if we move to it we would lose this feature, are we ok ? (I vote yes, I think we can live without it).

Anyway, and related to it:

Should we support the use of mapping files for legacy users ? (I vote no, let's simplify to keep easier maintainability of the code base).

commented

Feature completed in #2804