From e31766fe883156b931b5861eaff967fa0dcee32b Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Sat, 29 Apr 2023 17:48:13 +0200 Subject: [PATCH 1/2] Build with Ubuntu 20.04 and macOS 11 in CI --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 55bd13c..74c2e13 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -57,7 +57,7 @@ jobs: - job: maci64 displayName: 'macOS' pool: - vmImage: 'macos-10.15' + vmImage: 'macos-11' steps: @@ -89,7 +89,7 @@ jobs: - win32 - win64 pool: - vmImage: 'ubuntu-18.04' + vmImage: 'ubuntu-20.04' steps: From 9d898c9e919989f8b46e997ddbda30b681cf3f6e Mon Sep 17 00:00:00 2001 From: Torsten Sommer Date: Sat, 29 Apr 2023 17:37:04 +0200 Subject: [PATCH 2/2] Handle FMI 3.0 Enumerations in FMU import fixes #408 --- .../main/java/fmikit/ui/FMUBlockDialog.java | 13 ++--- Java/src/main/java/fmikit/ui/Util.java | 19 ++++++-- src/sfun_fmurun.c | 48 ++++++++++++++++++- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/Java/src/main/java/fmikit/ui/FMUBlockDialog.java b/Java/src/main/java/fmikit/ui/FMUBlockDialog.java index caf66a4..441600e 100644 --- a/Java/src/main/java/fmikit/ui/FMUBlockDialog.java +++ b/Java/src/main/java/fmikit/ui/FMUBlockDialog.java @@ -14,6 +14,7 @@ import javax.imageio.ImageIO; import javax.swing.*; +import javax.swing.border.TitledBorder; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.tree.*; import java.awt.*; @@ -833,7 +834,7 @@ public String getSFunctionParameters() { String startValue = startValues.get(variable.name); if ("structuralParameter".equals(variable.causality)) { - structuralParameterTypes.add(Util.typeEnumForVariable(variable)); + structuralParameterTypes.add(Util.typeEnumForVariable(variable, modelDescription.fmiVersion)); structuralParameterVRs.add(variable.valueReference); structuralParameterValues.add(startValue); } else if ("String".equals(variable.type)) { @@ -842,7 +843,7 @@ public String getSFunctionParameters() { stringStartValues.add("'" + startValue + "'"); } else { scalarStartSizes.add(variableSize); - scalarStartTypes.add(Util.typeEnumForVariable(variable)); + scalarStartTypes.add(Util.typeEnumForVariable(variable, modelDescription.fmiVersion)); scalarStartVRs.add(variable.valueReference); scalarStartValues.add(startValue); } @@ -869,7 +870,7 @@ public String getSFunctionParameters() { inputPortWidths.add(inputPortWidth); - inputPortTypes.add(Util.typeEnumForVariable(firstVariable)); + inputPortTypes.add(Util.typeEnumForVariable(firstVariable, modelDescription.fmiVersion)); for (ScalarVariable variable : inputPort) { inputPortVariableVRs.add(variable.valueReference); @@ -895,7 +896,7 @@ public String getSFunctionParameters() { outportWidths.add(portWidth); - outportPortTypes.add(Util.typeEnumForVariable(firstVariable)); + outportPortTypes.add(Util.typeEnumForVariable(firstVariable, modelDescription.fmiVersion)); for (ScalarVariable variable : outputPort) { outputPortVariableVRs.add(variable.valueReference); @@ -1005,7 +1006,7 @@ public String getSFunctionParameters() { params.add(isTunable ? "1" : "0"); // variable type - params.add(Integer.toString(Util.typeEnumForVariable(variable))); + params.add(Integer.toString(Util.typeEnumForVariable(variable, modelDescription.fmiVersion))); // value reference params.add(variable.valueReference); @@ -1772,7 +1773,7 @@ public void setStartValue(String variableName, String startValue) { panel7.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); panel7.setOpaque(false); panel4.add(panel7, new GridConstraints(1, 2, 9, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_VERTICAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(280, 280), new Dimension(280, 280), new Dimension(280, 280), 0, false)); - panel7.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), null)); + panel7.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); lblModelImage = new JLabel(); lblModelImage.setEnabled(false); lblModelImage.setText("no image available"); diff --git a/Java/src/main/java/fmikit/ui/Util.java b/Java/src/main/java/fmikit/ui/Util.java index 6a48001..c5a87fd 100644 --- a/Java/src/main/java/fmikit/ui/Util.java +++ b/Java/src/main/java/fmikit/ui/Util.java @@ -11,6 +11,7 @@ import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.awt.*; import java.io.File; @@ -55,9 +56,11 @@ public static void setTreeExpandedState(JTree tree, boolean expanded) { } public static void setNodeExpandedState(JTree tree, DefaultMutableTreeNode node, boolean expanded) { - ArrayList list = Collections.list(node.children()); - for (DefaultMutableTreeNode treeNode : list) { - setNodeExpandedState(tree, treeNode, expanded); + ArrayList list = Collections.list(node.children()); + for (Object treeNode : list) { + if (treeNode instanceof DefaultMutableTreeNode) { + setNodeExpandedState(tree, (DefaultMutableTreeNode) treeNode, expanded); + } } if (!expanded && node.isRoot()) { return; @@ -173,7 +176,7 @@ public static void delete(File f) throws IOException { throw new FileNotFoundException("Failed to delete file: " + f); } - public static int typeEnumForVariable(ScalarVariable variable) { + public static int typeEnumForVariable(final ScalarVariable variable, final String fmiVersion) { final String type = variable.type; final boolean discrete = "tunable".equals(variable.variability) || "discrete".equals(variable.variability); @@ -190,7 +193,7 @@ public static int typeEnumForVariable(ScalarVariable variable) { return 6; } else if ("UInt16".equals(type)) { return 7; - } else if ("Int32".equals(type) || "Integer".equals(type) || "Enumeration".equals(type)) { + } else if ("Int32".equals(type) || "Integer".equals(type)) { return 8; } else if ("UInt32".equals(type)) { return 9; @@ -206,6 +209,12 @@ public static int typeEnumForVariable(ScalarVariable variable) { return 14; } else if ("Clock".equals(type)) { return 15; + } else if ("Enumeration".equals(type)) { + if ("1.0".equals(fmiVersion) || "2.0".equals(fmiVersion)) { + return 8; + } else { + return 10; + } } throw new RuntimeException("Unknown variable type: " + type); diff --git a/src/sfun_fmurun.c b/src/sfun_fmurun.c index f3e170b..dd04478 100644 --- a/src/sfun_fmurun.c +++ b/src/sfun_fmurun.c @@ -224,6 +224,8 @@ static DTypeId simulinkVariableType(SimStruct *S, Parameter parameter, size_t in case FMIUInt16Type: return SS_UINT16; case FMIInt32Type: return SS_INT32; case FMIUInt32Type: return SS_UINT32; + case FMIInt64Type: return SS_INT32; + case FMIUInt64Type: return SS_UINT32; case FMIBooleanType: return SS_BOOLEAN; default: return -1; // error } @@ -570,6 +572,24 @@ static void setInput(SimStruct *S, bool direct, bool discrete, bool *inputEvent) case FMIUInt32Type: CHECK_STATUS(FMI3SetUInt32(instance, &vr, 1, (const uint32_T *)y, nValues)); break; + case FMIInt64Type: { + fmi3Int64* values = (fmi3Int64*)calloc(nValues, sizeof(fmi3Int64)); + for (int j = 0; j < nValues; j++) { + values[j] = ((const int32_T*)y)[j]; + } + CHECK_STATUS(FMI3SetInt64(instance, &vr, 1, values, nValues)); + free(values); + break; + } + case FMIUInt64Type: { + fmi3UInt64* values = (fmi3UInt64*)calloc(nValues, sizeof(fmi3UInt64)); + for (int j = 0; j < nValues; j++) { + values[j] = ((const uint32_T*)y)[j]; + } + CHECK_STATUS(FMI3SetUInt64(instance, &vr, 1, values, nValues)); + free(values); + break; + } case FMIBooleanType: { fmi3Boolean *values = (fmi3Boolean *)calloc(nValues, sizeof(fmi3Boolean)); for (int j = 0; j < nValues; j++) { @@ -688,6 +708,24 @@ static void getOutput(SimStruct *S) { case FMIUInt32Type: CHECK_STATUS(FMI3GetUInt32(instance, &vr, 1, (uint32_T *)y, nValues)); break; + case FMIInt64Type: { + fmi3Int64* values = (fmi3Int64*)calloc(nValues, sizeof(fmi3Int64)); + CHECK_STATUS(FMI3GetInt64(instance, &vr, 1, values, nValues)); + for (int j = 0; j < nValues; j++) { + ((int32_T*)y)[j] = values[j]; + } + free(values); + break; + } + case FMIUInt64Type: { + fmi3UInt64* values = (fmi3UInt64*)calloc(nValues, sizeof(fmi3UInt64)); + CHECK_STATUS(FMI3GetUInt64(instance, &vr, 1, values, nValues)); + for (int j = 0; j < nValues; j++) { + ((uint32_T*)y)[j] = values[j]; + } + free(values); + break; + } case FMIBooleanType: { fmi3Boolean *values = (fmi3Boolean *)calloc(nValues, sizeof(fmi3Boolean)); CHECK_STATUS(FMI3GetBoolean(instance, &vr, 1, values, nValues)); @@ -1496,7 +1534,11 @@ static void mdlInitializeSizes(SimStruct *S) { for (int i = 0; i < nu(S); i++) { ssSetInputPortWidth(S, i, inputPortWidth(S, i)); ssSetInputPortRequiredContiguous(S, i, 1); // direct input signal access - DTypeId type = simulinkVariableType(S, inputPortTypesParam, i); + const DTypeId type = simulinkVariableType(S, inputPortTypesParam, i); + if (type < 0) { + setErrorStatus(S, "Unexpected type id for input port %d.", i); + return; + } ssSetInputPortDataType(S, i, type); bool dirFeed = inputPortDirectFeedThrough(S, i); ssSetInputPortDirectFeedThrough(S, i, dirFeed); // direct feed through @@ -1515,6 +1557,10 @@ static void mdlInitializeSizes(SimStruct *S) { for (int i = 0; i < ny(S); i++) { ssSetOutputPortWidth(S, i, outputPortWidth(S, i)); DTypeId type = simulinkVariableType(S, outputPortTypesParam, i); + if (type < 0) { + setErrorStatus(S, "Unexpected type id for output port %d.", i); + return; + } ssSetOutputPortDataType(S, i, type); }