]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/Util/src/FMI2/fmi2_enums.c
Switch to full JavaSE-11+ compatibility
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / Util / src / FMI2 / fmi2_enums.c
1 /*
2     Copyright (C) 2012 Modelon AB
3
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the BSD style license.
6
7      This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10     FMILIB_License.txt file for more details.
11
12     You should have received a copy of the FMILIB_License.txt file
13     along with this program. If not, contact Modelon AB <http://www.modelon.com>.
14 */
15 #include <assert.h>
16 #include <stdio.h>
17
18 #include <FMI2/fmi2_functions.h>
19 #include <FMI2/fmi2_enums.h>
20
21 const char* fmi2_naming_convention_to_string(fmi2_variable_naming_convension_enu_t convention) {
22     if(convention == fmi2_naming_enu_flat) return "flat";
23     if(convention == fmi2_naming_enu_structured) return "structured";
24     return "Unknown";
25 }
26
27 const char* fmi2_fmu_kind_to_string(fmi2_fmu_kind_enu_t kind) {
28     switch (kind) {
29     case fmi2_fmu_kind_me: return "ModelExchange";
30     case fmi2_fmu_kind_cs: return "CoSimulation";
31     case fmi2_fmu_kind_me_and_cs: return "ModelExchange and CoSimulation";
32         default: break;
33     }
34     return "Unknown";
35 }
36
37 const char* fmi2_dependency_factor_kind_to_string(fmi2_dependency_factor_kind_enu_t fc) {
38         switch(fc) {
39         case fmi2_dependency_factor_kind_dependent: return "dependent";
40         case fmi2_dependency_factor_kind_constant: return "constant";
41         case fmi2_dependency_factor_kind_fixed: return "fixed";
42         case fmi2_dependency_factor_kind_tunable: return "tunable";
43         case fmi2_dependency_factor_kind_discrete: return "discrete";
44         default:break;
45         }
46         return "illegal factor kind";
47 }
48
49 const char* fmi2_variability_to_string(fmi2_variability_enu_t v) {
50     switch(v) {
51     case fmi2_variability_enu_constant: return "constant";
52     case fmi2_variability_enu_fixed: return "fixed";
53     case fmi2_variability_enu_tunable: return "tunable";
54     case fmi2_variability_enu_discrete: return "discrete";
55     case fmi2_variability_enu_continuous: return "continuous";
56         default: break;
57     }
58     return "Unknown";
59 }
60
61 const char* fmi2_causality_to_string(fmi2_causality_enu_t c) {
62     switch(c) {
63     case fmi2_causality_enu_input: return "input";
64     case fmi2_causality_enu_output: return "output";
65     case fmi2_causality_enu_parameter: return "parameter";
66     case fmi2_causality_enu_calculated_parameter: return "calculatedParameter";
67     case fmi2_causality_enu_local: return "local";
68     case fmi2_causality_enu_independent: return "independent";
69         default: break;
70     };
71     return "Unknown";
72 }
73
74 const char* fmi2_status_to_string(fmi2_status_t status) {
75         switch(status) {
76         case fmi2_status_ok:
77                 return "OK";
78         case fmi2_status_warning:
79                 return "Warning";
80         case fmi2_status_discard:
81                 return "Discard";
82         case fmi2_status_error:
83                 return "Error";
84         case fmi2_status_fatal:
85                 return "Fatal";
86         case fmi2_status_pending:
87                 return "Pending";
88         default: break;
89         }
90         return "Undefined";
91 }
92
93 const char* fmi2_base_type_to_string(fmi2_base_type_enu_t bt) {
94     switch(bt) {
95     case fmi2_base_type_real: return "Real";
96     case fmi2_base_type_int: return "Integer";
97     case fmi2_base_type_bool: return "Boolean";
98     case fmi2_base_type_str: return "String";
99     case fmi2_base_type_enum: return "Enumeration";
100         default: break;
101     }
102     return "Error";
103 }
104
105 const char* fmi2_initial_to_string(fmi2_initial_enu_t ini) {
106         switch (ini) {
107         case fmi2_initial_enu_exact: return "exact";
108         case fmi2_initial_enu_approx: return "approx";
109         case fmi2_initial_enu_calculated: return "calculated";
110                 default: break;
111         }
112         return "Undefined";
113 }
114
115 fmi2_initial_enu_t initialDefaultsTable[fmi2_variability_enu_unknown][fmi2_causality_enu_unknown] = {
116         /*              parameter                  calculated parameter,        input                     output                       local                        independent */
117         /* constant */  {fmi2_initial_enu_unknown, fmi2_initial_enu_unknown,    fmi2_initial_enu_unknown, fmi2_initial_enu_exact,      fmi2_initial_enu_exact,      fmi2_initial_enu_unknown},
118         /* fixed   */   {fmi2_initial_enu_exact,   fmi2_initial_enu_calculated, fmi2_initial_enu_approx,  fmi2_initial_enu_calculated, fmi2_initial_enu_calculated, fmi2_initial_enu_unknown},
119         /* tunable */   {fmi2_initial_enu_exact,   fmi2_initial_enu_calculated, fmi2_initial_enu_approx,  fmi2_initial_enu_calculated, fmi2_initial_enu_calculated, fmi2_initial_enu_unknown},
120         /* discrete */  {fmi2_initial_enu_unknown, fmi2_initial_enu_unknown,    fmi2_initial_enu_approx,  fmi2_initial_enu_calculated, fmi2_initial_enu_calculated, fmi2_initial_enu_unknown},
121         /* continuous */{fmi2_initial_enu_unknown, fmi2_initial_enu_unknown,    fmi2_initial_enu_approx,  fmi2_initial_enu_calculated, fmi2_initial_enu_calculated, fmi2_initial_enu_calculated}
122 };
123
124 fmi2_initial_enu_t fmi2_get_default_initial(fmi2_variability_enu_t v, fmi2_causality_enu_t c) {
125         if((unsigned)v >= (unsigned)fmi2_variability_enu_unknown) return fmi2_initial_enu_unknown;
126         if((unsigned)c >= (unsigned)fmi2_causality_enu_unknown) return fmi2_initial_enu_unknown;
127         return initialDefaultsTable[v][c];
128 }
129
130 FMILIB_EXPORT fmi2_initial_enu_t fmi2_get_valid_initial(fmi2_variability_enu_t v, fmi2_causality_enu_t c, fmi2_initial_enu_t i) {
131         fmi2_initial_enu_t defaultInitial = fmi2_get_default_initial(v, c);
132         if( (defaultInitial == i) ||
133                 ((unsigned)i >= (unsigned)fmi2_initial_enu_unknown) ||
134                 (defaultInitial == fmi2_initial_enu_unknown))
135                 return defaultInitial;
136         /*  At this point we know that v, c & i are fine and that (defaultInitial != i) 
137                 Check the other allowed combinations: */
138         if(defaultInitial == fmi2_initial_enu_calculated) {
139                 if(v >= fmi2_variability_enu_discrete) {
140                         return i;
141                 }
142                 else if(i != fmi2_initial_enu_exact)
143                         return i;
144         }
145         /* in all other cases the combination is not valid and default should be used */
146         return defaultInitial;
147 }
148
149
150 const char * fmi2_capability_to_string(fmi2_capabilities_enu_t id) {
151 #define FMI2_ME_CAPABILITIES_ENU_TO_STR(c) case fmi2_me_ ## c: return "me_"#c;
152 #define FMI2_CS_CAPABILITIES_ENU_TO_STR(c) case fmi2_cs_ ## c: return "cs_"#c;
153         switch (id) {
154         FMI2_ME_CAPABILITIES(FMI2_ME_CAPABILITIES_ENU_TO_STR)
155         FMI2_CS_CAPABILITIES(FMI2_CS_CAPABILITIES_ENU_TO_STR)
156         default: break;
157         }
158         return "Unknown";
159 }
160
161 const char * fmi2_SI_base_unit_to_string(fmi2_SI_base_units_enu_t id) {
162 #define FMI2_SI_BASE_UNIT_ENU_TO_STR(c) case fmi2_SI_base_unit_ ## c: return #c;
163         switch(id) {
164                 FMI2_SI_BASE_UNITS(FMI2_SI_BASE_UNIT_ENU_TO_STR)
165         default: break;
166         }
167         return "unknown";
168 }
169
170 /** \brief Convert a list of SI base unit exponents (corresponding to the IDs from  fmi2_SI_base_units_enu_t)
171         to a string of the form kg*m^2/s^2.
172
173         \param exp An array of SI base units exponents.
174         \param bufSize Size of the buffer to store the string. 
175         \param buf Buffer to store the string
176         \return Required size of the buffer to store the string including the terminating zero.
177                 This most likely be under [8*fmi2_SI_base_units_Num]. If the return value is larger or equal 
178                 than bufSize than the string could not be fitted in the buffer. 
179 */
180 size_t fmi2_SI_base_unit_exp_to_string(const int exp[fmi2_SI_base_units_Num], size_t bufSize, char buf[]){
181         int i = 0;
182         int num_pos_exp = 0, num_neg_exp = 0; /* number of exponents */
183         size_t len = 0;
184         char tmp[fmi2_SI_base_units_Num * 20]; /* tmp is always enough size */
185         if(bufSize) buf[0] = 0; /* just to prevent errors */
186
187         /* count the exponents */
188         for(i = 0; i < fmi2_SI_base_units_Num; i++) {
189                 if(exp[i] == 0) continue;
190                 if(exp[i] < 0) 
191                         num_neg_exp ++;
192                 else
193                         num_pos_exp ++;
194         }
195         if((num_neg_exp + num_pos_exp) == 0) { /* return "-" */ 
196                  if (bufSize < 2) return 2;
197                  buf[0] = '-';
198                  buf[1] = 0;
199                  return 2;
200         }
201         if(num_pos_exp == 0) {
202                 /* we start with "one over", i.e., 1 */
203                 tmp[0] = '1';
204                 len = 1;
205         }
206         else {
207                 len = 0;
208                 /* print positive exp */
209                 for(i = 0; i < fmi2_SI_base_units_Num; i++) {
210                         char* curp = tmp + len;
211                         int expi = exp[i];
212                         if(expi <= 0)  continue;
213                         if(len) {
214                                 *curp = '*';
215                                 curp++; len++;
216                         }
217
218                         strcpy(curp, fmi2_SI_base_unit_to_string((fmi2_SI_base_units_enu_t)i)) ;
219                         len += strlen(curp);
220                         curp = tmp + len;
221
222                         if(expi > 1) {
223                                 *curp = '^';
224                                 curp++; len++;
225
226                                 sprintf(curp, "%d", expi); /*safe */
227                                 len += strlen(curp);
228                         }
229                 }
230         }
231         /* print negative exp */
232         if(num_neg_exp > 0) {
233                 tmp[len++] = '/';
234                 if(num_neg_exp > 1)
235                         tmp[len++] = '(';
236                 num_neg_exp = 0;
237
238                 for(i = 0; i < fmi2_SI_base_units_Num; i++) {
239                         char* curp = tmp + len;
240                         int expi = exp[i];
241                         if(expi >= 0)  continue;
242                         expi = -expi;
243                         if(num_neg_exp > 0) {
244                                 *curp = '*';
245                                 curp++; len++;
246                         }
247                         num_neg_exp++;
248                         strcpy(curp, fmi2_SI_base_unit_to_string((fmi2_SI_base_units_enu_t)i)) ;
249                         len += strlen(curp);
250                         curp = tmp + len;
251
252                         if(expi > 1) {
253                                 *curp = '^';
254                                 curp++; len++;
255
256                                 sprintf(curp, "%d", expi); /*safe */
257                                 len += strlen(curp);
258                         }
259                 }
260                 if(num_neg_exp > 1)
261                         tmp[len++] = ')';
262         }
263         strncpy(buf, tmp, bufSize);
264     if(len < bufSize) buf[len] = 0;
265         return len + 1;
266 }