/* * Wrapper for the FMI function fmi2GetContinuousStates. * parameter flowParams is dummy and is only used to run the equations in sequence. * Returns states. */ void fmi2GetContinuousStates_OMC(void* in_fmi2me, int numberOfContinuousStates, double flowParams, double* states) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me; fmi2_status_t status = fmi2_import_get_continuous_states(FMI2ME->FMIImportInstance, (fmi2_real_t*)states, numberOfContinuousStates); if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2GetContinuousStates failed with status : %s\n", fmi2_status_to_string(status)); } }
/* * Wrapper for the FMI function fmi2GetEventIndicators. * parameter flowStates is dummy and is only used to run the equations in sequence. * Returns events. */ void fmi2GetEventIndicators_OMC(void* in_fmi2me, int numberOfEventIndicators, double flowStates, double* events) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me; fmi2_status_t status = fmi2_import_get_event_indicators(FMI2ME->FMIImportInstance, (fmi2_real_t*)events, numberOfEventIndicators); if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2GetEventIndicators failed with status : %s\n", fmi2_status_to_string(status)); } }
/* * Wrapper for the FMI function fmi2ExitInitializationMode. */ void fmi2ExitInitializationModel_OMC(void* in_fmi2me) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me; fmi2_status_t status = fmi2_import_exit_initialization_mode(FMI2ME->FMIImportInstance); FMI2ME->FMISolvingMode = fmi2_event_mode; if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2ExitInitializationMode failed with status : %s\n", fmi2_status_to_string(status)); } }
/* Logger function used by the FMU internally */ static void fmi2logger(fmi2_component_environment_t env, fmi2_string_t instanceName, fmi2_status_t status, fmi2_string_t category, fmi2_string_t message, ...) { int len; char msg[BUFFER]; va_list argp; va_start(argp, message); len = jm_vsnprintf(msg, BUFFER, message, argp); printf("fmiStatus = %s; %s (%s): %s\n", fmi2_status_to_string(status), instanceName, category, msg); }
void fmi2_log_forwarding_v(fmi2_component_environment_t c, fmi2_string_t instanceName, fmi2_status_t status, fmi2_string_t category, fmi2_string_t message, va_list args) { char buf[50000], *curp; const char* statusStr; fmi2_import_t* fmu = (fmi2_import_t*)c; jm_callbacks* cb; jm_log_level_enu_t logLevel; if(fmu) { cb = fmu->callbacks; } else cb = jm_get_default_callbacks(); logLevel = cb->log_level; switch(status) { case fmi2_status_discard: case fmi2_status_pending: case fmi2_status_ok: logLevel = jm_log_level_info; break; case fmi2_status_warning: logLevel = jm_log_level_warning; break; case fmi2_status_error: logLevel = jm_log_level_error; break; case fmi2_status_fatal: default: logLevel = jm_log_level_fatal; } if(logLevel > cb->log_level) return; curp = buf; *curp = 0; if(category) { sprintf(curp, "[%s]", category); curp += strlen(category)+2; } statusStr = fmi2_status_to_string(status); sprintf(curp, "[FMU status:%s] ", statusStr); curp += strlen(statusStr) + strlen("[FMU status:] "); vsprintf(curp, message, args); if(fmu) { fmi2_import_expand_variable_references(fmu, buf, cb->errMessageBuffer,JM_MAX_ERROR_MESSAGE_SIZE); } else { strncpy(cb->errMessageBuffer, buf, JM_MAX_ERROR_MESSAGE_SIZE); cb->errMessageBuffer[JM_MAX_ERROR_MESSAGE_SIZE - 1] = '\0'; } if(cb->logger) { cb->logger(cb, instanceName, logLevel, cb->errMessageBuffer); } }
/* * Wrapper for the FMI function fmi2SetTime. * Returns status. */ void fmi2SetTime_OMC(void* in_fmi2me, double time) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me; if (FMI2ME->FMISolvingMode == fmi2_instantiated_mode || FMI2ME->FMISolvingMode == fmi2_event_mode || FMI2ME->FMISolvingMode == fmi2_continuousTime_mode) { fmi2_status_t status = fmi2_import_set_time(FMI2ME->FMIImportInstance, time); if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2SetTime failed with status : %s\n", fmi2_status_to_string(status)); } } }
/* * Wrapper for the FMI function fmi2CompletedIntegratorStep. */ int fmi2CompletedIntegratorStep_OMC(void* in_fmi2me, double flowStates) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me; if (FMI2ME->FMISolvingMode == fmi2_continuousTime_mode){ fmi2_boolean_t callEventUpdate = fmi2_false; fmi2_boolean_t terminateSimulation = fmi2_false; fmi2_status_t status = fmi2_import_completed_integrator_step(FMI2ME->FMIImportInstance, fmi2_true, &callEventUpdate, &terminateSimulation); if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2CompletedIntegratorStep failed with status : %s\n", fmi2_status_to_string(status)); } return callEventUpdate; } return fmi2_false; }
/* * Wrapper for the FMI function fmi2GetReal. * parameter flowStatesInput is dummy and is only used to run the equations in sequence. * Returns realValues. */ void fmi2GetReal_OMC(void* in_fmi2, int numberOfValueReferences, double* realValuesReferences, double flowStatesInput, double* realValues, int fmiType) { if (fmiType == 1) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2; fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, realValuesReferences); fmi2_status_t status = fmi2_import_get_real(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_real_t*)realValues); free(valuesReferences_int); if (status != fmi2_status_ok && status != fmi2_status_warning) { ModelicaFormatError("fmi2GetReal failed with status : %s\n", fmi2_status_to_string(status)); } } else if (fmiType == 2) { } }
/* * Wrapper for the FMI function fmi2NewDiscreteStates. * Returns valuesOfContinuousStatesChanged */ int fmi2EventUpdate_OMC(void* in_fmi2me) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me; fmi2_event_info_t *eventInfo = FMI2ME->FMIEventInfo; fmi2_status_t status = fmi2_import_enter_event_mode(FMI2ME->FMIImportInstance); if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2EnterEventMode failed with status : %s\n", fmi2_status_to_string(status)); } FMI2ME->FMISolvingMode = fmi2_event_mode; eventInfo->newDiscreteStatesNeeded = fmi2_true; eventInfo->terminateSimulation = fmi2_false; status = fmi2_import_new_discrete_states(FMI2ME->FMIImportInstance, eventInfo); if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2NewDiscreteStates failed with status : %s\n", fmi2_status_to_string(status)); } status = fmi2_import_enter_continuous_time_mode(FMI2ME->FMIImportInstance); if (status != fmi1_status_ok && status != fmi1_status_warning) { ModelicaFormatError("fmi2EnterContinuousTimeMode failed with status : %s\n", fmi2_status_to_string(status)); } FMI2ME->FMISolvingMode = fmi2_continuousTime_mode; return eventInfo->valuesOfContinuousStatesChanged; }
/* * Wrapper for the FMI function fmi2SetString. * Returns status. */ void fmi2SetString_OMC(void* in_fmi2, int numberOfValueReferences, double* stringValuesReferences, char** stringValues, int fmiType) { if (fmiType == 1) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2; if (FMI2ME->FMISolvingMode == fmi2_instantiated_mode || FMI2ME->FMISolvingMode == fmi2_initialization_mode || FMI2ME->FMISolvingMode == fmi2_event_mode) { fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, stringValuesReferences); fmi2_status_t status = fmi2_import_set_string(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_string_t*)stringValues); free(valuesReferences_int); if (status != fmi2_status_ok && status != fmi2_status_warning) { ModelicaFormatError("fmi2SetString failed with status : %s\n", fmi2_status_to_string(status)); } } } else if (fmiType == 2) { } }
/* * Wrapper for the FMI function fmi2GetBoolean. * parameter flowStatesInput is dummy and is only used to run the equations in sequence. * Returns booleanValues. */ void fmi2GetBoolean_OMC(void* in_fmi2, int numberOfValueReferences, double* booleanValuesReferences, double flowStatesInput, signed char* booleanValues, int fmiType) { if (fmiType == 1) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2; fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, booleanValuesReferences); int* fmiBoolean = malloc(sizeof(int)*numberOfValueReferences); fmi2_status_t status = fmi2_import_get_boolean(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, fmiBoolean); int_to_signedchar(fmiBoolean, booleanValues, numberOfValueReferences); free(fmiBoolean); free(valuesReferences_int); if (status != fmi2_status_ok && status != fmi2_status_warning) { ModelicaFormatError("fmi2GetBoolean failed with status : %s\n", fmi2_status_to_string(status)); } } else if (fmiType == 2) { } }
void fmi2_default_callback_logger(fmi2_component_environment_t c, fmi2_string_t instanceName, fmi2_status_t status, fmi2_string_t category, fmi2_string_t message, ...) { va_list args; char buf[500], *curp; va_start (args, message); curp = buf; *curp = 0; if(instanceName) { sprintf(curp, "[%s]", instanceName); curp += strlen(instanceName)+2; } if(category) { sprintf(curp, "[%s]", category); curp += strlen(category)+2; } fprintf(stdout, "%s[status=%s]", buf, fmi2_status_to_string(status)); vfprintf (stdout, message, args); fprintf(stdout, "\n"); va_end (args); }
/* * Wrapper for the FMI function fmi2SetBoolean. * Returns status. */ void fmi2SetBoolean_OMC(void* in_fmi2, int numberOfValueReferences, double* booleanValuesReferences, signed char* booleanValues, int fmiType) { if (fmiType == 1) { FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2; if (FMI2ME->FMISolvingMode == fmi2_instantiated_mode || FMI2ME->FMISolvingMode == fmi2_initialization_mode || FMI2ME->FMISolvingMode == fmi2_event_mode) { fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, booleanValuesReferences); int* fmiBoolean = malloc(sizeof(int)*numberOfValueReferences); fmi2_status_t status; signedchar_to_int(booleanValues, fmiBoolean, numberOfValueReferences); status = fmi2_import_set_boolean(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, fmiBoolean); free(fmiBoolean); free(valuesReferences_int); if (status != fmi2_status_ok && status != fmi2_status_warning) { ModelicaFormatError("fmi2SetBoolean failed with status : %s\n", fmi2_status_to_string(status)); } } } else if (fmiType == 2) { } }
static void stepFinished(fmi2_component_environment_t env, fmi2_status_t status) { printf("stepFinished is called wiht fmiStatus = %s\n", fmi2_status_to_string(status)); }
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; }