3lbits / CIM4NoUtility

CIM for the Norwegian Power Utility
Creative Commons Attribution Share Alike 4.0 International
23 stars 5 forks source link

Converting CIMXML DifferenceModel to CIMJSON-LD #279

Closed Sveino closed 1 year ago

Sveino commented 1 year ago

As part of creating a CIMXML to/from CIMJSON-LD converter we would need to define how the DifferenceModel file defined in the IEC 61970-552 CIMXML Model exchange format . A proposal describing the CIMXML DifferenceModel was presented for the W3C and got Tim Berners-Lee support, but was still not approved. Being able to exchange and validate changes to a digital twin model by change set is critical. It is also very useful for handling alternative changes into the future. The changes would need to be accommodated with meta-data.

A ACLineSegment object is described with the following property:

    <cim:ACLineSegment rdf:ID="_9d58e5bb-834c-4faa-928c-7da0bb1497d9">
        <cim:IdentifiedObject.mRID>9d58e5bb-834c-4faa-928c-7da0bb1497d9</cim:IdentifiedObject.mRID>
        <cim:IdentifiedObject.description>400V Telemarkstien 2 ACLineSegment 1</cim:IdentifiedObject.description>
        <cim:IdentifiedObject.name>04 TELEMA2 ACLS1</cim:IdentifiedObject.name>
        <cim:Equipment.aggregate>false</cim:Equipment.aggregate>
        <cim:Equipment.normallyInService>true</cim:Equipment.normallyInService>
        <cim:Conductor.length>50</cim:Conductor.length>
        <cim:ACLineSegment.bch>0</cim:ACLineSegment.bch>
        <cim:ACLineSegment.gch>0</cim:ACLineSegment.gch>
        <cim:ACLineSegment.r>0.015999999945951</cim:ACLineSegment.r>
        <cim:ACLineSegment.x>0.003769911221053</cim:ACLineSegment.x>
        <cim:PowerSystemResource.AssetDatasheet rdf:resource="#_d25f35ca-69fb-4c06-905b-67ec532e5f14" />
        <cim:Equipment.EquipmentContainer rdf:resource="#_64e21d95-8b55-b941-a923-b74087410a66" />
        <cim:ConductingEquipment.BaseVoltage rdf:resource="#_9598e4a0-67e5-4ad7-879c-c85a1f63159c" />
    </cim:ACLineSegment>

Changing the ACLineSegment object by changing the length from 50 meter to 55 meter would look like:

<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF  xmlns:cim="http://iec.ch/TC57/CIM100#" 
            xmlns:dm="http://iec.ch/TC57/61970-552/DifferenceModel/1#" 
            xmlns:eu="http://iec.ch/TC57/CIM100-European#" 
            xmlns:md="http://iec.ch/TC57/61970-552/ModelDescription/1#" 
            xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

   <dm:DifferenceModel rdf:about="">
      <dm:reverseDifferences rdf:parseType="Statements">
         <rdf:Description rdf:about="#_9d58e5bb-834c-4faa-928c-7da0bb1497d9">
            <cim:Conductor.length>50</cim:Conductor.length>
         </rdf:Description>
      </dm:reverseDifferences>
      <dm:forwardDifferences rdf:parseType="Statements">
         <rdf:Description rdf:about="#_9d58e5bb-834c-4faa-928c-7da0bb1497d9">
            <cim:Conductor.length>55</cim:Conductor.length>
         </rdf:Description>
      </dm:forwardDifferences>
   </dm:DifferenceModel>
</rdf:RDF>

reverseDifferences describe the dataset that will be removed (delete). forwardDifferences describe the dataset that will be added (add) An update is describe as reverseDifferences and forwardDifferences (as shown in the example).

Proposal 1: Single Graph

{
    "@context": {
        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
        "cim": "http://iec.ch/TC57/CIM100#",
        "md": "http://iec.ch/TC57/61970-552/ModelDescription/1#",
        "eu": "http://iec.ch/TC57/CIM100-European#",
        "dm": "http://iec.ch/TC57/61970-552/DifferenceModel/1#"
    },

    "@graph": [{
            "@id": "urn:uuid:f52f12c3-db10-4d41-a9f2-b1fe29ab4d6d",
            "@type": "dm:DifferenceModel",
            "dm:reverseDifferences": [{
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 50.0
                    }
                }
            ],
            "dm:forwardDifferences": [{
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 55.0
                    }
                }
            ]
        }
    ]
}

Alt 2: Two graph

