2 Copyright (C) 2012 Modelon AB
\r
4 This program is free software: you can redistribute it and/or modify
\r
5 it under the terms of the BSD style license.
\r
7 This program is distributed in the hope that it will be useful,
\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
10 FMILIB_License.txt file for more details.
\r
12 You should have received a copy of the FMILIB_License.txt file
\r
13 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
\r
20 #include "config_test.h"
\r
25 void do_exit(int code)
\r
27 printf("Press 'Enter' to exit\n");
\r
32 void do_event_iteration(fmi2_import_t *fmu, fmi2_event_info_t *eventInfo)
\r
34 eventInfo->newDiscreteStatesNeeded = fmi2_true;
\r
35 eventInfo->terminateSimulation = fmi2_false;
\r
36 while (eventInfo->newDiscreteStatesNeeded && !eventInfo->terminateSimulation) {
\r
37 fmi2_import_new_discrete_states(fmu, eventInfo);
\r
41 int test_parsed_all_varialbes(fmi2_import_t* fmu)
\r
42 { /* Test that all variables where parsed */
\r
43 fmi2_import_model_counts_t mc;
\r
44 unsigned int n_total;
\r
46 fmi2_import_collect_model_counts(fmu, &mc);
\r
47 n_total = mc.num_constants
\r
52 + mc.num_independent;
\r
55 if (n_total != 12) {
\r
56 do_exit(CTEST_RETURN_FAIL);
\r
60 int test_simulate_me(fmi2_import_t* fmu)
\r
62 fmi2_status_t fmistatus;
\r
63 jm_status_enu_t jmstatus;
\r
64 fmi2_real_t tstart = 0.0;
\r
67 fmi2_real_t hdef = 0.1;
\r
68 fmi2_real_t tend = 2.0;
\r
70 size_t n_event_indicators;
\r
71 fmi2_real_t* states;
\r
72 fmi2_real_t states_end_results[] = {0.362000, -3.962000};
\r
73 fmi2_real_t* states_der;
\r
74 fmi2_real_t* event_indicators;
\r
75 fmi2_real_t* event_indicators_prev;
\r
76 fmi2_boolean_t callEventUpdate;
\r
77 fmi2_boolean_t terminateSimulation = fmi2_false;
\r
78 fmi2_boolean_t toleranceControlled = fmi2_true;
\r
79 fmi2_real_t relativeTolerance = 0.001;
\r
80 fmi2_event_info_t eventInfo;
\r
83 printf("Version returned from FMU: %s\n", fmi2_import_get_version(fmu));
\r
84 printf("Platform type returned: %s\n", fmi2_import_get_types_platform(fmu));
\r
86 n_states = fmi2_import_get_number_of_continuous_states(fmu);
\r
87 n_event_indicators = fmi2_import_get_number_of_event_indicators(fmu);
\r
89 if (sizeof(states_end_results)/sizeof(fmi2_real_t) != n_states) {
\r
90 printf("Number of states and results have different length n_states = %u n_results = %u\n", (unsigned)n_states, (unsigned)sizeof(states_end_results));
\r
91 do_exit(CTEST_RETURN_FAIL);
\r
94 states = calloc(n_states, sizeof(double));
\r
95 states_der = calloc(n_states, sizeof(double));
\r
96 event_indicators = calloc(n_event_indicators, sizeof(double));
\r
97 event_indicators_prev = calloc(n_event_indicators, sizeof(double));
\r
99 jmstatus = fmi2_import_instantiate(fmu, "Test ME model instance",fmi2_model_exchange,0,0);
\r
100 if (jmstatus == jm_status_error) {
\r
101 printf("fmi2_import_instantiate failed\n");
\r
102 do_exit(CTEST_RETURN_FAIL);
\r
105 fmistatus = fmi2_import_set_debug_logging(fmu, fmi2_false,0,0);
\r
106 printf("fmi2_import_set_debug_logging: %s\n", fmi2_status_to_string(fmistatus));
\r
107 fmi2_import_set_debug_logging(fmu, fmi2_true, 0, 0);
\r
109 fmistatus = fmi2_import_setup_experiment(fmu, toleranceControlled,
\r
110 relativeTolerance, tstart, fmi2_false, 0.0);
\r
112 fmistatus = fmi2_import_enter_initialization_mode(fmu);
\r
113 fmistatus = fmi2_import_exit_initialization_mode(fmu);
\r
117 callEventUpdate = fmi2_false;
\r
119 eventInfo.newDiscreteStatesNeeded = fmi2_false;
\r
120 eventInfo.terminateSimulation = fmi2_false;
\r
121 eventInfo.nominalsOfContinuousStatesChanged = fmi2_false;
\r
122 eventInfo.valuesOfContinuousStatesChanged = fmi2_true;
\r
123 eventInfo.nextEventTimeDefined = fmi2_false;
\r
124 eventInfo.nextEventTime = -0.0;
\r
126 /* fmiExitInitializationMode leaves FMU in event mode */
\r
127 do_event_iteration(fmu, &eventInfo);
\r
128 fmi2_import_enter_continuous_time_mode(fmu);
\r
130 fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states);
\r
131 fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
\r
133 while ((tcur < tend) && (!(eventInfo.terminateSimulation || terminateSimulation))) {
\r
136 int zero_crossing_event = 0;
\r
138 fmistatus = fmi2_import_set_time(fmu, tcur);
\r
140 { /* Swap event_indicators and event_indicators_prev so that we can get new indicators */
\r
141 fmi2_real_t *temp = event_indicators;
\r
142 event_indicators = event_indicators_prev;
\r
143 event_indicators_prev = temp;
\r
145 fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
\r
147 /* Check if an event indicator has triggered */
\r
148 for (k = 0; k < n_event_indicators; k++) {
\r
149 if ((event_indicators[k] > 0) != (event_indicators_prev[k] > 0)) {
\r
150 zero_crossing_event = 1;
\r
155 /* Handle any events */
\r
156 if (callEventUpdate || zero_crossing_event ||
\r
157 (eventInfo.nextEventTimeDefined && tcur == eventInfo.nextEventTime)) {
\r
158 fmistatus = fmi2_import_enter_event_mode(fmu);
\r
159 do_event_iteration(fmu, &eventInfo);
\r
160 fmistatus = fmi2_import_enter_continuous_time_mode(fmu);
\r
162 fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states);
\r
163 fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
\r
166 /* Calculate next time step */
\r
169 if (eventInfo.nextEventTimeDefined && (tcur >= eventInfo.nextEventTime)) {
\r
170 tcur = eventInfo.nextEventTime;
\r
172 hcur = tcur - tlast;
\r
173 if(tcur > tend - hcur/1e16) {
\r
175 hcur = tcur - tlast;
\r
178 /* Integrate a step */
\r
179 fmistatus = fmi2_import_get_derivatives(fmu, states_der, n_states);
\r
180 for (k = 0; k < n_states; k++) {
\r
181 states[k] = states[k] + hcur*states_der[k];
\r
182 if (k == 0) printf("Ball height state[%u] = %f\n", (unsigned)k, states[k]);
\r
186 fmistatus = fmi2_import_set_continuous_states(fmu, states, n_states);
\r
187 /* Step is complete */
\r
188 fmistatus = fmi2_import_completed_integrator_step(fmu, fmi2_true, &callEventUpdate,
\r
189 &terminateSimulation);
\r
192 /* Validate result */
\r
193 for (k = 0; k < n_states; k++) {
\r
194 fmi2_real_t res = states[k] - states_end_results[k];
\r
195 res = res > 0 ? res: -res; /* Take abs */
\r
197 printf("Simulation results is wrong states[%u] %f != %f, |res| = %f\n", (unsigned)k, states[k], states_end_results[k], res);
\r
198 do_exit(CTEST_RETURN_FAIL);
\r
203 fmistatus = fmi2_import_terminate(fmu);
\r
205 fmi2_import_free_instance(fmu);
\r
209 free(event_indicators);
\r
210 free(event_indicators_prev);
\r
215 int main(int argc, char *argv[])
\r
217 fmi2_callback_functions_t callBackFunctions;
\r
218 const char* FMUPath;
\r
219 const char* tmpPath;
\r
220 jm_callbacks callbacks;
\r
221 fmi_import_context_t* context;
\r
222 fmi_version_enu_t version;
\r
223 jm_status_enu_t status;
\r
225 fmi2_import_t* fmu;
\r
228 printf("Usage: %s <fmu_file> <temporary_dir>\n", argv[0]);
\r
229 do_exit(CTEST_RETURN_FAIL);
\r
236 callbacks.malloc = malloc;
\r
237 callbacks.calloc = calloc;
\r
238 callbacks.realloc = realloc;
\r
239 callbacks.free = free;
\r
240 callbacks.logger = jm_default_logger;
\r
241 callbacks.log_level = jm_log_level_debug;
\r
242 callbacks.context = 0;
\r
244 #ifdef FMILIB_GENERATE_BUILD_STAMP
\r
245 printf("Library build stamp:\n%s\n", fmilib_get_build_stamp());
\r
249 context = fmi_import_allocate_context(&callbacks);
\r
251 version = fmi_import_get_fmi_version(context, FMUPath, tmpPath);
\r
253 if(version != fmi_version_2_0_enu) {
\r
254 printf("Only version 2.0 is supported by this code\n");
\r
255 do_exit(CTEST_RETURN_FAIL);
\r
258 fmu = fmi2_import_parse_xml(context, tmpPath,0);
\r
261 printf("Error parsing XML, exiting\n");
\r
262 do_exit(CTEST_RETURN_FAIL);
\r
265 if(fmi2_import_get_fmu_kind(fmu) == fmi2_fmu_kind_cs) {
\r
266 printf("Only ME 2.0 is supported by this code\n");
\r
267 do_exit(CTEST_RETURN_FAIL);
\r
270 callBackFunctions.logger = fmi2_log_forwarding;
\r
271 callBackFunctions.allocateMemory = calloc;
\r
272 callBackFunctions.freeMemory = free;
\r
273 callBackFunctions.componentEnvironment = fmu;
\r
275 status = fmi2_import_create_dllfmu(fmu, fmi2_fmu_kind_me, &callBackFunctions);
\r
276 if (status == jm_status_error) {
\r
277 printf("Could not create the DLL loading mechanism(C-API test).\n");
\r
278 do_exit(CTEST_RETURN_FAIL);
\r
281 test_parsed_all_varialbes(fmu);
\r
283 test_simulate_me(fmu);
\r
285 fmi2_import_destroy_dllfmu(fmu);
\r
287 fmi2_import_free(fmu);
\r
288 fmi_import_free_context(context);
\r
290 printf("Everything seems to be OK since you got this far=)!\n");
\r
292 do_exit(CTEST_RETURN_SUCCESS);
\r