From 3b12a7bd2a8497acb922f1a185390db2b46ed06b Mon Sep 17 00:00:00 2001 From: Kristoffer Skare Date: Wed, 18 Dec 2024 16:40:14 +0100 Subject: [PATCH 1/6] Change generated modelDescription to have 1-indexed Unknown tags --- src/mlfmu/utils/fmi_builder.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlfmu/utils/fmi_builder.py b/src/mlfmu/utils/fmi_builder.py index b418f8c..0ba6faf 100644 --- a/src/mlfmu/utils/fmi_builder.py +++ b/src/mlfmu/utils/fmi_builder.py @@ -97,7 +97,8 @@ def generate_model_description(fmu_model: FmiModel) -> ElementTree: # Appending output to inside if var.causality == FmiCausality.OUTPUT: - _ = SubElement(outputs, "Unknown", {"index": str(var.variable_reference)}) + # Index is 1-indexed for tag + _ = SubElement(outputs, "Unknown", {"index": str(var.variable_reference + 1)}) # Create XML tree containing root element and pretty format its contents xml_tree = ElementTree(root) From 62d21f848cf200dab69d980306c769f637bdb56b Mon Sep 17 00:00:00 2001 From: Kristoffer Skare Date: Wed, 18 Dec 2024 16:43:30 +0100 Subject: [PATCH 2/6] Include InitialUnknowns tag containing all outputs in generated modelDescription --- src/mlfmu/utils/fmi_builder.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mlfmu/utils/fmi_builder.py b/src/mlfmu/utils/fmi_builder.py index 0ba6faf..0a68038 100644 --- a/src/mlfmu/utils/fmi_builder.py +++ b/src/mlfmu/utils/fmi_builder.py @@ -76,6 +76,7 @@ def generate_model_description(fmu_model: FmiModel) -> ElementTree: # tag with tab inside --> Append all outputs model_structure = SubElement(root, "ModelStructure") outputs = SubElement(model_structure, "Outputs") + initial_unknowns = SubElement(model_structure, "InitialUnknowns") for var in fmu_model.get_fmi_model_variables(): # XML variable attributes @@ -95,10 +96,13 @@ def generate_model_description(fmu_model: FmiModel) -> ElementTree: # FMI variable type element _ = SubElement(var_elem, var.type.value.capitalize(), var_type_attrs) - # Appending output to inside + # Adding outputs inside if var.causality == FmiCausality.OUTPUT: # Index is 1-indexed for tag - _ = SubElement(outputs, "Unknown", {"index": str(var.variable_reference + 1)}) + unknown_attributes = {"index": str(var.variable_reference + 1)} + # For each output create an tag inside both and + _ = SubElement(outputs, "Unknown", unknown_attributes) + _ = SubElement(initial_unknowns, "Unknown", unknown_attributes) # Create XML tree containing root element and pretty format its contents xml_tree = ElementTree(root) From 95beb793a45fe5306ea11f9560dd948abd7549b2 Mon Sep 17 00:00:00 2001 From: Kristoffer Skare Date: Wed, 18 Dec 2024 16:51:40 +0100 Subject: [PATCH 3/6] Update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d3914..1ff0424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the [mlfmu] project will be documented in this file.
The changelog format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## Unreleased + +### Changed + +* Generation of modelDescription.xml file to correctly generate tags for each output with 1-indexed indexes and InitialUnknowns tags + ## [1.0.2] ### Changed From d142bb9278ddf1680f1ef5e9b9242b5ed59339a2 Mon Sep 17 00:00:00 2001 From: Kristoffer Skare Date: Thu, 19 Dec 2024 08:38:31 +0100 Subject: [PATCH 4/6] Update model description generation test to reflect the changed correct behavior --- tests/utils/test_modelDescription_builder.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/utils/test_modelDescription_builder.py b/tests/utils/test_modelDescription_builder.py index 7af8308..7476b93 100644 --- a/tests/utils/test_modelDescription_builder.py +++ b/tests/utils/test_modelDescription_builder.py @@ -193,5 +193,6 @@ def test_generate_model_description_output(): output_variables = [var for var in variables if var.attrib.get("causality") == "output"] outputs_registered = xml_structure.findall(".//Outputs/Unknown") - assert output_variables[0].attrib["valueReference"] == outputs_registered[0].attrib["index"] - assert output_variables[1].attrib["valueReference"] == outputs_registered[1].attrib["index"] + # The index should be the valueReference + 1 + assert int(output_variables[0].attrib["valueReference"]) + 1 == int(outputs_registered[0].attrib["index"]) + assert int(output_variables[1].attrib["valueReference"]) + 1 == int(outputs_registered[1].attrib["index"]) From a5c0a2ab45076fc1e87366f883672d2424fdb861 Mon Sep 17 00:00:00 2001 From: Kristoffer Skare Date: Thu, 19 Dec 2024 13:51:10 +0100 Subject: [PATCH 5/6] Change the order of the variables added to the modelDescription to be sorted by their variableReference --- CHANGELOG.md | 1 + src/mlfmu/utils/fmi_builder.py | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ff0424..c88fc55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog format is based on [Keep a Changelog](https://keepachangelog.com/e ### Changed * Generation of modelDescription.xml file to correctly generate tags for each output with 1-indexed indexes and InitialUnknowns tags +* Generation of modelDescription.xml adds the variables (inputs, parameters and outputs) in the orderer of their valueReference. This is for the indexing to work correctly ## [1.0.2] diff --git a/src/mlfmu/utils/fmi_builder.py b/src/mlfmu/utils/fmi_builder.py index 0a68038..cdb3595 100644 --- a/src/mlfmu/utils/fmi_builder.py +++ b/src/mlfmu/utils/fmi_builder.py @@ -78,7 +78,14 @@ def generate_model_description(fmu_model: FmiModel) -> ElementTree: outputs = SubElement(model_structure, "Outputs") initial_unknowns = SubElement(model_structure, "InitialUnknowns") - for var in fmu_model.get_fmi_model_variables(): + # Get all variables to add them inside the tag + model_variables = fmu_model.get_fmi_model_variables() + + # The variables needs to be added in the order of their valueReference + sorted_model_variables = sorted(model_variables, key=lambda x: x.variable_reference) + + # Add each variable inside the tag + for var in sorted_model_variables: # XML variable attributes var_attrs = { "name": var.name, From e35f12c07c8dde617006de844bf909f42cff762f Mon Sep 17 00:00:00 2001 From: Kristoffer Skare Date: Thu, 19 Dec 2024 13:54:05 +0100 Subject: [PATCH 6/6] Change test for model description with internal state params to expect the output and state in opposite order. --- tests/utils/test_modelDescription_builder.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/utils/test_modelDescription_builder.py b/tests/utils/test_modelDescription_builder.py index 7476b93..2ba348f 100644 --- a/tests/utils/test_modelDescription_builder.py +++ b/tests/utils/test_modelDescription_builder.py @@ -56,13 +56,14 @@ def test_generate_model_description_with_internal_state_params(): variables = xml_structure.findall(".//ScalarVariable") assert xml_structure.getroot().tag == "fmiModelDescription" - assert variables[0].attrib["name"] == "state1" - assert variables[0].attrib["causality"] == "parameter" - assert variables[0][0].tag == "Real" - assert variables[0][0].attrib["start"] == "0.0" - assert variables[1].attrib["name"] == "output1" - assert variables[1].attrib["causality"] == "output" + assert variables[0].attrib["name"] == "output1" + assert variables[0].attrib["causality"] == "output" + + assert variables[1].attrib["name"] == "state1" + assert variables[1].attrib["causality"] == "parameter" + assert variables[1][0].tag == "Real" + assert variables[1][0].attrib["start"] == "0.0" def test_generate_vector_ports():