diff --git a/Compiler/FrontEnd/ModelicaBuiltin.mo b/Compiler/FrontEnd/ModelicaBuiltin.mo index 17f1276c862..e853ee450e8 100644 --- a/Compiler/FrontEnd/ModelicaBuiltin.mo +++ b/Compiler/FrontEnd/ModelicaBuiltin.mo @@ -1857,7 +1857,7 @@ function importFMUNew "Imports the Functional Mockup Unit importFMU(\"A.fmu\");" input String filename "the fmu file name"; input String workdir := "" "The output directory for imported FMU files. will put the files to current working directory."; - input Integer loglevel := 6 "loglevel_nothing=0;loglevel_fatal=1;loglevel_error=2;loglevel_warning=3;loglevel_info=4;loglevel_verbose=5;loglevel_debug=6"; + input Integer loglevel := 2 "loglevel_nothing=0;loglevel_fatal=1;loglevel_error=2;loglevel_warning=3;loglevel_info=4;loglevel_verbose=5;loglevel_debug=6"; output String generatedFileName "Returns the full path of the generated file."; external "builtin"; annotation(preferredView="text"); diff --git a/Compiler/Script/CevalScript.mo b/Compiler/Script/CevalScript.mo index 7950ac6ae1e..4a6963aeaa3 100644 --- a/Compiler/Script/CevalScript.mo +++ b/Compiler/Script/CevalScript.mo @@ -1450,8 +1450,9 @@ algorithm fmiModelVariablesInstance, fmiModelVariablesList) = FMI.initializeFMIImport(filename, workdir, fmiLogLevel); true = b; /* if something goes wrong while initializing */ fmiModelVariablesList1 = listReverse(fmiModelVariablesList); - str = Tpl.tplString(CodegenFMU.importFMUModelica, FMI.FMIIMPORT(fmiContext, fmiInstance, fmiModelIdentifier, fmiDescription, fmiExperimentStartTime, - fmiExperimentStopTime, fmiExperimentTolerance, fmiModelVariablesInstance, fmiModelVariablesList1)); + str = Tpl.tplString(CodegenFMU.importFMUModelica, FMI.FMIIMPORT(filename, workdir, fmiLogLevel, fmiContext, fmiInstance, fmiModelIdentifier, fmiDescription, + fmiExperimentStartTime, fmiExperimentStopTime, fmiExperimentTolerance, + fmiModelVariablesInstance, fmiModelVariablesList1)); pd = System.pathDelimiter(); filename_1 = stringAppendList({workdir,pd,fmiModelIdentifier,"FMUImportNew.mo"}); System.writeFile(filename_1, str); diff --git a/Compiler/Template/CodegenFMU.tpl b/Compiler/Template/CodegenFMU.tpl index abe4a20e7bc..44e7f1e6ce6 100644 --- a/Compiler/Template/CodegenFMU.tpl +++ b/Compiler/Template/CodegenFMU.tpl @@ -1105,8 +1105,9 @@ case FMIIMPORT(__) then class fmiImportContext extends ExternalObject; function constructor + input Integer fmiLogLevel; output fmiImportContext context; - external "C" context = fmi_import_allocate_context_OMC() annotation(Library = {"omcruntime", "fmilib"}); + external "C" context = fmi_import_allocate_context_OMC(fmiLogLevel) annotation(Library = {"omcruntime", "fmilib"}); end constructor; function destructor @@ -1120,16 +1121,61 @@ case FMIIMPORT(__) then function constructor input fmiImportContext context; input String tempPath; - output fmiImportInstance fmu; - external "C" fmu = fmiImportInstance_OMC(context, tempPath) annotation(Library = {"omcruntime", "fmilib"}); + output fmiImportInstance fmi; + external "C" fmi = fmiImportInstance_OMC(context, tempPath) annotation(Library = {"omcruntime", "fmilib"}); end constructor; function destructor - input fmiImportInstance fmu; - external "C" fmiImportFreeInstance_OMC(fmu) annotation(Library = {"omcruntime", "fmilib"}); + input fmiImportInstance fmi; + external "C" fmiImportFreeInstance_OMC(fmi) annotation(Library = {"omcruntime", "fmilib"}); end destructor; end fmiImportInstance; + package fmiFunctions + function fmiInstantiateModel + input fmiImportInstance fmi; + input String instanceName; + output Integer status; + external "C" status = fmiInstantiateModel_OMC(fmi, instanceName) annotation(Library = {"omcruntime", "fmilib"}); + end fmiInstantiateModel; + + function fmiSetTime + input fmiImportInstance fmi; + input Real in_time; + output Integer status; + external "C" status = fmiSetTime_OMC(fmi, in_time) annotation(Library = {"omcruntime", "fmilib"}); + end fmiSetTime; + + function fmiInitialize + input fmiImportInstance fmi; + output Integer status; + external "C" status = fmiInitialize_OMC(fmi) annotation(Library = {"omcruntime", "fmilib"}); + end fmiInitialize; + + function fmiGetContinuousStates + input fmiImportInstance fmi; + input Integer numberOfContinuousStates; + input Real fmi_x[numberOfContinuousStates]; + output Integer status; + external "C" status = fmiGetContinuousStates_OMC(fmi, fmi_x, numberOfContinuousStates) annotation(Library = {"omcruntime", "fmilib"}); + end fmiGetContinuousStates; + + function fmiGetEventIndicators + input fmiImportInstance fmi; + input Integer numberOfEventIndicators; + input Real fmi_z[numberOfEventIndicators]; + output Integer status; + external "C" status = fmiGetEventIndicators_OMC(fmi, fmi_z, numberOfEventIndicators) annotation(Library = {"omcruntime", "fmilib"}); + end fmiGetEventIndicators; + + function fmiSetDebugLogging + input fmiImportInstance fmi; + input Boolean debugLogging; + output Integer status; + external "C" status = fmiSetDebugLogging_OMC(fmi, debugLogging) annotation(Library = {"omcruntime", "fmilib"}); + end fmiSetDebugLogging; + end fmiFunctions; + package fmiStatus constant Integer fmiOK=0; constant Integer fmiWarning=1; @@ -1146,9 +1192,29 @@ case FMIIMPORT(__) then end jmStatus; model FMUModel <%if stringEq(fmiDescription, "") then "" else " \"fmiDescription\""%> + constant String fmuFile = "<%fmuFileName%>"; + constant String fmuWorkingDir = "<%fmuWorkingDirectory%>"; + constant Integer fmiLogLevel = <%fmiLogLevel%>; <%dumpFMIModelVariablesList(fmiModelVariablesList)%> - constant Integer numberOfContinuousStates=<%getFMINumberOfContinuousStates(fmiInstance)%>; - constant Integer numberOfEventIndicators=<%getFMINumberOfEventIndicators(fmiInstance)%>; + constant Integer numberOfContinuousStates = <%getFMINumberOfContinuousStates(fmiInstance)%>; + Real fmi_x[numberOfContinuousStates] "States"; + constant Integer numberOfEventIndicators = <%getFMINumberOfEventIndicators(fmiInstance)%>; + Real fmi_z[numberOfEventIndicators] "Event indicators"; + constant Boolean debugLogging = true; + Integer fmi_status; + fmiImportInstance fmi = fmiImportInstance(context, fmuWorkingDir); + fmiImportContext context = fmiImportContext(fmiLogLevel); + initial algorithm + fmiFunctions.fmiInstantiateModel(fmi, "<%fmiModelIdentifier%>"); + fmi_status := fmiFunctions.fmiSetTime(fmi, time); + fmi_status := fmiFunctions.fmiInitialize(fmi); + fmi_status := fmiFunctions.fmiGetContinuousStates(fmi, fmi_x, numberOfContinuousStates); + fmi_status := fmiFunctions.fmiGetEventIndicators(fmi, fmi_z, numberOfEventIndicators); + fmi_status := fmiFunctions.fmiSetDebugLogging(fmi, debugLogging); + equation + fmi_status = fmiFunctions.fmiSetTime(fmi, time); + assert(fmi_status<>fmiStatus.fmiFatal, "fmiInitialize returned a fatal error."); + assert(fmi_status<>fmiStatus.fmiError, "fmiInitialize returned an error."); annotation(experiment(StartTime=<%fmiExperimentStartTime%>, StopTime=<%fmiExperimentStopTime%>, Tolerance=<%fmiExperimentTolerance%>)); end FMUModel; end <%fmiModelIdentifier%>_FMU; diff --git a/Compiler/Template/SimCodeTV.mo b/Compiler/Template/SimCodeTV.mo index de7936c141c..69d52fb22d3 100644 --- a/Compiler/Template/SimCodeTV.mo +++ b/Compiler/Template/SimCodeTV.mo @@ -2557,6 +2557,9 @@ package FMI uniontype FmiImport record FMIIMPORT + String fmuFileName; + String fmuWorkingDirectory; + Integer fmiLogLevel; Integer fmiContext; Integer fmiInstance; String fmiModelIdentifier; diff --git a/Compiler/Util/FMI.mo b/Compiler/Util/FMI.mo index 60c7c405e8e..4919d8e0e4a 100644 --- a/Compiler/Util/FMI.mo +++ b/Compiler/Util/FMI.mo @@ -35,6 +35,9 @@ uniontype FmiImport record FMIIMPORT + String fmuFileName; + String fmuWorkingDirectory; + Integer fmiLogLevel; Integer fmiContext; Integer fmiInstance; String fmiModelIdentifier; diff --git a/Compiler/runtime/FMIWrapper.c b/Compiler/runtime/FMIWrapper.c index d32012d1ae8..3fa33dfd7b2 100644 --- a/Compiler/runtime/FMIWrapper.c +++ b/Compiler/runtime/FMIWrapper.c @@ -62,7 +62,7 @@ static void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_statu /* * Creates an instance of the FMI Import Context i.e fmi_import_context_t */ -void* fmi_import_allocate_context_OMC() +void* fmi_import_allocate_context_OMC(int fmi_log_level) { // JM callbacks static int init = 0; @@ -74,7 +74,7 @@ void* fmi_import_allocate_context_OMC() callbacks.realloc = realloc; callbacks.free = free; callbacks.logger = importlogger; - callbacks.log_level = jm_log_level_debug; + callbacks.log_level = fmi_log_level; callbacks.context = 0; } fmi_import_context_t* context = fmi_import_allocate_context(&callbacks); @@ -106,31 +106,59 @@ void* fmiImportInstance_OMC(void* context, char* working_directory) callback_functions.freeMemory = free; } // parse the xml file - fmi1_import_t* fmu; - fmu = fmi1_import_parse_xml((fmi_import_context_t*)context, working_directory); - if(!fmu) { + fmi1_import_t* fmi; + fmi = fmi1_import_parse_xml((fmi_import_context_t*)context, working_directory); + if(!fmi) { fprintf(stderr, "Error parsing the XML file contained in %s\n", working_directory); return 0; } // Load the binary (dll/so) jm_status_enu_t status; - status = fmi1_import_create_dllfmu(fmu, callback_functions, 0); + status = fmi1_import_create_dllfmu(fmi, callback_functions, 0); if (status == jm_status_error) { fprintf(stderr, "Could not create the DLL loading mechanism(C-API).\n"); return 0; } - return fmu; + return fmi; } /* * Destroys the instance of the FMI Import i.e fmi1_import_t * Also destroys the loaded binary (dll/so). */ -void fmiImportFreeInstance_OMC(void* fmu) +void fmiImportFreeInstance_OMC(void* fmi) { - fmi1_import_t* fmu1 = (fmi1_import_t*)fmu; - fmi1_import_destroy_dllfmu(fmu1); - fmi1_import_free(fmu1); + fmi1_import_t* fmi1 = (fmi1_import_t*)fmi; + fmi1_import_destroy_dllfmu(fmi1); + fmi1_import_free(fmi1); +} + +int fmiInstantiateModel_OMC(void* fmi, const char* instanceName) +{ + return fmi1_import_instantiate_model((fmi1_import_t*)fmi, instanceName); +} + +int fmiSetTime_OMC(void* fmi, double time) +{ + return fmi1_import_set_time((fmi1_import_t*)fmi, time); +} + +int fmiInitialize_OMC(void* fmi) +{ + fmi1_boolean_t toleranceControlled = fmi1_true; + fmi1_real_t relativeTolerance = 0.001; + fmi1_event_info_t eventInfo; + return fmi1_import_initialize((fmi1_import_t*)fmi, toleranceControlled, relativeTolerance, &eventInfo); +} + +int fmiGetContinuousStates_OMC(void* fmi, const double* states, int numberOfContinuousStates) +{ + return fmi1_import_get_continuous_states((fmi1_import_t*)fmi, (fmi1_real_t*)states, numberOfContinuousStates); +} + +int fmiGetEventIndicators_OMC(void* fmi, const double* events, int numberOfEventIndicators) +{ + return fmi1_import_get_event_indicators((fmi1_import_t*)fmi, (fmi1_real_t*)events, numberOfEventIndicators); } #ifdef __cplusplus