{
    "@context": {
        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
        "cim": "http://iec.ch/TC57/CIM100#",
        "md": "http://iec.ch/TC57/61970-552/ModelDescription/1#",
        "eu": "http://iec.ch/TC57/CIM100-European#",
        "dm": "http://iec.ch/TC57/61970-552/DifferenceModel/1#"
    },

    "@graph": [{
            "@id": "urn:uuid:f52f12c3-db10-4d41-a9f2-b1fe29ab4d6d",
            "@type": "dm:DifferenceModel",
            "dm:reverseDifferences": [{
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 50.0
                    },
                    "cim:IdentifiedObject.name": "04 TELEMA2 ACLS1"
                }
            ]
        }, {
            "@id": "urn:uuid:f1aa3e3a-8391-4bf9-b435-6bd0702f9e0d",
            "@type": "dm:DifferenceModel",
            "dm:forwardDifferences": [{
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 55.0
                    },
                    "cim:IdentifiedObject.name": "04 TELEMA2 ACLS2"
                }
            ]
        }
    ]
}

I do not think the example is correct. I think we might need to use the container structure shown in Example 122 in the JSON-LD 1.1 standard.

Relevant links:

Sveino commented 1 year ago

Maybe a better (not correct syntax);

{
  "@context": {
    "@version": 1.1,
        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
        "cim": "http://iec.ch/TC57/CIM100#",
        "md": "http://iec.ch/TC57/61970-552/ModelDescription/1#",
        "eu": "http://iec.ch/TC57/CIM100-European#",
        "dm": "http://iec.ch/TC57/61970-552/DifferenceModel/1#", 
    "dm:DifferenceModel": {
      "@id": "urn:uuid:f52f12c3-db10-4d41-a9f2-b1fe29ab4d6d",
      "@container": ["@graph", "@id"]
    }
  },

  "dm:DifferenceModel": {
    "@none": [{
        "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
        "@type": "cim:ACLineSegment",
        "cim:Conductor.length": {
                "cim:Length.value": 50.0
        }
    }, {
        "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
        "@type": "cim:ACLineSegment",
        "cim:Conductor.length": {
                "cim:Length.value": 55.0
        }
    }]
  }
}
ThomasRanvikEriksen commented 1 year ago

My team like this idea but there are some issues we discussed internally that needs to be addressed

Both alternatives have array for @graph, reverseDifferences and forwardDifferences. What is allowed to do. Depends also on what the header is ment to provide. If the header is ment to provie timestamp you will have issues if you include more than 1 difference to the same object (ACLineSegment @id) in the same message. You will also have issues if you send more than one difference object (difference @id) in the same message since they are most likely not executed at the same timestamp. The main difference between the first alternativ and the second is that the second can have its own id for both reverse and forward but then it also should have its own timestamp? The second option have its onw ids, but you don't have a relation between the reverse and forward anymore.

So what can be done and what can not. What must be enforced?

Examples:

Option1 (Which change is the latest one?):

{
    "@context": {
        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
        "cim": "http://iec.ch/TC57/CIM100#",
        "md": "http://iec.ch/TC57/61970-552/ModelDescription/1#",
        "eu": "http://iec.ch/TC57/CIM100-European#",
        "dm": "http://iec.ch/TC57/61970-552/DifferenceModel/1#"
    },
    "@graph": [
        {
            "@id": "urn:uuid:f52f12c3-db10-4d41-a9f2-b1fe29ab4d6d",
            "@type": "dm:DifferenceModel",
            "dm:reverseDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 50.0
                    }
                },
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d5",
                    "@type": "cim:Switch",
                    "cim:IdentifiedObject.Name": "Switch1"
                }
            ],
            "dm:forwardDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 55.0
                    }
                },
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d5",
                    "@type": "cim:Switch",
                    "cim:IdentifiedObject.Name": "Switch2"
                }
            ]
        },
        {
            "@id": "urn:uuid:f52f12c3-db10-4d41-a9f2-b1fe29ab4d6a",
            "@type": "dm:DifferenceModel",
            "dm:reverseDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 60.0
                    }
                }
            ],
            "dm:forwardDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 65.0
                    }
                }
            ]
        }
    ]
}

Option2 (Which change is the latest one and which forward is connected to which reversed?):

{
    "@context": {
        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
        "cim": "http://iec.ch/TC57/CIM100#",
        "md": "http://iec.ch/TC57/61970-552/ModelDescription/1#",
        "eu": "http://iec.ch/TC57/CIM100-European#",
        "dm": "http://iec.ch/TC57/61970-552/DifferenceModel/1#"
    },
    "@graph": [
        {
            "@id": "urn:uuid:f52f12c3-db10-4d41-a9f2-b1fe29ab4d6d",
            "@type": "dm:DifferenceModel",
            "dm:reverseDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 50.0
                    }
                },
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d5",
                    "@type": "cim:Switch",
                    "cim:IdentifiedObject.Name": "Switch1"
                }
            ]
        },
        {
            "@id": "urn:uuid:f1aa3e3a-8391-4bf9-b435-6bd0702f9e0d",
            "@type": "dm:DifferenceModel",
            "dm:forwardDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 55.0
                    }
                },
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d5",
                    "@type": "cim:Switch",
                    "cim:IdentifiedObject.Name": "Switch2"
                }
            ]
        },
        {
            "@id": "urn:uuid:f52f12c3-db10-4d41-a9f2-b1fe29ab4d6t",
            "@type": "dm:DifferenceModel",
            "dm:reverseDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 60.0
                    }
                }
            ]
        },
        {
            "@id": "urn:uuid:f1aa3e3a-8391-4bf9-b435-6bd0702f9e0ru",
            "@type": "dm:DifferenceModel",
            "dm:forwardDifferences": [
                {
                    "@id": "urn:uuid:9d58e5bb-834c-4faa-928c-7da0bb1497d9",
                    "@type": "cim:ACLineSegment",
                    "cim:Conductor.length": {
                        "cim:Length.value": 65.0
                    }
                }
            ]
        }
    ]
}
Sveino commented 1 year ago

