diff --git a/Resource/FMI1CS.xml b/Resource/FMI1CS.xml
index 290fec3e..8d91bad3 100644
--- a/Resource/FMI1CS.xml
+++ b/Resource/FMI1CS.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/fmusim/FMIModelDescription.c b/fmusim/FMIModelDescription.c
index 4da3e468..619186ed 100644
--- a/fmusim/FMIModelDescription.c
+++ b/fmusim/FMIModelDescription.c
@@ -103,6 +103,40 @@ static FMIModelDescription* readModelDescriptionFMI1(xmlNodePtr root) {
const char* typeName = (char*)typeNode->name;
+ const char* causality = (char*)xmlGetProp(variableNode, (xmlChar*)"causality");
+
+ if (!causality) {
+ // default
+ variable->causality = FMILocal;
+ } else if (!strcmp(causality, "input")) {
+ variable->causality = FMIInput;
+ } else if (!strcmp(causality, "output")) {
+ variable->causality = FMIOutput;
+ } else {
+ // "internal" or "none"
+ variable->causality = FMILocal;
+ }
+
+ xmlFree((void*)causality);
+
+ const char* variability = (char*)xmlGetProp(variableNode, (xmlChar*)"variability");
+
+ if (!variability) {
+ // default
+ variable->variability = FMIContinuous;
+ } else if (!strcmp(variability, "constant")) {
+ variable->variability = FMIConstant;
+ } else if (!strcmp(variability, "parameter")) {
+ variable->causality = FMIParameter;
+ variable->variability = FMITunable;
+ } else if (!strcmp(variability, "discrete")) {
+ variable->variability = FMIDiscrete;
+ } else if (!strcmp(variability, "continuous")) {
+ variable->variability = FMIContinuous;
+ }
+
+ free((void*)variability);
+
if (!strcmp(typeName, "Real")) {
const char* variability = (char*)xmlGetProp(variableNode, (xmlChar*)"variability");
if (variability && !strcmp(variability, "discrete")) {
@@ -123,29 +157,30 @@ static FMIModelDescription* readModelDescriptionFMI1(xmlNodePtr root) {
variable->valueReference = getUInt32Attribute(variableNode, "valueReference");
- const char* causality = (char*)xmlGetProp(variableNode, (xmlChar*)"causality");
+ }
- if (!causality) {
- variable->causality = FMILocal;
- } else if (!strcmp(causality, "parameter")) {
- variable->causality = FMIParameter;
- } else if (!strcmp(causality, "input")) {
- variable->causality = FMIInput;
- } else if (!strcmp(causality, "output")) {
- variable->causality = FMIOutput;
- } else if (!strcmp(causality, "independent")) {
- variable->causality = FMIIndependent;
- } else {
- variable->causality = FMILocal;
- }
+ size_t nProblems = 0;
- xmlFree((void*)causality);
+ // check variabilities
+ for (size_t i = 0; i < modelDescription->nModelVariables; i++) {
+ FMIModelVariable* variable = &modelDescription->modelVariables[i];
+ if (variable->type != FMIRealType && variable->type != FMIDiscreteRealType && variable->variability == FMIContinuous) {
+ printf("Variable \"%s\" is not of type Real but has variability = continuous.\n", variable->name);
+ nProblems++;
+ }
}
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx);
+ if (nProblems > 0) {
+ FMIFreeModelDescription(modelDescription);
+ modelDescription = NULL;
+ }
+
+ return modelDescription;
+
return modelDescription;
}
@@ -260,29 +295,38 @@ static FMIModelDescription* readModelDescriptionFMI2(xmlNodePtr root) {
variable->derivative = (FMIModelVariable*)xmlGetProp(typeNode, (xmlChar*)"derivative");
- FMIVariableType type;
const char* typeName = (char*)typeNode->name;
+ const char* variability = (char*)xmlGetProp(variableNode, (xmlChar*)"variability");
+
+ if (!variability) {
+ variable->variability = FMIContinuous;
+ } else if(!strcmp(variability, "constant")) {
+ variable->variability = FMIConstant;
+ } else if (!strcmp(variability, "fixed")) {
+ variable->variability = FMIFixed;
+ } else if (!strcmp(variability, "tunable")) {
+ variable->variability = FMITunable;
+ } else if (!strcmp(variability, "discrete")) {
+ variable->variability = FMIDiscrete;
+ } else {
+ variable->variability = FMIContinuous;
+ }
+
+ free((void*)variability);
+
if (!strcmp(typeName, "Real")) {
- const char* variability = (char*)xmlGetProp(variableNode, (xmlChar*)"variability");
- if (variability && (!strcmp(variability, "discrete") || !strcmp(variability, "tunable"))) {
- type = FMIDiscreteRealType;
- } else {
- type = FMIRealType;
- }
- free((void*)variability);
+ variable->type = variable->variability == FMIDiscrete ? FMIDiscreteRealType : FMIRealType;
} else if (!strcmp(typeName, "Integer") || !strcmp(typeName, "Enumeration")) {
- type = FMIIntegerType;
+ variable->type = FMIIntegerType;
} else if (!strcmp(typeName, "Boolean")) {
- type = FMIBooleanType;
+ variable->type = FMIBooleanType;
} else if (!strcmp(typeName, "String")) {
- type = FMIStringType;
+ variable->type = FMIStringType;
} else {
continue;
}
- variable->type = type;
-
const char* vr = (char*)xmlGetProp(variableNode, (xmlChar*)"valueReference");
variable->valueReference = FMIValueReferenceForLiteral(vr);
@@ -332,6 +376,15 @@ static FMIModelDescription* readModelDescriptionFMI2(xmlNodePtr root) {
}
}
+ // check variabilities
+ for (size_t i = 0; i < modelDescription->nModelVariables; i++) {
+ FMIModelVariable* variable = &modelDescription->modelVariables[i];
+ if (variable->type != FMIRealType && variable->type != FMIDiscreteRealType && variable->variability == FMIContinuous) {
+ printf("Variable \"%s\" is not of type Real but has variability = continuous.\n", variable->name);
+ nProblems++;
+ }
+ }
+
nProblems += FMIValidateModelStructure(modelDescription);
if (nProblems > 0) {
@@ -420,13 +473,43 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
const char* name = (char*)node->name;
const char* variability = (char*)xmlGetProp(node, (xmlChar*)"variability");
- const bool discrete = variability && (!strcmp(variability, "discrete") || !strcmp(variability, "tunable"));
+
+ if (!variability) {
+ variable->variability = -1; // infer from type
+ } else if (!strcmp(variability, "constant")) {
+ variable->variability = FMIConstant;
+ } else if (!strcmp(variability, "fixed")) {
+ variable->variability = FMIFixed;
+ } else if (!strcmp(variability, "tunable")) {
+ variable->variability = FMITunable;
+ } else if (!strcmp(variability, "discrete")) {
+ variable->variability = FMIDiscrete;
+ } else {
+ variable->variability = FMIContinuous;
+ }
+
free((void*)variability);
if (!strcmp(name, "Float32")) {
- type = discrete ? FMIDiscreteFloat32Type : FMIFloat32Type;
+ switch (variable->variability) {
+ case -1:
+ case FMIContinuous:
+ type = FMIFloat32Type;
+ break;
+ default:
+ type = FMIDiscreteFloat32Type;
+ break;
+ }
} else if (!strcmp(name, "Float64")) {
- type = discrete ? FMIDiscreteFloat64Type : FMIFloat64Type;
+ switch (variable->variability) {
+ case -1:
+ case FMIContinuous:
+ type = FMIFloat64Type;
+ break;
+ default:
+ type = FMIDiscreteFloat64Type;
+ break;
+ }
} else if (!strcmp(name, "Int8")) {
type = FMIInt8Type;
} else if (!strcmp(name, "UInt8")) {
@@ -457,6 +540,18 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
variable->type = type;
+ if (variable->variability == -1) {
+ switch (variable->type) {
+ case FMIFloat32Type:
+ case FMIFloat64Type:
+ variable->variability = FMIContinuous;
+ break;
+ default:
+ variable->variability = FMIDiscrete;
+ break;
+ }
+ }
+
const char* vr = (char*)xmlGetProp(node, (xmlChar*)"valueReference");
variable->valueReference = FMIValueReferenceForLiteral(vr);
@@ -483,6 +578,8 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
variable->causality = FMILocal;
}
+ free(causality);
+
variable->derivative = (FMIModelVariable*)xmlGetProp(node, (xmlChar*)"derivative");
xmlXPathObjectPtr xpathObj2 = xmlXPathNodeEval(node, ".//Dimension", xpathCtx);
@@ -532,6 +629,17 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
size_t nProblems = 0;
+ // check variabilities
+ for (size_t i = 0; i < modelDescription->nModelVariables; i++) {
+
+ FMIModelVariable* variable = &modelDescription->modelVariables[i];
+
+ if (variable->type != FMIFloat32Type && variable->type != FMIFloat64Type && variable->variability == FMIContinuous) {
+ printf("Variable \"%s\" is not of type Float{32|64} but has variability = continuous.\n", variable->name);
+ nProblems++;
+ }
+ }
+
// resolve derivatives
for (size_t i = 0; i < modelDescription->nModelVariables; i++) {
diff --git a/fmusim/FMIModelDescription.h b/fmusim/FMIModelDescription.h
index e4c1af73..7c9c8e49 100644
--- a/fmusim/FMIModelDescription.h
+++ b/fmusim/FMIModelDescription.h
@@ -18,6 +18,16 @@ typedef enum {
} FMICausality;
+typedef enum {
+
+ FMIConstant,
+ FMIFixed,
+ FMITunable,
+ FMIDiscrete,
+ FMIContinuous
+
+} FMIVariability;
+
typedef struct FMIDimension FMIDimension;
typedef struct FMIModelVariable FMIModelVariable;
@@ -29,6 +39,7 @@ struct FMIModelVariable {
const char* description;
unsigned int valueReference;
FMICausality causality;
+ FMIVariability variability;
size_t nDimensions;
FMIDimension* dimensions;
FMIModelVariable* derivative;