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;