Very important! The difference model are not meant to replace audit-trail inside an application. It is also not intended to track changes that is related to activity. We are focus on the exchange of structure data in a digital twin. This to support:

It must be possible to exchange any "droddeling" changes - particularly just adding stuff. The time is not central, but the dependency are central - we are using this to model alternative into the future.

The header of the difference model should follow the same header as any dataset. However, one instance of the DifferenceModel dataset can only change one dataset, e.g. if EQ is exchange as one dataset including EQ-Core, EQ-ShortCircute the difference model dataset can include changes to data that confirms to both set.

A DifferenceModel dataset can only include two graph (ForwardModel and ReversModel). It include the net change from the previous exchange (or generated) model. However, there can be different version of the difference model. In this case the resolving model version will be different.

For a Compound (e.g. Money) all the element must be include in both the reverse and forward model.

  • Should it support multiple changes to the same component in the same message?

Yes, all changes to the same component can be handle in the same dataset.

  • Should it support changes to multiple components in the same message (Even if they are executed on different timestamp)?

Yes, if the changes should be applied to the same model. E.g. Switch A might be installed on a different time than Switch B, but they are both part of an update to the Power System model that does not require separate analysis. All changes are considered a set of changes - However, a given set can consist of only one change. We are exchanging all the relevant changes that belongs together.

  • Should it support multiple changes over time in the same message or do you need to send them separately?

If we are looking at the future we can make update to the same dataset (with separate version), but if changes applied to the as-built there must be send separately even if the changes was infarct made at the same time.

  • Can you send a message that only include forward? (What is optional and not?) (forward and reveres is doable with modern systems, but we have some issues regarding older systems)

The dataset shall include both forward and reverse model (and only those), but one of them can be empty.

For a class to be deleted it needs to include all the attribute that has values.

This will be specified in the upcoming 61970-553 and not -552

Relevant rules from 61970-600-1:

FBOD5. A difference model shall not be created in cases where the numeric differences are outside the accuracy of the attributes’ numerical declaration, e.g. a xsd:float is considered to only have 7-digit accuracy. It is up to the application to define a suitable tolerance value when creating difference files. (R:600:ALL:NA:float)
GENC18. Decimal character for floating point numbers shall only be a full stop. This constraint is necessary because local (regional) settings may select either comma or full stop and a particular local settings do not support both comma and full stop. The mix of comma and full stop prevents interoperability: hence one must be selected.
EXCH4. For CGMES exchanges a Topology profile distribution is not exchanged using a difference file. In CGMES Topology profile distribution is only exchanged as full model.
MAS_7. A new mRID is generated in case there is a need to change the class (e.g. GeneratingUnit is changed to ThermalGeneratingUnit in a sequence of exchanges in a process). If a physical unit given by mRID in the asset part of the CIM needs to be represented simultaneously as GeneratingUnit and ThermalGeneratingUnit (a given specialisation) it must have different mRIDs for GeneratingUnit and ThermalGeneratingUnit. If different business processes are required to support both types (GeneratingUnit and ThermalGeneratingUnit), the applications should maintain two mRIDs and in both cases support difference file exchange.
DL__1. A full Diagram (non-difference instance file) represents a new drawing of the diagram. Data may change from one system drawing to another, e.g. two diagrams with the same mRID of the classes in the instance files (distribution) do not need to be identical. The purpose of the Diagram layout profile is to support the understanding of the equipment data. If a diagram generated by one system is updated by another the file does not need to be identical, with the exception of the edited changes. However, the updated and exported diagram instance file shall include all the same relevant information and must have the same layout rendering in the new destination system (old source) as the original, with the exception of the changes. The expected behaviour is that a diagram may have a new layout with the same Diagram mRID as well as DiagramObject mRID. Persistence of Diagram and DiagramObject mRIDs is required if difference updates are supported
FILX7. In case difference files are exchanged, the same dependencies as for full model exchange are followed. The difference file (e.g. equipment, topology or dynamics) should refer to the base model, which is subject of an update. Dependencies are listed in the file header of each file which is exchanged.

EQ (all of them), DY, GL and DL and boundary can be updated with difference model. SSH, TP and SV cannot.