int test_simulate_me(fmi2_import_t* fmu) { fmi2_status_t fmistatus; jm_status_enu_t jmstatus; fmi2_real_t tstart = 0.0; fmi2_real_t tcur; fmi2_real_t hcur; fmi2_real_t hdef = 0.1; fmi2_real_t tend = 2.0; size_t n_states; size_t n_event_indicators; fmi2_real_t* states; fmi2_real_t states_end_results[] = {0.362000, -3.962000}; fmi2_real_t* states_der; fmi2_real_t* event_indicators; fmi2_real_t* event_indicators_prev; fmi2_boolean_t callEventUpdate; fmi2_boolean_t terminateSimulation = fmi2_false; fmi2_boolean_t toleranceControlled = fmi2_true; fmi2_real_t relativeTolerance = 0.001; fmi2_event_info_t eventInfo; size_t k; printf("Version returned from FMU: %s\n", fmi2_import_get_version(fmu)); printf("Platform type returned: %s\n", fmi2_import_get_types_platform(fmu)); n_states = fmi2_import_get_number_of_continuous_states(fmu); n_event_indicators = fmi2_import_get_number_of_event_indicators(fmu); if (sizeof(states_end_results)/sizeof(fmi2_real_t) != n_states) { printf("Number of states and results have different length n_states = %u n_results = %u\n", (unsigned)n_states, (unsigned)sizeof(states_end_results)); do_exit(CTEST_RETURN_FAIL); } states = calloc(n_states, sizeof(double)); states_der = calloc(n_states, sizeof(double)); event_indicators = calloc(n_event_indicators, sizeof(double)); event_indicators_prev = calloc(n_event_indicators, sizeof(double)); jmstatus = fmi2_import_instantiate(fmu, "Test ME model instance",fmi2_model_exchange,0,0); if (jmstatus == jm_status_error) { printf("fmi2_import_instantiate failed\n"); do_exit(CTEST_RETURN_FAIL); } fmistatus = fmi2_import_set_debug_logging(fmu, fmi2_false,0,0); printf("fmi2_import_set_debug_logging: %s\n", fmi2_status_to_string(fmistatus)); fmi2_import_set_debug_logging(fmu, fmi2_true, 0, 0); fmistatus = fmi2_import_setup_experiment(fmu, toleranceControlled, relativeTolerance, tstart, fmi2_false, 0.0); fmistatus = fmi2_import_enter_initialization_mode(fmu); fmistatus = fmi2_import_exit_initialization_mode(fmu); tcur = tstart; hcur = hdef; callEventUpdate = fmi2_false; eventInfo.newDiscreteStatesNeeded = fmi2_false; eventInfo.terminateSimulation = fmi2_false; eventInfo.nominalsOfContinuousStatesChanged = fmi2_false; eventInfo.valuesOfContinuousStatesChanged = fmi2_true; eventInfo.nextEventTimeDefined = fmi2_false; eventInfo.nextEventTime = -0.0; /* fmiExitInitializationMode leaves FMU in event mode */ do_event_iteration(fmu, &eventInfo); fmi2_import_enter_continuous_time_mode(fmu); fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states); fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators); while ((tcur < tend) && (!(eventInfo.terminateSimulation || terminateSimulation))) { size_t k; fmi2_real_t tlast; int zero_crossing_event = 0; fmistatus = fmi2_import_set_time(fmu, tcur); { /* Swap event_indicators and event_indicators_prev so that we can get new indicators */ fmi2_real_t *temp = event_indicators; event_indicators = event_indicators_prev; event_indicators_prev = temp; } fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators); /* Check if an event indicator has triggered */ for (k = 0; k < n_event_indicators; k++) { if ((event_indicators[k] > 0) != (event_indicators_prev[k] > 0)) { zero_crossing_event = 1; break; } } /* Handle any events */ if (callEventUpdate || zero_crossing_event || (eventInfo.nextEventTimeDefined && tcur == eventInfo.nextEventTime)) { fmistatus = fmi2_import_enter_event_mode(fmu); do_event_iteration(fmu, &eventInfo); fmistatus = fmi2_import_enter_continuous_time_mode(fmu); fmistatus = fmi2_import_get_continuous_states(fmu, states, n_states); fmistatus = fmi2_import_get_event_indicators(fmu, event_indicators, n_event_indicators); } /* Calculate next time step */ tlast = tcur; tcur += hdef; if (eventInfo.nextEventTimeDefined && (tcur >= eventInfo.nextEventTime)) { tcur = eventInfo.nextEventTime; } hcur = tcur - tlast; if(tcur > tend - hcur/1e16) { tcur = tend; hcur = tcur - tlast; } /* Integrate a step */ fmistatus = fmi2_import_get_derivatives(fmu, states_der, n_states); for (k = 0; k < n_states; k++) { states[k] = states[k] + hcur*states_der[k]; if (k == 0) printf("Ball height state[%u] = %f\n", (unsigned)k, states[k]); } /* Set states */ fmistatus = fmi2_import_set_continuous_states(fmu, states, n_states); /* Step is complete */ fmistatus = fmi2_import_completed_integrator_step(fmu, fmi2_true, &callEventUpdate, &terminateSimulation); } /* Validate result */ for (k = 0; k < n_states; k++) { fmi2_real_t res = states[k] - states_end_results[k]; res = res > 0 ? res: -res; /* Take abs */ if (res > 1e-10) { printf("Simulation results is wrong states[%u] %f != %f, |res| = %f\n", (unsigned)k, states[k], states_end_results[k], res); do_exit(CTEST_RETURN_FAIL); } } fmistatus = fmi2_import_terminate(fmu); fmi2_import_free_instance(fmu); free(states); free(states_der); free(event_indicators); free(event_indicators_prev); return 0; }
void* FMI2ModelExchangeConstructor_OMC(int fmi_log_level, char* working_directory, char* instanceName, int debugLogging) { FMI2ModelExchange* FMI2ME = malloc(sizeof(FMI2ModelExchange)); jm_status_enu_t status, instantiateModelStatus; FMI2ME->FMILogLevel = fmi_log_level; /* JM callbacks */ FMI2ME->JMCallbacks.malloc = malloc; FMI2ME->JMCallbacks.calloc = calloc; FMI2ME->JMCallbacks.realloc = realloc; FMI2ME->JMCallbacks.free = free; FMI2ME->JMCallbacks.logger = importlogger; FMI2ME->JMCallbacks.log_level = FMI2ME->FMILogLevel; FMI2ME->JMCallbacks.context = 0; FMI2ME->FMIImportContext = fmi_import_allocate_context(&FMI2ME->JMCallbacks); /* parse the xml file */ FMI2ME->FMIWorkingDirectory = (char*) malloc(strlen(working_directory)+1); strcpy(FMI2ME->FMIWorkingDirectory, working_directory); FMI2ME->FMIImportInstance = fmi2_import_parse_xml(FMI2ME->FMIImportContext, FMI2ME->FMIWorkingDirectory, NULL); if(!FMI2ME->FMIImportInstance) { FMI2ME->FMISolvingMode = fmi2_none_mode; ModelicaFormatError("Error parsing the XML file contained in %s\n", FMI2ME->FMIWorkingDirectory); return 0; } /* FMI callback functions */ FMI2ME->FMICallbackFunctions.logger = fmi2logger; FMI2ME->FMICallbackFunctions.allocateMemory = calloc; FMI2ME->FMICallbackFunctions.freeMemory = free; FMI2ME->FMICallbackFunctions.componentEnvironment = FMI2ME->FMIImportInstance; /* Load the binary (dll/so) */ status = fmi2_import_create_dllfmu(FMI2ME->FMIImportInstance, fmi2_import_get_fmu_kind(FMI2ME->FMIImportInstance), &FMI2ME->FMICallbackFunctions); if (status == jm_status_error) { FMI2ME->FMISolvingMode = fmi2_none_mode; ModelicaFormatError("Loading of FMU dynamic link library failed with status : %s\n", jm_log_level_to_string(status)); return 0; } FMI2ME->FMIInstanceName = (char*) malloc(strlen(instanceName)+1); strcpy(FMI2ME->FMIInstanceName, instanceName); FMI2ME->FMIDebugLogging = debugLogging; instantiateModelStatus = fmi2_import_instantiate(FMI2ME->FMIImportInstance, FMI2ME->FMIInstanceName, fmi2_model_exchange, NULL, fmi2_false); if (instantiateModelStatus == jm_status_error) { FMI2ME->FMISolvingMode = fmi2_none_mode; ModelicaFormatError("fmi2InstantiateModel failed with status : %s\n", jm_log_level_to_string(instantiateModelStatus)); return 0; } /* Only call fmi2SetDebugLogging if debugLogging is true */ if (FMI2ME->FMIDebugLogging) { int i; size_t categoriesSize = 0; fmi2_status_t debugLoggingStatus; fmi2_string_t *categories; /* Read the log categories size */ categoriesSize = fmi2_import_get_log_categories_num(FMI2ME->FMIImportInstance); categories = (fmi2_string_t*)malloc(categoriesSize*sizeof(fmi2_string_t)); for (i = 0 ; i < categoriesSize ; i++) { categories[i] = fmi2_import_get_log_category(FMI2ME->FMIImportInstance, i); } debugLoggingStatus = fmi2_import_set_debug_logging(FMI2ME->FMIImportInstance, FMI2ME->FMIDebugLogging, categoriesSize, categories); if (debugLoggingStatus != fmi2_status_ok && debugLoggingStatus != fmi2_status_warning) { ModelicaFormatMessage("fmi2SetDebugLogging failed with status : %s\n", fmi1_status_to_string(debugLoggingStatus)); } } FMI2ME->FMIToleranceControlled = fmi2_true; FMI2ME->FMIRelativeTolerance = 0.001; FMI2ME->FMIEventInfo = malloc(sizeof(fmi2_event_info_t)); FMI2ME->FMISolvingMode = fmi2_instantiated_mode; return FMI2ME; }
int test_simulate_cs(fmi2_import_t* fmu) { fmi2_status_t fmistatus; jm_status_enu_t jmstatus; fmi2_string_t instanceName = "Test CS model instance"; fmi2_string_t fmuGUID; fmi2_string_t fmuLocation = ""; fmi2_boolean_t visible = fmi2_false; fmi2_real_t relativeTol = 1e-4; /* fmi2_boolean_t loggingOn = fmi2_true; */ /* fmi2_real_t simulation_results[] = {-0.001878, -1.722275}; */ fmi2_real_t simulation_results[] = {0.0143633, -1.62417}; fmi2_value_reference_t compare_real_variables_vr[] = {0, 1}; size_t k; fmi2_real_t tstart = 0.0; fmi2_real_t tcur = tstart; fmi2_real_t hstep = 0.1; fmi2_real_t tend = 2.0; fmi2_boolean_t StopTimeDefined = fmi2_false; if (sizeof(compare_real_variables_vr)/sizeof(fmi2_value_reference_t) != sizeof(simulation_results)/sizeof(fmi2_real_t)) { printf("Number of simulation values and reference values are different\n"); do_exit(CTEST_RETURN_FAIL); } printf("Version returned from FMU: %s\n", fmi2_import_get_version(fmu)); printf("Platform type returned: %s\n", fmi2_import_get_types_platform(fmu)); fmuGUID = fmi2_import_get_GUID(fmu); printf("GUID: %s\n", fmuGUID); jmstatus = fmi2_import_instantiate(fmu, instanceName, fmi2_cosimulation, fmuLocation, visible); if (jmstatus == jm_status_error) { printf("fmi2_import_instantiate failed\n"); do_exit(CTEST_RETURN_FAIL); } fmistatus = fmi2_import_setup_experiment(fmu, fmi2_true, relativeTol, tstart, StopTimeDefined, tend); if(fmistatus != fmi2_status_ok) { printf("fmi2_import_setup_experiment failed\n"); do_exit(CTEST_RETURN_FAIL); } fmistatus = fmi2_import_enter_initialization_mode(fmu); if(fmistatus != fmi2_status_ok) { printf("fmi2_import_enter_initialization_mode failed\n"); do_exit(CTEST_RETURN_FAIL); } fmistatus = fmi2_import_exit_initialization_mode(fmu); if(fmistatus != fmi2_status_ok) { printf("fmi2_import_exit_initialization_mode failed\n"); do_exit(CTEST_RETURN_FAIL); } tcur = tstart; printf("%10s %10s\n", "Ball height", "Ball speed"); while (tcur < tend) { fmi2_boolean_t newStep = fmi2_true; #if 0 /* Prints a real value.. */ fmi2_real_t rvalue; fmi2_value_reference_t vr = 0; fmistatus = fmi2_import_get_real(fmu, &vr, 1, &rvalue); printf("rvalue = %f\n", rvalue); #endif fmistatus = fmi2_import_do_step(fmu, tcur, hstep, newStep); for (k = 0; k < sizeof(compare_real_variables_vr)/sizeof(fmi2_value_reference_t); k++) { fmi2_value_reference_t vr = compare_real_variables_vr[k]; fmi2_real_t rvalue; fmistatus = fmi2_import_get_real(fmu, &vr, 1, &rvalue); } { fmi2_real_t val[2]; fmi2_import_get_real(fmu, compare_real_variables_vr, 2, val); printf("%10g %10g\n", val[0],val[1]); } tcur += hstep; } printf("Simulation finished. Checking results\n"); /* Validate result */ for (k = 0; k < sizeof(compare_real_variables_vr)/sizeof(fmi2_value_reference_t); k++) { fmi2_value_reference_t vr = compare_real_variables_vr[k]; fmi2_real_t rvalue; fmi2_real_t res; fmistatus = fmi2_import_get_real(fmu, &vr, 1, &rvalue); res = rvalue - simulation_results[k]; res = res > 0 ? res: -res; /* Take abs */ if (res > 3e-3) { printf("Simulation results is wrong!\n"); printf("State [%u] %g != %g, |res| = %g\n", (unsigned)k, rvalue, simulation_results[k], res); printf("\n"); do_exit(CTEST_RETURN_FAIL); } } fmistatus = fmi2_import_terminate(fmu); fmi2_import_free_instance(fmu); return 0; }