]> gerrit.simantics Code Review - simantics/fmil.git/blobdiff - org.simantics.fmil.core/native/FMILibrary/Test/FMI2/fmi2_import_me_test.c
Add FMILibrary-2.0.3 to org.simantics.fmil.core\native.
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / Test / FMI2 / fmi2_import_me_test.c
diff --git a/org.simantics.fmil.core/native/FMILibrary/Test/FMI2/fmi2_import_me_test.c b/org.simantics.fmil.core/native/FMILibrary/Test/FMI2/fmi2_import_me_test.c
new file mode 100644 (file)
index 0000000..488ca7c
--- /dev/null
@@ -0,0 +1,297 @@
+/*\r
+    Copyright (C) 2012 Modelon AB\r
+\r
+    This program is free software: you can redistribute it and/or modify\r
+    it under the terms of the BSD style license.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    FMILIB_License.txt file for more details.\r
+\r
+    You should have received a copy of the FMILIB_License.txt file\r
+    along with this program. If not, contact Modelon AB <http://www.modelon.com>.\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+\r
+#include "config_test.h"\r
+#include <fmilib.h>\r
+\r
+#define BUFFER 1000\r
+\r
+void do_exit(int code)\r
+{\r
+       printf("Press 'Enter' to exit\n");\r
+       /* getchar(); */\r
+       exit(code);\r
+}\r
+\r
+void do_event_iteration(fmi2_import_t *fmu, fmi2_event_info_t *eventInfo)\r
+{\r
+    eventInfo->newDiscreteStatesNeeded = fmi2_true;\r
+    eventInfo->terminateSimulation     = fmi2_false;\r
+    while (eventInfo->newDiscreteStatesNeeded && !eventInfo->terminateSimulation) {\r
+        fmi2_import_new_discrete_states(fmu, eventInfo);\r
+    }\r
+}\r
+\r
+int test_parsed_all_varialbes(fmi2_import_t* fmu)\r
+{ /* Test that all variables where parsed */\r
+    fmi2_import_model_counts_t  mc;\r
+    unsigned int                n_total;\r
+    \r
+    fmi2_import_collect_model_counts(fmu, &mc);\r
+    n_total = mc.num_constants\r
+            + mc.num_fixed\r
+            + mc.num_tunable\r
+            + mc.num_discrete\r
+            + mc.num_continuous\r
+            + mc.num_independent;\r
+    \r
+    \r
+    if (n_total != 12) {\r
+        do_exit(CTEST_RETURN_FAIL);\r
+    }\r
+}\r
+          \r
+int test_simulate_me(fmi2_import_t* fmu)\r
+{      \r
+       fmi2_status_t fmistatus;\r
+       jm_status_enu_t jmstatus;\r
+       fmi2_real_t tstart = 0.0;\r
+       fmi2_real_t tcur;\r
+       fmi2_real_t hcur;\r
+       fmi2_real_t hdef = 0.1;\r
+       fmi2_real_t tend = 2.0;\r
+       size_t n_states;\r
+       size_t n_event_indicators;\r
+       fmi2_real_t* states;\r
+       fmi2_real_t states_end_results[] = {0.362000, -3.962000};\r
+       fmi2_real_t* states_der;\r
+       fmi2_real_t* event_indicators;\r
+       fmi2_real_t* event_indicators_prev;\r
+       fmi2_boolean_t callEventUpdate;\r
+       fmi2_boolean_t terminateSimulation = fmi2_false;\r
+       fmi2_boolean_t toleranceControlled = fmi2_true;\r
+       fmi2_real_t relativeTolerance = 0.001;\r
+       fmi2_event_info_t eventInfo;\r
+       size_t k;\r
+\r
+       printf("Version returned from FMU:   %s\n", fmi2_import_get_version(fmu));\r
+       printf("Platform type returned:      %s\n", fmi2_import_get_types_platform(fmu));\r
+\r
+       n_states = fmi2_import_get_number_of_continuous_states(fmu);\r
+       n_event_indicators = fmi2_import_get_number_of_event_indicators(fmu);\r
+\r
+       if (sizeof(states_end_results)/sizeof(fmi2_real_t) != n_states) {\r
+               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
+               do_exit(CTEST_RETURN_FAIL);\r
+       }\r
+\r
+       states = calloc(n_states, sizeof(double));\r
+       states_der = calloc(n_states, sizeof(double));\r
+       event_indicators = calloc(n_event_indicators, sizeof(double));\r
+       event_indicators_prev = calloc(n_event_indicators, sizeof(double));\r
+\r
+       jmstatus = fmi2_import_instantiate(fmu, "Test ME model instance",fmi2_model_exchange,0,0);\r
+       if (jmstatus == jm_status_error) {\r
+               printf("fmi2_import_instantiate failed\n");\r
+               do_exit(CTEST_RETURN_FAIL);\r
+       }\r
+\r
+       fmistatus = fmi2_import_set_debug_logging(fmu, fmi2_false,0,0);\r
+       printf("fmi2_import_set_debug_logging:  %s\n", fmi2_status_to_string(fmistatus));       \r
+       fmi2_import_set_debug_logging(fmu, fmi2_true, 0, 0);\r
+\r
+    fmistatus = fmi2_import_setup_experiment(fmu, toleranceControlled,\r
+        relativeTolerance, tstart, fmi2_false, 0.0);\r
+\r
+    fmistatus = fmi2_import_enter_initialization_mode(fmu);\r
+    fmistatus = fmi2_import_exit_initialization_mode(fmu);\r
+\r
+       tcur = tstart;\r
+       hcur = hdef;\r
+       callEventUpdate = fmi2_false;\r
+\r
+       eventInfo.newDiscreteStatesNeeded           = fmi2_false;\r
+       eventInfo.terminateSimulation               = fmi2_false;\r
+       eventInfo.nominalsOfContinuousStatesChanged = fmi2_false;\r
+       eventInfo.valuesOfContinuousStatesChanged   = fmi2_true;\r
+       eventInfo.nextEventTimeDefined              = fmi2_false;\r
+       eventInfo.nextEventTime                     = -0.0;\r
+\r
+    /* fmiExitInitializationMode leaves FMU in event mode */\r
+    do_event_iteration(fmu, &eventInfo);\r
+    fmi2_import_enter_continuous_time_mode(fmu);\r
+\r
+       fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states);\r
+       fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);\r
+\r
+       while ((tcur < tend) && (!(eventInfo.terminateSimulation || terminateSimulation))) {\r
+               size_t k;\r
+        fmi2_real_t tlast;\r
+               int zero_crossing_event = 0;\r
+\r
+               fmistatus = fmi2_import_set_time(fmu, tcur);\r
+\r
+        { /* Swap event_indicators and event_indicators_prev so that we can get new indicators */\r
+            fmi2_real_t *temp = event_indicators;\r
+            event_indicators = event_indicators_prev;\r
+            event_indicators_prev = temp;\r
+        }\r
+               fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);\r
+\r
+               /* Check if an event indicator has triggered */\r
+               for (k = 0; k < n_event_indicators; k++) {\r
+                       if ((event_indicators[k] > 0) != (event_indicators_prev[k] > 0)) {\r
+                               zero_crossing_event = 1;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               /* Handle any events */\r
+               if (callEventUpdate || zero_crossing_event ||\r
+                 (eventInfo.nextEventTimeDefined && tcur == eventInfo.nextEventTime)) {\r
+            fmistatus = fmi2_import_enter_event_mode(fmu);\r
+            do_event_iteration(fmu, &eventInfo);\r
+            fmistatus = fmi2_import_enter_continuous_time_mode(fmu);\r
+\r
+                       fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states);\r
+                       fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators);\r
+               }\r
+\r
+               /* Calculate next time step */\r
+        tlast = tcur;\r
+        tcur += hdef;\r
+               if (eventInfo.nextEventTimeDefined && (tcur >= eventInfo.nextEventTime)) {\r
+            tcur = eventInfo.nextEventTime;\r
+               }\r
+        hcur = tcur - tlast;\r
+               if(tcur > tend - hcur/1e16) {\r
+                       tcur = tend;                            \r
+                       hcur = tcur - tlast;\r
+               }\r
+\r
+               /* Integrate a step */\r
+               fmistatus = fmi2_import_get_derivatives(fmu, states_der, n_states);\r
+               for (k = 0; k < n_states; k++) {\r
+                       states[k] = states[k] + hcur*states_der[k];     \r
+                       if (k == 0) printf("Ball height state[%u] = %f\n", (unsigned)k, states[k]);\r
+               }\r
+\r
+               /* Set states */\r
+               fmistatus = fmi2_import_set_continuous_states(fmu, states, n_states);\r
+               /* Step is complete */\r
+               fmistatus = fmi2_import_completed_integrator_step(fmu, fmi2_true, &callEventUpdate,\r
+                                                          &terminateSimulation);\r
+       }       \r
+\r
+       /* Validate result */\r
+       for (k = 0; k < n_states; k++) {\r
+               fmi2_real_t res = states[k] - states_end_results[k];\r
+               res = res > 0 ? res: -res; /* Take abs */\r
+               if (res > 1e-10) {\r
+                       printf("Simulation results is wrong  states[%u] %f != %f, |res| = %f\n", (unsigned)k, states[k], states_end_results[k], res);\r
+                       do_exit(CTEST_RETURN_FAIL);\r
+               }\r
+       }\r
+       \r
+\r
+       fmistatus = fmi2_import_terminate(fmu);\r
+\r
+       fmi2_import_free_instance(fmu);\r
+\r
+       free(states);\r
+       free(states_der);\r
+       free(event_indicators);\r
+       free(event_indicators_prev);\r
+\r
+       return 0;\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+       fmi2_callback_functions_t callBackFunctions;\r
+       const char* FMUPath;\r
+       const char* tmpPath;\r
+       jm_callbacks callbacks;\r
+       fmi_import_context_t* context;\r
+       fmi_version_enu_t version;\r
+       jm_status_enu_t status;\r
+\r
+       fmi2_import_t* fmu;     \r
+\r
+       if(argc < 3) {\r
+               printf("Usage: %s <fmu_file> <temporary_dir>\n", argv[0]);\r
+               do_exit(CTEST_RETURN_FAIL);\r
+       }\r
+\r
+       FMUPath = argv[1];\r
+       tmpPath = argv[2];\r
+\r
+\r
+       callbacks.malloc = malloc;\r
+    callbacks.calloc = calloc;\r
+    callbacks.realloc = realloc;\r
+    callbacks.free = free;\r
+    callbacks.logger = jm_default_logger;\r
+       callbacks.log_level = jm_log_level_debug;\r
+    callbacks.context = 0;\r
+\r
+#ifdef FMILIB_GENERATE_BUILD_STAMP\r
+       printf("Library build stamp:\n%s\n", fmilib_get_build_stamp());\r
+#endif\r
+\r
+\r
+       context = fmi_import_allocate_context(&callbacks);\r
+\r
+       version = fmi_import_get_fmi_version(context, FMUPath, tmpPath);\r
+\r
+       if(version != fmi_version_2_0_enu) {\r
+               printf("Only version 2.0 is supported by this code\n");\r
+               do_exit(CTEST_RETURN_FAIL);\r
+       }\r
+\r
+       fmu = fmi2_import_parse_xml(context, tmpPath,0);\r
+\r
+       if(!fmu) {\r
+               printf("Error parsing XML, exiting\n");\r
+               do_exit(CTEST_RETURN_FAIL);\r
+       }       \r
+\r
+       if(fmi2_import_get_fmu_kind(fmu) == fmi2_fmu_kind_cs) {\r
+               printf("Only ME 2.0 is supported by this code\n");\r
+               do_exit(CTEST_RETURN_FAIL);\r
+       }\r
+\r
+       callBackFunctions.logger = fmi2_log_forwarding;\r
+       callBackFunctions.allocateMemory = calloc;\r
+       callBackFunctions.freeMemory = free;\r
+       callBackFunctions.componentEnvironment = fmu;\r
+\r
+       status = fmi2_import_create_dllfmu(fmu, fmi2_fmu_kind_me, &callBackFunctions);\r
+       if (status == jm_status_error) {\r
+               printf("Could not create the DLL loading mechanism(C-API test).\n");\r
+               do_exit(CTEST_RETURN_FAIL);\r
+       }\r
+    \r
+    test_parsed_all_varialbes(fmu);\r
+    \r
+       test_simulate_me(fmu);\r
+\r
+       fmi2_import_destroy_dllfmu(fmu);\r
+\r
+       fmi2_import_free(fmu);\r
+       fmi_import_free_context(context);\r
+       \r
+       printf("Everything seems to be OK since you got this far=)!\n");\r
+\r
+       do_exit(CTEST_RETURN_SUCCESS);\r
+\r
+       return 0;\r
+}\r
+\r
+\r