@@ -103,6 +103,40 @@ static FMIModelDescription* readModelDescriptionFMI1(xmlNodePtr root) {
103103
104104 const char * typeName = (char * )typeNode -> name ;
105105
106+ const char * causality = (char * )xmlGetProp (variableNode , (xmlChar * )"causality" );
107+
108+ if (!causality ) {
109+ // default
110+ variable -> causality = FMILocal ;
111+ } else if (!strcmp (causality , "input" )) {
112+ variable -> causality = FMIInput ;
113+ } else if (!strcmp (causality , "output" )) {
114+ variable -> causality = FMIOutput ;
115+ } else {
116+ // "internal" or "none"
117+ variable -> causality = FMILocal ;
118+ }
119+
120+ xmlFree ((void * )causality );
121+
122+ const char * variability = (char * )xmlGetProp (variableNode , (xmlChar * )"variability" );
123+
124+ if (!variability ) {
125+ // default
126+ variable -> variability = FMIContinuous ;
127+ } else if (!strcmp (variability , "constant" )) {
128+ variable -> variability = FMIConstant ;
129+ } else if (!strcmp (variability , "parameter" )) {
130+ variable -> causality = FMIParameter ;
131+ variable -> variability = FMITunable ;
132+ } else if (!strcmp (variability , "discrete" )) {
133+ variable -> variability = FMIDiscrete ;
134+ } else if (!strcmp (variability , "continuous" )) {
135+ variable -> variability = FMIContinuous ;
136+ }
137+
138+ free ((void * )variability );
139+
106140 if (!strcmp (typeName , "Real" )) {
107141 const char * variability = (char * )xmlGetProp (variableNode , (xmlChar * )"variability" );
108142 if (variability && !strcmp (variability , "discrete" )) {
@@ -123,29 +157,30 @@ static FMIModelDescription* readModelDescriptionFMI1(xmlNodePtr root) {
123157
124158 variable -> valueReference = getUInt32Attribute (variableNode , "valueReference" );
125159
126- const char * causality = ( char * ) xmlGetProp ( variableNode , ( xmlChar * ) "causality" );
160+ }
127161
128- if (!causality ) {
129- variable -> causality = FMILocal ;
130- } else if (!strcmp (causality , "parameter" )) {
131- variable -> causality = FMIParameter ;
132- } else if (!strcmp (causality , "input" )) {
133- variable -> causality = FMIInput ;
134- } else if (!strcmp (causality , "output" )) {
135- variable -> causality = FMIOutput ;
136- } else if (!strcmp (causality , "independent" )) {
137- variable -> causality = FMIIndependent ;
138- } else {
139- variable -> causality = FMILocal ;
140- }
162+ size_t nProblems = 0 ;
141163
142- xmlFree ((void * )causality );
164+ // check variabilities
165+ for (size_t i = 0 ; i < modelDescription -> nModelVariables ; i ++ ) {
166+ FMIModelVariable * variable = & modelDescription -> modelVariables [i ];
167+ if (variable -> type != FMIRealType && variable -> type != FMIDiscreteRealType && variable -> variability == FMIContinuous ) {
168+ printf ("Variable \"%s\" is not of type Real but has variability = continuous.\n" , variable -> name );
169+ nProblems ++ ;
170+ }
143171 }
144172
145173 xmlXPathFreeObject (xpathObj );
146174
147175 xmlXPathFreeContext (xpathCtx );
148176
177+ if (nProblems > 0 ) {
178+ FMIFreeModelDescription (modelDescription );
179+ modelDescription = NULL ;
180+ }
181+
182+ return modelDescription ;
183+
149184 return modelDescription ;
150185}
151186
@@ -260,29 +295,38 @@ static FMIModelDescription* readModelDescriptionFMI2(xmlNodePtr root) {
260295
261296 variable -> derivative = (FMIModelVariable * )xmlGetProp (typeNode , (xmlChar * )"derivative" );
262297
263- FMIVariableType type ;
264298 const char * typeName = (char * )typeNode -> name ;
265299
300+ const char * variability = (char * )xmlGetProp (variableNode , (xmlChar * )"variability" );
301+
302+ if (!variability ) {
303+ variable -> variability = FMIContinuous ;
304+ } else if (!strcmp (variability , "constant" )) {
305+ variable -> variability = FMIConstant ;
306+ } else if (!strcmp (variability , "fixed" )) {
307+ variable -> variability = FMIFixed ;
308+ } else if (!strcmp (variability , "tunable" )) {
309+ variable -> variability = FMITunable ;
310+ } else if (!strcmp (variability , "discrete" )) {
311+ variable -> variability = FMIDiscrete ;
312+ } else {
313+ variable -> variability = FMIContinuous ;
314+ }
315+
316+ free ((void * )variability );
317+
266318 if (!strcmp (typeName , "Real" )) {
267- const char * variability = (char * )xmlGetProp (variableNode , (xmlChar * )"variability" );
268- if (variability && (!strcmp (variability , "discrete" ) || !strcmp (variability , "tunable" ))) {
269- type = FMIDiscreteRealType ;
270- } else {
271- type = FMIRealType ;
272- }
273- free ((void * )variability );
319+ variable -> type = variable -> variability == FMIDiscrete ? FMIDiscreteRealType : FMIRealType ;
274320 } else if (!strcmp (typeName , "Integer" ) || !strcmp (typeName , "Enumeration" )) {
275- type = FMIIntegerType ;
321+ variable -> type = FMIIntegerType ;
276322 } else if (!strcmp (typeName , "Boolean" )) {
277- type = FMIBooleanType ;
323+ variable -> type = FMIBooleanType ;
278324 } else if (!strcmp (typeName , "String" )) {
279- type = FMIStringType ;
325+ variable -> type = FMIStringType ;
280326 } else {
281327 continue ;
282328 }
283329
284- variable -> type = type ;
285-
286330 const char * vr = (char * )xmlGetProp (variableNode , (xmlChar * )"valueReference" );
287331
288332 variable -> valueReference = FMIValueReferenceForLiteral (vr );
@@ -332,6 +376,15 @@ static FMIModelDescription* readModelDescriptionFMI2(xmlNodePtr root) {
332376 }
333377 }
334378
379+ // check variabilities
380+ for (size_t i = 0 ; i < modelDescription -> nModelVariables ; i ++ ) {
381+ FMIModelVariable * variable = & modelDescription -> modelVariables [i ];
382+ if (variable -> type != FMIRealType && variable -> type != FMIDiscreteRealType && variable -> variability == FMIContinuous ) {
383+ printf ("Variable \"%s\" is not of type Real but has variability = continuous.\n" , variable -> name );
384+ nProblems ++ ;
385+ }
386+ }
387+
335388 nProblems += FMIValidateModelStructure (modelDescription );
336389
337390 if (nProblems > 0 ) {
@@ -420,13 +473,43 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
420473 const char * name = (char * )node -> name ;
421474
422475 const char * variability = (char * )xmlGetProp (node , (xmlChar * )"variability" );
423- const bool discrete = variability && (!strcmp (variability , "discrete" ) || !strcmp (variability , "tunable" ));
476+
477+ if (!variability ) {
478+ variable -> variability = -1 ; // infer from type
479+ } else if (!strcmp (variability , "constant" )) {
480+ variable -> variability = FMIConstant ;
481+ } else if (!strcmp (variability , "fixed" )) {
482+ variable -> variability = FMIFixed ;
483+ } else if (!strcmp (variability , "tunable" )) {
484+ variable -> variability = FMITunable ;
485+ } else if (!strcmp (variability , "discrete" )) {
486+ variable -> variability = FMIDiscrete ;
487+ } else {
488+ variable -> variability = FMIContinuous ;
489+ }
490+
424491 free ((void * )variability );
425492
426493 if (!strcmp (name , "Float32" )) {
427- type = discrete ? FMIDiscreteFloat32Type : FMIFloat32Type ;
494+ switch (variable -> variability ) {
495+ case -1 :
496+ case FMIContinuous :
497+ type = FMIFloat32Type ;
498+ break ;
499+ default :
500+ type = FMIDiscreteFloat32Type ;
501+ break ;
502+ }
428503 } else if (!strcmp (name , "Float64" )) {
429- type = discrete ? FMIDiscreteFloat64Type : FMIFloat64Type ;
504+ switch (variable -> variability ) {
505+ case -1 :
506+ case FMIContinuous :
507+ type = FMIFloat64Type ;
508+ break ;
509+ default :
510+ type = FMIDiscreteFloat64Type ;
511+ break ;
512+ }
430513 } else if (!strcmp (name , "Int8" )) {
431514 type = FMIInt8Type ;
432515 } else if (!strcmp (name , "UInt8" )) {
@@ -457,6 +540,18 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
457540
458541 variable -> type = type ;
459542
543+ if (variable -> variability == -1 ) {
544+ switch (variable -> type ) {
545+ case FMIFloat32Type :
546+ case FMIFloat64Type :
547+ variable -> variability = FMIContinuous ;
548+ break ;
549+ default :
550+ variable -> variability = FMIDiscrete ;
551+ break ;
552+ }
553+ }
554+
460555 const char * vr = (char * )xmlGetProp (node , (xmlChar * )"valueReference" );
461556
462557 variable -> valueReference = FMIValueReferenceForLiteral (vr );
@@ -483,6 +578,8 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
483578 variable -> causality = FMILocal ;
484579 }
485580
581+ free (causality );
582+
486583 variable -> derivative = (FMIModelVariable * )xmlGetProp (node , (xmlChar * )"derivative" );
487584
488585 xmlXPathObjectPtr xpathObj2 = xmlXPathNodeEval (node , ".//Dimension" , xpathCtx );
@@ -532,6 +629,17 @@ static FMIModelDescription* readModelDescriptionFMI3(xmlNodePtr root) {
532629
533630 size_t nProblems = 0 ;
534631
632+ // check variabilities
633+ for (size_t i = 0 ; i < modelDescription -> nModelVariables ; i ++ ) {
634+
635+ FMIModelVariable * variable = & modelDescription -> modelVariables [i ];
636+
637+ if (variable -> type != FMIFloat32Type && variable -> type != FMIFloat64Type && variable -> variability == FMIContinuous ) {
638+ printf ("Variable \"%s\" is not of type Float{32|64} but has variability = continuous.\n" , variable -> name );
639+ nProblems ++ ;
640+ }
641+ }
642+
535643 // resolve derivatives
536644 for (size_t i = 0 ; i < modelDescription -> nModelVariables ; i ++ ) {
537645
0 commit comments