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 int test_simulate_me(fmi1_import_t* fmu)
\r
34 fmi1_status_t fmistatus;
\r
35 jm_status_enu_t jmstatus;
\r
36 fmi1_real_t tstart = 0.0;
\r
39 fmi1_real_t hdef = 0.1;
\r
40 fmi1_real_t tend = 2.0;
\r
42 size_t n_event_indicators;
\r
43 fmi1_real_t* states;
\r
44 fmi1_real_t states_end_results[] = {0.362000, -3.962000};
\r
45 fmi1_real_t* states_der;
\r
46 fmi1_real_t* event_indicators;
\r
47 fmi1_real_t* event_indicators_prev;
\r
48 fmi1_boolean_t callEventUpdate;
\r
49 fmi1_boolean_t toleranceControlled = fmi1_true;
\r
50 fmi1_real_t relativeTolerance = 0.001;
\r
51 fmi1_event_info_t eventInfo;
\r
52 fmi1_boolean_t intermediateResults = fmi1_false;
\r
55 printf("Version returned from FMU: %s\n", fmi1_import_get_version(fmu));
\r
56 printf("Platform type returned: %s\n", fmi1_import_get_model_types_platform(fmu));
\r
58 n_states = fmi1_import_get_number_of_continuous_states(fmu);
\r
59 n_event_indicators = fmi1_import_get_number_of_event_indicators(fmu);
\r
61 if (sizeof(states_end_results)/sizeof(fmi1_real_t) != n_states) {
\r
62 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
63 do_exit(CTEST_RETURN_FAIL);
\r
66 states = calloc(n_states, sizeof(double));
\r
67 states_der = calloc(n_states, sizeof(double));
\r
68 event_indicators = calloc(n_event_indicators, sizeof(double));
\r
69 event_indicators_prev = calloc(n_event_indicators, sizeof(double));
\r
71 jmstatus = fmi1_import_instantiate_model(fmu, "Test ME model instance");
\r
72 if (jmstatus == jm_status_error) {
\r
73 printf("fmi1_import_instantiate_model failed\n");
\r
74 do_exit(CTEST_RETURN_FAIL);
\r
77 fmistatus = fmi1_import_set_time(fmu, tstart);
\r
79 fmistatus = fmi1_import_initialize(fmu, toleranceControlled, relativeTolerance, &eventInfo);
\r
81 fmistatus = fmi1_import_get_continuous_states(fmu, states, n_states);
\r
82 fmistatus = fmi1_import_get_event_indicators(fmu, event_indicators_prev, n_event_indicators);
\r
84 fmistatus = fmi1_import_set_debug_logging(fmu, fmi1_false);
\r
85 printf("fmi1_import_set_debug_logging: %s\n", fmi1_status_to_string(fmistatus));
\r
86 fmi1_import_set_debug_logging(fmu, fmi1_true);
\r
90 callEventUpdate = fmi1_false;
\r
92 while (tcur < tend) {
\r
94 int zero_crossning_event = 0;
\r
96 fmistatus = fmi1_import_set_time(fmu, tcur);
\r
97 fmistatus = fmi1_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
\r
99 /* Check if an event inidcator has triggered */
\r
100 for (k = 0; k < n_event_indicators; k++) {
\r
101 if (event_indicators[k]*event_indicators_prev[k] < 0) {
\r
102 zero_crossning_event = 1;
\r
107 /* Handle any events */
\r
108 if (callEventUpdate || zero_crossning_event || (eventInfo.upcomingTimeEvent && tcur == eventInfo.nextEventTime)) {
\r
109 fmistatus = fmi1_import_eventUpdate(fmu, intermediateResults, &eventInfo);
\r
110 fmistatus = fmi1_import_get_continuous_states(fmu, states, n_states);
\r
111 fmistatus = fmi1_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
\r
112 fmistatus = fmi1_import_get_event_indicators(fmu, event_indicators_prev, n_event_indicators);
\r
115 /* Updated next time step */
\r
116 if (eventInfo.upcomingTimeEvent) {
\r
117 if (tcur + hdef < eventInfo.nextEventTime) {
\r
120 hcur = eventInfo.nextEventTime - tcur;
\r
126 if(tcur > tend - hcur/1e16) {
\r
128 hcur = (tend - tcur);
\r
131 /* Integrate a step */
\r
132 fmistatus = fmi1_import_get_derivatives(fmu, states_der, n_states);
\r
133 for (k = 0; k < n_states; k++) {
\r
134 states[k] = states[k] + hcur*states_der[k];
\r
135 if (k == 0) printf("Ball hight state[%u] = %f\n", (unsigned)k, states[k]);
\r
139 fmistatus = fmi1_import_set_continuous_states(fmu, states, n_states);
\r
140 /* Step is complete */
\r
141 fmistatus = fmi1_import_completed_integrator_step(fmu, &callEventUpdate);
\r
144 /* Validate result */
\r
145 for (k = 0; k < n_states; k++) {
\r
146 fmi1_real_t res = states[k] - states_end_results[k];
\r
147 res = res > 0 ? res: -res; /* Take abs */
\r
149 printf("Simulation results is wrong states[%u] %f != %f, |res| = %f\n", (unsigned)k, states[k], states_end_results[k], res);
\r
150 do_exit(CTEST_RETURN_FAIL);
\r
155 fmistatus = fmi1_import_terminate(fmu);
\r
157 fmi1_import_free_model_instance(fmu);
\r
161 free(event_indicators);
\r
162 free(event_indicators_prev);
\r
168 fmi1_import_t* fmu;
\r
169 fmi_import_context_t* context;
\r
170 jm_callbacks* callbacks;
\r
171 fmi1_callback_functions_t callBackFunctions;
\r
174 fmul_t load(int argc, char *argv[])
\r
176 fmi1_callback_functions_t callBackFunctions;
\r
177 const char* FMUPath;
\r
178 const char* tmpPath;
\r
179 jm_callbacks* callbacks;
\r
180 fmi_import_context_t* context;
\r
181 fmi_version_enu_t version;
\r
182 jm_status_enu_t status;
\r
183 static int isunzipped;
\r
185 fmi1_import_t* fmu;
\r
188 printf("Usage: %s <fmu_file> <temporary_dir>\n", argv[0]);
\r
189 do_exit(CTEST_RETURN_FAIL);
\r
196 callbacks = (jm_callbacks*)malloc(sizeof(jm_callbacks));
\r
197 callbacks->malloc = malloc;
\r
198 callbacks->calloc = calloc;
\r
199 callbacks->realloc = realloc;
\r
200 callbacks->free = free;
\r
201 callbacks->logger = jm_default_logger;
\r
202 callbacks->log_level = jm_log_level_debug;
\r
203 callbacks->context = 0;
\r
205 callBackFunctions.logger = fmi1_log_forwarding;
\r
206 callBackFunctions.allocateMemory = calloc;
\r
207 callBackFunctions.freeMemory = free;
\r
209 #ifdef FMILIB_GENERATE_BUILD_STAMP
\r
210 printf("Library build stamp:\n%s\n", fmilib_get_build_stamp());
\r
214 context = fmi_import_allocate_context(callbacks);
\r
216 if (isunzipped == 0) { /* Unzip the FMU only once. Overwriting the dll/so file may cause a segfault. */
\r
217 version = fmi_import_get_fmi_version(context, FMUPath, tmpPath);
\r
218 if(version != fmi_version_1_enu) {
\r
219 printf("Only version 1.0 is supported so far\n");
\r
220 do_exit(CTEST_RETURN_FAIL);
\r
225 fmu = fmi1_import_parse_xml(context, tmpPath);
\r
228 printf("Error parsing XML, exiting\n");
\r
229 do_exit(CTEST_RETURN_FAIL);
\r
232 status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 1);
\r
233 if (status == jm_status_error) {
\r
234 printf("Could not create the DLL loading mechanism(C-API test).\n");
\r
235 do_exit(CTEST_RETURN_FAIL);
\r
238 test_simulate_me(fmu);
\r
240 printf("Everything seems to be OK since you got this far=)!\n");
\r
243 fmus.callBackFunctions = callBackFunctions;
\r
244 fmus.callbacks = callbacks;
\r
245 fmus.context = context;
\r
251 void destroy(fmul_t* fmus) {
\r
252 fmi1_import_destroy_dllfmu(fmus->fmu);
\r
253 fmi1_import_free(fmus->fmu);
\r
254 fmi_import_free_context(fmus->context);
\r
255 free(fmus->callbacks);
\r
256 memset(fmus, 0, sizeof(fmul_t));
\r
259 /* Load and simulate 150 FMUs. Destroy and free all memory last. Usefull testing speciall for the registerGlobally functionality. */
\r
260 #define NUMBER_OF_TESTS 150
\r
261 int main(int argc, char *argv[])
\r
263 fmul_t fmul[NUMBER_OF_TESTS];
\r
266 for (k=0;k<NUMBER_OF_TESTS;k++) {
\r
267 fmul[k] = load(argc, argv);
\r
270 for (k=0;k<NUMBER_OF_TESTS;k++) {
\r
274 do_exit(CTEST_RETURN_SUCCESS);
\r