FMI Library: part of JModelica.org
fmi2_import_me_test.c
Go to the documentation of this file.
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 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stdarg.h>
19 
20 #include "config_test.h"
21 #include <fmilib.h>
22 
23 #define BUFFER 1000
24 
25 void do_exit(int code)
26 {
27  printf("Press 'Enter' to exit\n");
28  /* getchar(); */
29  exit(code);
30 }
31 
33 {
35  eventInfo->terminateSimulation = fmi2_false;
36  while (eventInfo->newDiscreteStatesNeeded && !eventInfo->terminateSimulation) {
37  fmi2_import_new_discrete_states(fmu, eventInfo);
38  }
39 }
40 
42 { /* Test that all variables where parsed */
44  unsigned int n_total;
45 
47  n_total = mc.num_constants
48  + mc.num_fixed
49  + mc.num_tunable
50  + mc.num_discrete
51  + mc.num_continuous
52  + mc.num_independent;
53 
54 
55  if (n_total != 12) {
56  do_exit(CTEST_RETURN_FAIL);
57  }
58 }
59 
61 {
62  fmi2_status_t fmistatus;
63  jm_status_enu_t jmstatus;
64  fmi2_real_t tstart = 0.0;
65  fmi2_real_t tcur;
66  fmi2_real_t hcur;
67  fmi2_real_t hdef = 0.1;
68  fmi2_real_t tend = 2.0;
69  size_t n_states;
70  size_t n_event_indicators;
71  fmi2_real_t* states;
72  fmi2_real_t states_end_results[] = {0.362000, -3.962000};
73  fmi2_real_t* states_der;
74  fmi2_real_t* event_indicators;
75  fmi2_real_t* event_indicators_prev;
76  fmi2_boolean_t callEventUpdate;
77  fmi2_boolean_t terminateSimulation = fmi2_false;
78  fmi2_boolean_t toleranceControlled = fmi2_true;
79  fmi2_real_t relativeTolerance = 0.001;
80  fmi2_event_info_t eventInfo;
81  size_t k;
82 
83  printf("Version returned from FMU: %s\n", fmi2_import_get_version(fmu));
84  printf("Platform type returned: %s\n", fmi2_import_get_types_platform(fmu));
85 
87  n_event_indicators = fmi2_import_get_number_of_event_indicators(fmu);
88 
89  if (sizeof(states_end_results)/sizeof(fmi2_real_t) != n_states) {
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));
91  do_exit(CTEST_RETURN_FAIL);
92  }
93 
94  states = calloc(n_states, sizeof(double));
95  states_der = calloc(n_states, sizeof(double));
96  event_indicators = calloc(n_event_indicators, sizeof(double));
97  event_indicators_prev = calloc(n_event_indicators, sizeof(double));
98 
99  jmstatus = fmi2_import_instantiate(fmu, "Test ME model instance",fmi2_model_exchange,0,0);
100  if (jmstatus == jm_status_error) {
101  printf("fmi2_import_instantiate failed\n");
102  do_exit(CTEST_RETURN_FAIL);
103  }
104 
105  fmistatus = fmi2_import_set_debug_logging(fmu, fmi2_false,0,0);
106  printf("fmi2_import_set_debug_logging: %s\n", fmi2_status_to_string(fmistatus));
108 
109  fmistatus = fmi2_import_setup_experiment(fmu, toleranceControlled,
110  relativeTolerance, tstart, fmi2_false, 0.0);
111 
112  fmistatus = fmi2_import_enter_initialization_mode(fmu);
113  fmistatus = fmi2_import_exit_initialization_mode(fmu);
114 
115  tcur = tstart;
116  hcur = hdef;
117  callEventUpdate = fmi2_false;
118 
120  eventInfo.terminateSimulation = fmi2_false;
123  eventInfo.nextEventTimeDefined = fmi2_false;
124  eventInfo.nextEventTime = -0.0;
125 
126  /* fmiExitInitializationMode leaves FMU in event mode */
127  do_event_iteration(fmu, &eventInfo);
129 
130  fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states);
131  fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
132 
133  while ((tcur < tend) && (!(eventInfo.terminateSimulation || terminateSimulation))) {
134  size_t k;
135  fmi2_real_t tlast;
136  int zero_crossing_event = 0;
137 
138  fmistatus = fmi2_import_set_time(fmu, tcur);
139 
140  { /* Swap event_indicators and event_indicators_prev so that we can get new indicators */
141  fmi2_real_t *temp = event_indicators;
142  event_indicators = event_indicators_prev;
143  event_indicators_prev = temp;
144  }
145  fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
146 
147  /* Check if an event indicator has triggered */
148  for (k = 0; k < n_event_indicators; k++) {
149  if ((event_indicators[k] > 0) != (event_indicators_prev[k] > 0)) {
150  zero_crossing_event = 1;
151  break;
152  }
153  }
154 
155  /* Handle any events */
156  if (callEventUpdate || zero_crossing_event ||
157  (eventInfo.nextEventTimeDefined && tcur == eventInfo.nextEventTime)) {
158  fmistatus = fmi2_import_enter_event_mode(fmu);
159  do_event_iteration(fmu, &eventInfo);
161 
162  fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states);
163  fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);
164  }
165 
166  /* Calculate next time step */
167  tlast = tcur;
168  tcur += hdef;
169  if (eventInfo.nextEventTimeDefined && (tcur >= eventInfo.nextEventTime)) {
170  tcur = eventInfo.nextEventTime;
171  }
172  hcur = tcur - tlast;
173  if(tcur > tend - hcur/1e16) {
174  tcur = tend;
175  hcur = tcur - tlast;
176  }
177 
178  /* Integrate a step */
179  fmistatus = fmi2_import_get_derivatives(fmu, states_der, n_states);
180  for (k = 0; k < n_states; k++) {
181  states[k] = states[k] + hcur*states_der[k];
182  if (k == 0) printf("Ball height state[%u] = %f\n", (unsigned)k, states[k]);
183  }
184 
185  /* Set states */
186  fmistatus = fmi2_import_set_continuous_states(fmu, states, n_states);
187  /* Step is complete */
188  fmistatus = fmi2_import_completed_integrator_step(fmu, fmi2_true, &callEventUpdate,
189  &terminateSimulation);
190  }
191 
192  /* Validate result */
193  for (k = 0; k < n_states; k++) {
194  fmi2_real_t res = states[k] - states_end_results[k];
195  res = res > 0 ? res: -res; /* Take abs */
196  if (res > 1e-10) {
197  printf("Simulation results is wrong states[%u] %f != %f, |res| = %f\n", (unsigned)k, states[k], states_end_results[k], res);
198  do_exit(CTEST_RETURN_FAIL);
199  }
200  }
201 
202 
203  fmistatus = fmi2_import_terminate(fmu);
204 
206 
207  free(states);
208  free(states_der);
209  free(event_indicators);
210  free(event_indicators_prev);
211 
212  return 0;
213 }
214 
215 int main(int argc, char *argv[])
216 {
217  fmi2_callback_functions_t callBackFunctions;
218  const char* FMUPath;
219  const char* tmpPath;
221  fmi_import_context_t* context;
222  fmi_version_enu_t version;
223  jm_status_enu_t status;
224 
225  fmi2_import_t* fmu;
226 
227  if(argc < 3) {
228  printf("Usage: %s <fmu_file> <temporary_dir>\n", argv[0]);
229  do_exit(CTEST_RETURN_FAIL);
230  }
231 
232  FMUPath = argv[1];
233  tmpPath = argv[2];
234 
235 
236  callbacks.malloc = malloc;
237  callbacks.calloc = calloc;
238  callbacks.realloc = realloc;
239  callbacks.free = free;
240  callbacks.logger = jm_default_logger;
241  callbacks.log_level = jm_log_level_debug;
242  callbacks.context = 0;
243 
244 #ifdef FMILIB_GENERATE_BUILD_STAMP
245  printf("Library build stamp:\n%s\n", fmilib_get_build_stamp());
246 #endif
247 
248 
249  context = fmi_import_allocate_context(&callbacks);
250 
251  version = fmi_import_get_fmi_version(context, FMUPath, tmpPath);
252 
253  if(version != fmi_version_2_0_enu) {
254  printf("Only version 2.0 is supported by this code\n");
255  do_exit(CTEST_RETURN_FAIL);
256  }
257 
258  fmu = fmi2_import_parse_xml(context, tmpPath,0);
259 
260  if(!fmu) {
261  printf("Error parsing XML, exiting\n");
262  do_exit(CTEST_RETURN_FAIL);
263  }
264 
266  printf("Only ME 2.0 is supported by this code\n");
267  do_exit(CTEST_RETURN_FAIL);
268  }
269 
270  callBackFunctions.logger = fmi2_log_forwarding;
271  callBackFunctions.allocateMemory = calloc;
272  callBackFunctions.freeMemory = free;
273  callBackFunctions.componentEnvironment = fmu;
274 
275  status = fmi2_import_create_dllfmu(fmu, fmi2_fmu_kind_me, &callBackFunctions);
276  if (status == jm_status_error) {
277  printf("Could not create the DLL loading mechanism(C-API test).\n");
278  do_exit(CTEST_RETURN_FAIL);
279  }
280 
282 
283  test_simulate_me(fmu);
284 
286 
287  fmi2_import_free(fmu);
288  fmi_import_free_context(context);
289 
290  printf("Everything seems to be OK since you got this far=)!\n");
291 
292  do_exit(CTEST_RETURN_SUCCESS);
293 
294  return 0;
295 }
296 
297 
FMILIB_EXPORT fmi2_status_t fmi2_import_get_derivatives(fmi2_import_t *fmu, fmi2_real_t derivatives[], size_t nx)
Wrapper for the FMI function fmiGetDerivatives(...)
FMILIB_EXPORT fmi2_status_t fmi2_import_enter_continuous_time_mode(fmi2_import_t *fmu)
Calls the FMI function fmiEnterContinuousTimeMode(...)
jm_calloc_f calloc
Allocate zero initialized memory.
Definition: jm_callbacks.h:77
unsigned int num_discrete
Number of discrete variables.
fmi2_boolean_t valuesOfContinuousStatesChanged
FMILIB_EXPORT fmi2_status_t fmi2_import_new_discrete_states(fmi2_import_t *fmu, fmi2_event_info_t *eventInfo)
Calls the FMI function fmiNewDiscreteStates(...)
FMILIB_EXPORT fmi2_status_t fmi2_import_enter_event_mode(fmi2_import_t *fmu)
Calls the FMI function fmiEnterEventMode(...)
FMILIB_EXPORT fmi2_status_t fmi2_import_set_time(fmi2_import_t *fmu, fmi2_real_t time)
Wrapper for the FMI function fmiSetTime(...)
FMILIB_EXPORT void fmi2_import_free_instance(fmi2_import_t *fmu)
Wrapper for the FMI function fmiFreeInstance(...)
int test_simulate_me(fmi2_import_t *fmu)
fmi_version_enu_t
Suported versions of FMI standard.
Definition: fmi_version.h:34
FMILIB_EXPORT fmi2_status_t fmi2_import_set_continuous_states(fmi2_import_t *fmu, const fmi2_real_t x[], size_t nx)
Wrapper for the FMI function fmiSetContinuousStates(...)
int test_parsed_all_varialbes(fmi2_import_t *fmu)
fmi2_callback_allocate_memory_ft allocateMemory
unsigned int num_continuous
Number of continuous variables.
FMILIB_EXPORT const char * fmi2_import_get_version(fmi2_import_t *fmu)
Wrapper for the FMI function fmiGetVersion()
FMILIB_EXPORT size_t fmi2_import_get_number_of_event_indicators(fmi2_import_t *fmu)
Get the number of event indicators.
FMILIB_EXPORT void fmi2_import_collect_model_counts(fmi2_import_t *fmu, fmi2_import_model_counts_t *counts)
Collect model information by counting the number of variables with specific properties and fillinf in...
FMILIB_EXPORT fmi2_import_t * fmi2_import_parse_xml(fmi_import_context_t *context, const char *dirPath, fmi2_xml_callbacks_t *xml_callbacks)
Create fmi2_import_t structure and parse the FMI 2.0 XML file found in the directory dirName...
fmi2_real_t nextEventTime
FMILIB_EXPORT fmi2_fmu_kind_enu_t fmi2_import_get_fmu_kind(fmi2_import_t *fmu)
Get the type of the FMU (model exchange or co-simulation)
fmi2_boolean_t terminateSimulation
jm_log_level_enu_t log_level
Logging level.
Definition: jm_callbacks.h:85
v callbacks
FMILIB_EXPORT fmi2_status_t fmi2_import_set_debug_logging(fmi2_import_t *fmu, fmi2_boolean_t loggingOn, size_t nCategories, fmi2_string_t categories[])
Wrapper for the FMI function fmiSetDebugLogging(...)
fmi1_capi_t * fmu
fmi2_boolean_t newDiscreteStatesNeeded
FMILIB_EXPORT void fmi2_import_destroy_dllfmu(fmi2_import_t *fmu)
Free a C-API struct. All memory allocated since the struct was created is freed.
FMILIB_EXPORT fmi2_status_t fmi2_import_get_event_indicators(fmi2_import_t *fmu, fmi2_real_t eventIndicators[], size_t ni)
Wrapper for the FMI function fmiGetEventIndicators(...)
fmi2_status_t
FMILIB_EXPORT fmi2_status_t fmi2_import_exit_initialization_mode(fmi2_import_t *fmu)
Calls the FMI function fmiExitInitializationMode(...)
Collection of counters providing model information.
unsigned int num_fixed
Number of fixed.
fmi2_callback_logger_ft logger
Verbose messages.
Definition: jm_types.h:58
Include file to be used in client applications of the FMI Library.
jm_malloc_f malloc
Allocate non-initialized memory.
Definition: jm_callbacks.h:75
fmi2_callback_free_memory_ft freeMemory
jm_voidp context
Arbitrary context pointer passed to the logger function.
Definition: jm_callbacks.h:87
fmi2_component_environment_t componentEnvironment
FMILIB_EXPORT fmi2_status_t fmi2_import_setup_experiment(fmi2_import_t *fmu, fmi2_boolean_t toleranceDefined, fmi2_real_t tolerance, fmi2_real_t startTime, fmi2_boolean_t stopTimeDefined, fmi2_real_t stopTime)
Calls the FMI function fmiSetupExperiment(...)
FMILIB_EXPORT jm_status_enu_t fmi2_import_create_dllfmu(fmi2_import_t *fmu, fmi2_fmu_kind_enu_t fmuKind, const fmi2_callback_functions_t *callBackFunctions)
Create a C-API struct. The C-API struct is a placeholder for the FMI DLL functions.
FMILIB_EXPORT void jm_default_logger(jm_callbacks *c, jm_string module, jm_log_level_enu_t log_level, jm_string message)
The default logger implementation prints messages to stderr.
The callbacks struct is sent to all the modules in the library.
Definition: jm_callbacks.h:73
FMILIB_EXPORT const char * fmi2_status_to_string(fmi2_status_t status)
void do_event_iteration(fmi2_import_t *fmu, fmi2_event_info_t *eventInfo)
fmi2_boolean_t nominalsOfContinuousStatesChanged
FMILIB_EXPORT fmi2_status_t fmi2_import_enter_initialization_mode(fmi2_import_t *fmu)
Calls the FMI function fmiEnterInitializationMode(...)
struct fmi_xml_context_t fmi_import_context_t
FMI version independent library context. Opaque struct returned from fmi_import_allocate_context() ...
FMILIB_EXPORT void fmi2_import_free(fmi2_import_t *fmu)
Release the memory allocated.
FMILIB_EXPORT fmi_import_context_t * fmi_import_allocate_context(jm_callbacks *callbacks)
Create fmi_import_context_t structure.
FMILIB_EXPORT const char * fmi2_import_get_types_platform(fmi2_import_t *fmu)
Wrapper for the FMI function fmiGetTypesPlatform(...)
unsigned int num_independent
Number of independent variables.
fmi2_boolean_t nextEventTimeDefined
FMILIB_EXPORT size_t fmi2_import_get_number_of_continuous_states(fmi2_import_t *fmu)
Get the number of continuous states.
FMILIB_EXPORT fmi2_status_t fmi2_import_completed_integrator_step(fmi2_import_t *fmu, fmi2_boolean_t noSetFMUStatePriorToCurrentPoint, fmi2_boolean_t *enterEventMode, fmi2_boolean_t *terminateSimulation)
Wrapper for the FMI function fmiCompletedIntegratorStep(...)
FMILIB_EXPORT fmi2_status_t fmi2_import_terminate(fmi2_import_t *fmu)
Wrapper for the FMI function fmiTerminate(...)
FMILIB_EXPORT fmi2_status_t fmi2_import_get_continuous_states(fmi2_import_t *fmu, fmi2_real_t states[], size_t nx)
Wrapper for the FMI function fmiGetContinuousStates(...)
FMILIB_EXPORT fmi_version_enu_t fmi_import_get_fmi_version(fmi_import_context_t *c, const char *fileName, const char *dirName)
Unzip an FMU specified by the fileName into directory dirName and parse XML to get FMI standard versi...
FMILIB_EXPORT void fmi_import_free_context(fmi_import_context_t *c)
Free memory allocated for the library context.
jm_realloc_f realloc
Re-allocate memory.
Definition: jm_callbacks.h:79
jm_status_enu_t
Return status codes.
Definition: jm_types.h:44
FMILIB_EXPORT jm_status_enu_t fmi2_import_instantiate(fmi2_import_t *fmu, fmi2_string_t instanceName, fmi2_type_t fmuType, fmi2_string_t fmuResourceLocation, fmi2_boolean_t visible)
Wrapper for the FMI function fmiInstantiate(...)
int main(int argc, char *argv[])
jm_free_f free
Free-allocated memory.
Definition: jm_callbacks.h:81
void do_exit(int code)
jm_logger_f logger
Logging callback.
Definition: jm_callbacks.h:83
FMILIB_EXPORT void fmi2_log_forwarding(fmi2_component_t c, fmi2_string_t instanceName, fmi2_status_t status, fmi2_string_t category, fmi2_string_t message,...)
An implementation of FMI 2.0 logger that forwards the messages to logger function inside jm_callbacks...
unsigned int num_tunable
Number of tunable.
unsigned int num_constants
Number of constants.
struct fmi2_import_t fmi2_import_t
FMU version 2.0 object.