Skip to content

Commit

Permalink
Fixing fmiFlags=s:euler for CMake FMUs (#9677)
Browse files Browse the repository at this point in the history
* Fixing fmiFlags=s:euler for CMake FMUs
  - CMakeLists.txt.in changes:
    - Won't include C source files for CVODE unless needed
    - CMake will define WITH_SUNDIALS if needed
    - Link to sundials_cvode and sundials_nvecserial
  - Removed #define WITH_SUNDIALS from template
* Check if json has "s":"cvode"
  • Loading branch information
AnHeuermann committed Nov 11, 2022
1 parent 149d2cf commit 3047cde
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 39 deletions.
7 changes: 1 addition & 6 deletions OMCompiler/Compiler/Script/CevalScriptBackend.mo
Expand Up @@ -4052,12 +4052,7 @@ algorithm
end if;

// Check flag fmiFlags if we need additional 3rdParty runtime libs and files
fmiFlagsList := Flags.getConfigStringList(Flags.FMI_FLAGS);
if listLength(fmiFlagsList) >= 1 and not stringEqual(List.first(fmiFlagsList), "none") then
needs3rdPartyLibs := true;
else
needs3rdPartyLibs := false;
end if;
needs3rdPartyLibs := SimCodeUtil.cvodeFmiFlagIsSet(SimCodeUtil.createFMISimulationFlags(false));

// Use CMake on Windows when cross-compiling with docker
_ := match (Flags.getConfigString(Flags.FMU_CMAKE_BUILD), needs3rdPartyLibs)
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/SimCode/SimCode.mo
Expand Up @@ -715,7 +715,7 @@ public uniontype FmiSimulationFlags
end FMI_SIMULATION_FLAGS_FILE;
end FmiSimulationFlags;

constant FmiSimulationFlags defaultFmiSimulationFlags = FMI_SIMULATION_FLAGS({("solver","euler")});
constant FmiSimulationFlags defaultFmiSimulationFlags = FMI_SIMULATION_FLAGS({("s","euler")});

annotation(__OpenModelica_Interface="backend");
end SimCode;
11 changes: 3 additions & 8 deletions OMCompiler/Compiler/SimCode/SimCodeMain.mo
Expand Up @@ -845,9 +845,8 @@ algorithm
cminpack_sources := {};
end if;

// Check if the sundials files are needed. Shouldn't this actually check what the flags are
// instead of just checking if flags are set only?
if isSome(simCode.fmiSimulationFlags) then
// Check if the sundials files are needed
if SimCodeUtil.cvodeFmiFlagIsSet(simCode.fmiSimulationFlags) then
// The sundials headers are in the include directory.
copyFiles(RuntimeSources.sundials_headers, source=install_include_omc_dir, destination=fmu_tmp_sources_dir);
copyFiles(RuntimeSources.simrt_c_sundials_sources, source=install_fmu_sources_dir, destination=fmu_tmp_sources_dir);
Expand Down Expand Up @@ -924,13 +923,9 @@ algorithm
Error.addCompilerError("Unsupported value " + Flags.getConfigString(Flags.FMU_RUNTIME_DEPENDS) + "for compiler flag 'fmuRuntimeDepends'.");
then();
end match;
if isSome(simCode.fmiSimulationFlags) then
cmakelistsStr := System.stringReplace(cmakelistsStr, "@WITH_SUNDIALS@", ";WITH_SUNDIALS");
else
cmakelistsStr := System.stringReplace(cmakelistsStr, "@WITH_SUNDIALS@", "");
end if;

// Add external libraries and includes
cmakelistsStr := System.stringReplace(cmakelistsStr, "@NEED_CVODE@", SimCodeUtil.getCmakeSundialsLinkCode(simCode.fmiSimulationFlags));
cmakelistsStr := System.stringReplace(cmakelistsStr, "@FMU_ADDITIONAL_LIBS@", SimCodeUtil.getCmakeLinkLibrariesCode(simCode.makefileParams.libs));
cmakelistsStr := System.stringReplace(cmakelistsStr, "@FMU_ADDITIONAL_INCLUDES@", SimCodeUtil.make2CMakeInclude(simCode.makefileParams.includes));

Expand Down
75 changes: 66 additions & 9 deletions OMCompiler/Compiler/SimCode/SimCodeUtil.mo
Expand Up @@ -13706,6 +13706,7 @@ public function createFMISimulationFlags
"Function reads FMI simulation flags from user input --fmiFlags
and creates FmiSimulationFlags record for code generation.
Author: AnHeuermann"
input Boolean printWarning = true;
output Option<SimCode.FmiSimulationFlags> fmiSimulationFlags;
protected
list<String> fmiFlagsList;
Expand All @@ -13730,7 +13731,7 @@ algorithm
fmiSimulationFlags := SOME(SimCode.defaultFmiSimulationFlags);

// User supplied file
// --fmiFlags=none
// --fmiFlags=path/to/*.json
elseif listLength(fmiFlagsList) == 1 and stringEqual( List.last(Util.stringSplitAtChar(List.first(fmiFlagsList),".")) , "json" ) then
pathToFile := List.first(fmiFlagsList);
if System.regularFileExists(pathToFile) then
Expand All @@ -13740,8 +13741,10 @@ algorithm
fmiSimulationFlags := SOME(SimCode.FMI_SIMULATION_FLAGS_FILE(path=Util.absoluteOrRelative(pathToFile)));
return;
else
msg := "Could not find file \"" + pathToFile + "\nIgnoring \"--fmiFlags=" + pathToFile + "\" and using default setting.\n";
Error.addCompilerWarning(msg);
if printWarning then
msg := "Could not find file \"" + pathToFile + "\nIgnoring \"--fmiFlags=" + pathToFile + "\" and using default setting.\n";
Error.addCompilerWarning(msg);
end if;
fmiSimulationFlags := SOME(SimCode.defaultFmiSimulationFlags);
return;
end if;
Expand All @@ -13753,8 +13756,10 @@ algorithm
// Check each flag
tmpSplitted := Util.stringSplitAtChar(flag,":");
if not listLength(tmpSplitted) == 2 then
msg := "Can't process flag \"" + flag + "\".\nSeperate flag name and flag value with \":\".\n";
Error.addCompilerWarning(msg);
if printWarning then
msg := "Can't process flag \"" + flag + "\".\nSeperate flag name and flag value with \":\".\n";
Error.addCompilerWarning(msg);
end if;
fmiSimulationFlags := SOME(SimCode.defaultFmiSimulationFlags);
return;
end if;
Expand All @@ -13763,12 +13768,16 @@ algorithm
// Save value
if stringEqual(tmpName, "s") then
if not stringEqual(tmpValue, "euler") and not stringEqual(tmpValue, "cvode") then
msg := "Unknown value \"" + tmpValue + "\" for flag \"s\".";
Error.addCompilerWarning(msg);
if printWarning then
msg := "Unknown value \"" + tmpValue + "\" for flag \"s\".";
Error.addCompilerWarning(msg);
end if;
end if;
else
msg := "Adding unknown FMU simulation flag \"" + tmpName + "\" .";
Error.addCompilerWarning(msg);
if printWarning then
msg := "Adding unknown FMU simulation flag \"" + tmpName + "\" .";
Error.addCompilerWarning(msg);
end if;
end if;
nameValueTuples := (tmpName, tmpValue) :: nameValueTuples;
end for;
Expand Down Expand Up @@ -15604,6 +15613,54 @@ algorithm
end for;
end getCmakeLinkLibrariesCode;

public function getCmakeSundialsLinkCode
"Code for FMU CMakeLists.txt to specify if CVODE is needed."
input Option<SimCode.FmiSimulationFlags> fmiSimulationFlags;
output String code = "";
algorithm
if not cvodeFmiFlagIsSet(fmiSimulationFlags) then
code := "set(NEED_CVODE FALSE)";
else
code := "set(NEED_CVODE TRUE)\n" +
"set(CVODE_DIRECTORY \"" + Settings.getInstallationDirectoryPath() + "/lib/omc\")";
end if;
end getCmakeSundialsLinkCode;

public function cvodeFmiFlagIsSet
"Checks if s:cvode is part of FMI_FLAGS.
If a *.json exists we don't check and assume cvode will be needed at some point."
input Option<SimCode.FmiSimulationFlags> fmiSimulationFlags;
output Boolean needsCvode = false;
algorithm
_ := match fmiSimulationFlags
local
list<tuple<String,String>> nameValueTuples;
String setting, value;
String configFile;
String fileContent;
case SOME(SimCode.FMI_SIMULATION_FLAGS(nameValueTuples))
algorithm
if listLength(nameValueTuples) >= 1 then
for tpl in nameValueTuples loop
(setting, value) := tpl;
if stringEqual(setting, "s") and stringEqual(value, "cvode") then
needsCvode := true;
break;
end if;
end for;
end if;
then();
case SOME(SimCode.FMI_SIMULATION_FLAGS_FILE(configFile))
algorithm
fileContent := System.readFile(configFile);
if not -1 == System.stringFind(fileContent, "\"cvode\"") then
needsCvode := true;
end if;
then();
else then();
end match;
end cvodeFmiFlagIsSet;

public function make2CMakeInclude
"Convert makefile include directories to CMake include directories"
input list<String> includes;
Expand Down
1 change: 0 additions & 1 deletion OMCompiler/Compiler/Template/CodegenFMU.tpl
Expand Up @@ -1305,7 +1305,6 @@ template settingsfile(SimCode simCode)
#define OMC_MODEL_PREFIX "<%modelNamePrefix(simCode)%>"
#define OMC_MINIMAL_RUNTIME 1
#define OMC_FMI_RUNTIME 1
<%if isSome(fmiSimulationFlags) then "#define WITH_SUNDIALS 1"%>
#endif
>>
end settingsfile;
Expand Down
11 changes: 0 additions & 11 deletions OMCompiler/SimulationRuntime/c/simulation/solver/sundials_error.c
Expand Up @@ -949,15 +949,4 @@ void kinsolInfoHandlerFunction(const char *module, const char *function,
throwStreamPrint(NULL, "No sundials/kinsol support activated.");
}

/**
* @brief Function not supported without WITH_SUNDIALS
*
* @param A
* @param name
* @param logLevel
*/
void sundialsPrintSparseMatrix(SUNMatrix A, const char* name, const int logLevel) {
throwStreamPrint(NULL, "No sundials/kinsol support activated.");
}

#endif /* WITH_SUNDIALS */
Expand Up @@ -5,6 +5,9 @@ set(FMU_NAME @FMU_NAME_IN@)

project(${FMU_NAME})

# CVODE needed
@NEED_CVODE@

# Test if RUNTIME_DEPENDENCIES is needed and available
set(RUNTIME_DEPENDENCIES_LEVEL @RUNTIME_DEPENDENCIES_LEVEL@)
if(${CMAKE_VERSION} VERSION_LESS "3.21" AND NOT ${RUNTIME_DEPENDENCIES_LEVEL} STREQUAL "none")
Expand Down Expand Up @@ -36,7 +39,10 @@ file(GLOB_RECURSE FMU_RUNTIME_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/external_solve
${CMAKE_CURRENT_SOURCE_DIR}/meta/*.c
${CMAKE_CURRENT_SOURCE_DIR}/simulation/*.c
${CMAKE_CURRENT_SOURCE_DIR}/util/*.c)

if (NOT ${NEED_CVODE})
list(REMOVE_ITEM FMU_RUNTIME_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/simulation/solver/sundials_error.c
${CMAKE_CURRENT_SOURCE_DIR}/simulation/solver/cvode_solver.c)
endif()
file(GLOB FMU_GENERATED_MODEL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c)

if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
Expand Down Expand Up @@ -78,12 +84,26 @@ if(NOT ${CMAKE_VERSION} VERSION_LESS "3.13")
endif()
target_link_libraries(${FMU_NAME} PRIVATE m Threads::Threads)
@FMU_ADDITIONAL_LIBS@
if(${NEED_CVODE})
find_library(SUNDIALS_CVODE_LIBRARY sundials_cvode
PATHS ${CVODE_DIRECTORY}
NO_DEFAULT_PATH)
find_library(SUNDIALS_NVSERIAL_LIBRARY sundials_nvecserial
PATHS ${CVODE_DIRECTORY}
NO_DEFAULT_PATH)
target_link_libraries(${FMU_NAME} PRIVATE ${SUNDIALS_CVODE_LIBRARY} ${SUNDIALS_NVSERIAL_LIBRARY})
target_include_directories(${FMU_NAME} PRIVATE sundials)
set(WITH_SUNDIALS ";WITH_SUNDIALS")
message(STATUS "CVODE: ${SUNDIALS_CVODE_LIBRARY} ${SUNDIALS_NVSERIAL_LIBRARY}")
else()
message(STATUS "CVODE: Not linked")
endif()

target_include_directories(${FMU_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${FMU_NAME} PRIVATE ${FMI_INTERFACE_HEADER_FILES_DIRECTORY}
sundials@FMU_ADDITIONAL_INCLUDES@)

target_compile_definitions(${FMU_NAME} PRIVATE OMC_MINIMAL_RUNTIME=1;OMC_FMI_RUNTIME=1;CMINPACK_NO_DLL)
target_compile_definitions(${FMU_NAME} PRIVATE OMC_MINIMAL_RUNTIME=1;OMC_FMI_RUNTIME=1;CMINPACK_NO_DLL${WITH_SUNDIALS})

if(RUNTIME_DEPENDENCIES_LEVEL STREQUAL "all")
install(TARGETS ${FMU_NAME}
Expand Down
Expand Up @@ -97,7 +97,7 @@ val(v, 1.0, "BouncingBallFMI20_res.mat"); getErrorString();
// 0
// ""
// "{
// \"solver\" : \"euler\"
// \"s\" : \"euler\"
// }"
// ""
// true
Expand Down

0 comments on commit 3047cde

Please sign in to comment.