fmi1_variable_naming_convension_enu_t fmi1_import_get_naming_convention(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return fmi1_naming_enu_unknown; } return fmi1_xml_get_naming_convention(fmu->md); }
fmi1_import_vendor_list_t* fmi1_import_get_vendor_list(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return fmi1_xml_get_vendor_list(fmu->md); }
double fmi1_import_get_default_experiment_tolerance(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return fmi1_xml_get_default_experiment_tolerance(fmu->md); }
unsigned int fmi1_import_get_number_of_event_indicators(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return fmi1_xml_get_number_of_event_indicators(fmu->md); }
void fmi1_import_set_default_experiment_stop(fmi1_import_t* fmu, double t) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return; } fmi1_xml_set_default_experiment_stop(fmu->md, t); }
fmi1_import_type_definitions_t* fmi1_import_get_type_definitions(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return fmi1_xml_get_type_definitions(fmu->md); }
/* FMI 2.0 Common functions */ const char* fmi2_import_get_version(fmi2_import_t* fmu) { if(!fmu->capi) { jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded"); return 0; } return fmi2_capi_get_version(fmu -> capi); }
const char* fmi1_import_get_model_version(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return fmi1_xml_get_model_version(fmu->md); }
const char* fmi1_import_get_generation_date_and_time(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return fmi1_xml_get_generation_date_and_time(fmu->md); }
int fmi2_import_check_has_FMU(fmi2_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return 1; }
fmi2_status_t fmi2_import_set_debug_logging(fmi2_import_t* fmu, fmi2_boolean_t loggingOn, size_t nCategories, fmi2_string_t categories[]) { if(!fmu->capi) { jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded"); return fmi2_status_fatal; } return fmi2_capi_set_debug_logging(fmu -> capi, loggingOn, nCategories, categories); }
unsigned int fmi1_import_get_number_of_continuous_states(fmi1_import_t* fmu) { if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } return fmi1_xml_get_number_of_continuous_states(fmu->md); }
/* Loading shared library functions */ static jm_status_enu_t fmi2_capi_get_fcn(fmi2_capi_t* fmu, const char* function_name, jm_dll_function_ptr* dll_function_ptrptr, jm_status_enu_t* status ) { jm_status_enu_t jm_status = jm_portability_load_dll_function(fmu->dllHandle, (char*)function_name, dll_function_ptrptr); if (jm_status == jm_status_error) { jm_log_error(fmu->callbacks, FMI_CAPI_MODULE_NAME, "Could not load the FMI function '%s'. %s", function_name, jm_portability_get_last_dll_error()); *status = jm_status_error; } return jm_status; }
jm_status_enu_t fmi2_capi_load_fcn(fmi2_capi_t* fmu, unsigned int capabilities[]) { assert(fmu); /* Load ME functions */ if (fmu->standard == fmi2_fmu_kind_me) { return fmi2_capi_load_me_fcn(fmu, capabilities); /* Load CS functions */ } else if (fmu->standard == fmi2_fmu_kind_cs) { return fmi2_capi_load_cs_fcn(fmu, capabilities); } else { jm_log_error(fmu->callbacks, FMI_CAPI_MODULE_NAME, "Unexpected FMU kind in FMICAPI."); return jm_status_error; } }
/* Get the list of all the variables in the model in alphabetical order */ fmi1_import_variable_list_t* fmi1_import_get_variable_list_alphabetical_order(fmi1_import_t* fmu) { jm_vector(jm_named_ptr)* vars; fmi1_import_variable_list_t* vl; size_t nv, i; if(!fmu->md) { jm_log_error(fmu->callbacks, module,"No FMU is loaded"); return 0; } vars = fmi1_xml_get_variables_alphabetical_order(fmu->md); nv = jm_vector_get_size(jm_named_ptr)(vars); vl = fmi1_import_alloc_variable_list(fmu, nv); if(!vl) return 0; for(i = 0; i< nv; i++) { jm_vector_set_item(jm_voidp)(&vl->variables, i, jm_vector_get_item(jm_named_ptr)(vars, i).ptr); } return vl; }
/* Load FMI 1.0 Co-Simulation functions */ static jm_status_enu_t fmi1_capi_load_cs_fcn(fmi1_capi_t* fmu) { jm_status_enu_t jm_status = jm_status_success; jm_log_verbose(fmu->callbacks, FMI_CAPI_MODULE_NAME, "Loading functions for the co-simulation interface"); /* Workaround for Dymola 2012 and SimulationX 3.x */ if (fmi1_capi_get_fcn(fmu, "fmiGetTypesPlatform",(jm_dll_function_ptr*)&fmu->fmiGetTypesPlatform) == jm_status_error) { jm_log_warning(fmu->callbacks, FMI_CAPI_MODULE_NAME, "Could not load the FMI function 'fmiGetTypesPlatform'. %s. Trying to load fmiGetModelTypesPlatform instead.", jm_portability_get_last_dll_error()); jm_status = jm_status_warning; if (fmi1_capi_get_fcn(fmu, "fmiGetModelTypesPlatform", (jm_dll_function_ptr*)&fmu->fmiGetTypesPlatform) == jm_status_error) { jm_log_error(fmu->callbacks, FMI_CAPI_MODULE_NAME, "Could not load the FMI function 'fmiGetModelTypesPlatform'. %s", jm_portability_get_last_dll_error()); jm_status = jm_status_error; } } LOAD_DLL_FUNCTION(fmiInstantiateSlave); LOAD_DLL_FUNCTION(fmiInitializeSlave); LOAD_DLL_FUNCTION(fmiTerminateSlave); LOAD_DLL_FUNCTION(fmiResetSlave); LOAD_DLL_FUNCTION(fmiFreeSlaveInstance); LOAD_DLL_FUNCTION(fmiSetRealInputDerivatives); LOAD_DLL_FUNCTION(fmiGetRealOutputDerivatives); LOAD_DLL_FUNCTION(fmiCancelStep); LOAD_DLL_FUNCTION(fmiDoStep); LOAD_DLL_FUNCTION(fmiGetStatus); LOAD_DLL_FUNCTION(fmiGetRealStatus); LOAD_DLL_FUNCTION(fmiGetIntegerStatus); LOAD_DLL_FUNCTION(fmiGetBooleanStatus); LOAD_DLL_FUNCTION(fmiGetStringStatus); LOAD_DLL_FUNCTION(fmiGetVersion); LOAD_DLL_FUNCTION(fmiSetDebugLogging); LOAD_DLL_FUNCTION(fmiSetReal); LOAD_DLL_FUNCTION(fmiSetInteger); LOAD_DLL_FUNCTION(fmiSetBoolean); LOAD_DLL_FUNCTION(fmiSetString); LOAD_DLL_FUNCTION(fmiGetReal); LOAD_DLL_FUNCTION(fmiGetInteger); LOAD_DLL_FUNCTION(fmiGetBoolean); LOAD_DLL_FUNCTION(fmiGetString); return jm_status; }
/* Load and destroy functions */ jm_status_enu_t fmi2_import_create_dllfmu(fmi2_import_t* fmu, fmi2_fmu_kind_enu_t fmuKind, const fmi2_callback_functions_t* callBackFunctions) { char curDir[FILENAME_MAX + 2]; char* dllDirPath = 0; char* dllFileName = 0; const char* modelIdentifier; fmi2_callback_functions_t defaultCallbacks; if (fmu == NULL) { assert(0); return jm_status_error; } if(fmu -> capi) { if(fmi2_capi_get_fmu_kind(fmu -> capi) == fmuKind) { jm_log_warning(fmu->callbacks, module, "FMU binary is already loaded"); return jm_status_success; } else fmi2_import_destroy_dllfmu(fmu); } if(fmuKind == fmi2_fmu_kind_me) modelIdentifier = fmi2_import_get_model_identifier_ME(fmu); else if(fmuKind == fmi2_fmu_kind_cs) modelIdentifier = fmi2_import_get_model_identifier_CS(fmu); else { assert(0); return jm_status_error; } if (modelIdentifier == NULL) { jm_log_error(fmu->callbacks, module, "No model identifier given"); return jm_status_error; } if( jm_portability_get_current_working_directory(curDir, FILENAME_MAX+1) != jm_status_success) { jm_log_warning(fmu->callbacks, module, "Could not get current working directory (%s)", strerror(errno)); curDir[0] = 0; }; dllDirPath = fmi_construct_dll_dir_name(fmu->callbacks, fmu->dirPath); dllFileName = fmi_construct_dll_file_name(fmu->callbacks, dllDirPath, modelIdentifier); if (!dllDirPath ||!dllFileName) { fmu->callbacks->free(dllDirPath); return jm_status_error; } if(!callBackFunctions) { jm_callbacks* cb = fmu->callbacks; defaultCallbacks.allocateMemory = cb->calloc; defaultCallbacks.freeMemory = cb->free; defaultCallbacks.componentEnvironment = fmu; defaultCallbacks.logger = fmi2_log_forwarding; defaultCallbacks.stepFinished = 0; callBackFunctions = &defaultCallbacks; } if(jm_portability_set_current_working_directory(dllDirPath) != jm_status_success) { jm_log_fatal(fmu->callbacks, module, "Could not change to the DLL directory %s", dllDirPath); if(ENOENT == errno) jm_log_fatal(fmu->callbacks, module, "No binary for this platform?"); else jm_log_fatal(fmu->callbacks, module, "System error: %s", strerror(errno)); } else { /* Allocate memory for the C-API struct */ fmu -> capi = fmi2_capi_create_dllfmu(fmu->callbacks, dllFileName, modelIdentifier, callBackFunctions, fmuKind); } /* Load the DLL handle */ if (fmu -> capi) { jm_log_info(fmu->callbacks, module, "Loading '" FMI_PLATFORM "' binary with '%s' platform types", fmi2_get_types_platform() ); if(fmi2_capi_load_dll(fmu -> capi) == jm_status_error) { fmi2_capi_destroy_dllfmu(fmu -> capi); fmu -> capi = NULL; } } if(curDir[0] && (jm_portability_set_current_working_directory(curDir) != jm_status_success)) { jm_log_error(fmu->callbacks, module, "Could not restore current working directory (%s)", strerror(errno)); } fmu->callbacks->free((jm_voidp)dllDirPath); fmu->callbacks->free((jm_voidp)dllFileName); if (fmu -> capi == NULL) { return jm_status_error; } /* Load the DLL functions */ if (fmi2_capi_load_fcn(fmu -> capi, fmi2_xml_get_capabilities(fmu->md)) == jm_status_error) { fmi2_capi_free_dll(fmu -> capi); fmi2_capi_destroy_dllfmu(fmu -> capi); fmu -> capi = NULL; return jm_status_error; } jm_log_verbose(fmu->callbacks, module, "Successfully loaded all the interface functions"); return jm_status_success; }
jm_status_enu_t fmi1_cs_simulate(fmu_check_data_t* cdata) { fmi1_status_t fmistatus; jm_status_enu_t jmstatus = jm_status_success; jm_callbacks* cb = &cdata->callbacks; fmi1_import_t* fmu = cdata->fmu1; fmi1_string_t fmuGUID = fmi1_import_get_GUID(fmu); fmi1_string_t mimeType; fmi1_real_t timeout = 0.0; fmi1_boolean_t visible = fmi1_false; fmi1_boolean_t interactive = fmi1_false; fmi1_real_t tstart = fmi1_import_get_default_experiment_start(fmu); fmi1_real_t tcur = tstart; fmi1_real_t hstep; fmi1_real_t tend = fmi1_import_get_default_experiment_stop(fmu); fmi1_boolean_t StopTimeDefined = fmi1_true; mimeType = fmi1_import_get_mime_type(fmu); if( (cdata->fmu1_kind == fmi1_fmu_kind_enu_cs_standalone) || !mimeType || !mimeType[0]) { mimeType = "application/x-fmu-sharedlibrary"; } else { if( strcmp(mimeType, "application/x-fmu-sharedlibrary") != 0 ) { jm_log_info(cb, fmu_checker_module,"The FMU requests simulator with MIME type '%s'.", mimeType); printf("\nPlease, start a simulator program for MIME type '%s'\nPress enter to continue.\n", mimeType); getchar(); } } if(cdata->stopTime > 0) { tend = cdata->stopTime; } if(cdata->stepSize > 0) { hstep = cdata->stepSize; } else { hstep = (tend - tstart) / cdata->numSteps; } cdata->instanceName = "Test FMI 1.0 CS"; jm_log_verbose(cb, fmu_checker_module, "Checker will instantiate the slave with \n" "\tFMU location ='%s'\n\tMIME type = '%s'", cdata->fmuLocation, mimeType); jmstatus = fmi1_import_instantiate_slave(fmu, cdata->instanceName, cdata->fmuLocation, mimeType, timeout, visible, interactive); if (jmstatus == jm_status_error) { jm_log_fatal(cb, fmu_checker_module, "Could not instantiate the model"); return jm_status_error; } fmistatus = fmi1_import_initialize_slave(fmu, tstart, StopTimeDefined, tend); if((fmistatus == fmi1_status_ok) || (fmistatus == fmi1_status_warning)) { jm_log_info(cb, fmu_checker_module, "Initialized FMU for simulation starting at time %g", tstart); fmistatus = fmi1_status_ok; } else { jm_log_fatal(cb, fmu_checker_module, "Failed to initialize FMU for simulation (FMU status: %s)", fmi1_status_to_string(fmistatus)); jmstatus = jm_status_error; } if(jmstatus != jm_status_error) { jm_log_verbose(cb, fmu_checker_module, "Writing simulation output for start time"); if(fmi1_write_csv_data(cdata, tstart) != jm_status_success){ jmstatus = jm_status_error; } } while ((tcur < tend) && (jmstatus != jm_status_error)) { fmi1_boolean_t newStep = fmi1_true; fmi1_real_t tnext = tcur + hstep; if(tnext > tend - 1e-3*hstep) { /* last step should be on tend */ hstep = tend - tcur; tnext = tend; } jm_log_verbose(cb, fmu_checker_module, "Simulation step from time: %g until: %g", tcur, tnext); fmistatus = fmi1_import_do_step(fmu, tcur, hstep, newStep); tcur = tnext; if(fmi1_write_csv_data(cdata, tcur) != jm_status_success){ jmstatus = jm_status_error; } if((fmistatus == fmi1_status_ok) || (fmistatus == fmi1_status_warning)) { fmistatus = fmi1_status_ok; } else jmstatus = jm_status_error; } if((fmistatus != fmi1_status_ok) && (fmistatus != fmi1_status_warning)) { jm_log_fatal(cb, fmu_checker_module, "Simulation loop terminated at time %g since FMU returned status: %s", tcur, fmi1_status_to_string(fmistatus)); jmstatus = jm_status_error; } else if(jmstatus != jm_status_error) { jm_log_info(cb, fmu_checker_module, "Simulation finished successfully at time %g", tcur); } fmistatus = fmi1_import_terminate_slave(fmu); if( fmistatus != fmi1_status_ok) { jm_log_error(cb, fmu_checker_module, "fmiTerminateSlave returned status: %s", fmi1_status_to_string(fmistatus)); } fmi1_import_free_slave_instance(fmu); return jmstatus; }
void fmi1_xml_parse_error(fmi1_xml_parser_context_t *context, const char* message) { if(context->parser) jm_log_error(context->callbacks, module, "[Line:%u] %s", XML_GetCurrentLineNumber(context->parser),message); else jm_log_error(context->callbacks, module, "%s", message); }