Skip to content

Commit

Permalink
[FMI] Adding CVODE to 2.0 CS export
Browse files Browse the repository at this point in the history
Incoved by FMI simulation flag `--fmiFlags=s:cvode`.

  - Add source code files to FMU:
    - Adding cvode_solver.c and cvode_solver.h.
    - Adding SUNDIALS CVODE headers to FMU.
    - Changed Makefiles and configure to compile
      CVODE into binaries.
  - New initialization and deinitialization to handle
    different solver methods.
  - New integrator step function to be called in fmi2DoStep.
  - New tests for static and dynamic FMUs with CVODE.

Co-authored-by: Karim Abdelhak <karim.abdelhak@fh-bielefeld.de>
  • Loading branch information
2 people authored and adrpo committed Jun 11, 2020
1 parent b9dfeac commit 1014b60
Show file tree
Hide file tree
Showing 22 changed files with 864 additions and 336 deletions.
65 changes: 53 additions & 12 deletions OMCompiler/Compiler/Script/CevalScriptBackend.mo
Expand Up @@ -3541,30 +3541,41 @@ algorithm
end callTranslateModel;

protected function configureFMU
"Configures Makefile.in of FMU for traget configuration."
input String platform;
input String fmutmp;
input String logfile;
input Boolean isWindows;
input Boolean needs3rdPartyLibs;
protected
String CC, CFLAGS, LDFLAGS, makefileStr, container, host, nozip, path1, path2,
String CC, CFLAGS, CPPFLAGS, LDFLAGS, SUNDIALS, makefileStr, container, host, nozip, path1, path2,
dir=fmutmp+"/sources/", cmd="",
quote="'",
dquote = if isWindows then "\"" else "'",
includeDefaultFmi, volumeID, cidFile, containerID;
list<String> rest;
Boolean finishedBuild;
Integer uid, status;
Boolean verbose = false;
algorithm
includeDefaultFmi := dquote + Settings.getInstallationDirectoryPath() + "/include/omc/c/fmi" + dquote;

CC := System.getCCompiler();
CFLAGS := "-Os "+System.stringReplace(System.getCFlags(),"${MODELICAUSERCFLAGS}","");
LDFLAGS := ("-L"+dquote+Settings.getInstallationDirectoryPath()+"/lib/"+Autoconf.triple+"/omc"+dquote+" "+
"-Wl,-rpath,"+dquote+Settings.getInstallationDirectoryPath()+"/lib/"+Autoconf.triple+"/omc"+dquote+" "+
System.getLDFlags()+" ");
"-Wl,-rpath,"+dquote+Settings.getInstallationDirectoryPath()+"/lib/"+Autoconf.triple+"/omc"+dquote+" "+
System.getLDFlags()+" ");
CPPFLAGS := "-I" + includeDefaultFmi + " -DOMC_FMI_RUNTIME=1";
if needs3rdPartyLibs then
SUNDIALS := "1";
CPPFLAGS := CPPFLAGS + " -DWITH_SUNDIALS=1" + " -Isundials";
else
SUNDIALS := "";
end if;
if System.regularFileExists(logfile) then
System.removeFile(logfile);
end if;
nozip := Autoconf.make+" -j"+intString(Config.noProc()) + " nozip";
includeDefaultFmi := dquote + Settings.getInstallationDirectoryPath() + "/include/omc/c/fmi" + dquote;
finishedBuild := match Util.stringSplitAtChar(platform, " ")
case {"dynamic"}
algorithm
Expand All @@ -3577,8 +3588,9 @@ algorithm
makefileStr := System.stringReplace(makefileStr, "@DLLEXT@", Autoconf.dllExt);
makefileStr := System.stringReplace(makefileStr, "@NEED_RUNTIME@", "");
makefileStr := System.stringReplace(makefileStr, "@NEED_DGESV@", "");
makefileStr := System.stringReplace(makefileStr, "@NEED_SUNDIALS@", "");
makefileStr := System.stringReplace(makefileStr, "@FMIPLATFORM@", System.modelicaPlatform());
makefileStr := System.stringReplace(makefileStr, "@CPPFLAGS@", "-I" + includeDefaultFmi + " -DOMC_SIM_SETTINGS_CMDLINE -DOMC_FMI_RUNTIME=1");
makefileStr := System.stringReplace(makefileStr, "@CPPFLAGS@", CPPFLAGS + " -DOMC_SIM_SETTINGS_CMDLINE");
makefileStr := System.stringReplace(makefileStr, "@LIBTYPE_DYNAMIC@", "1");
makefileStr := System.stringReplace(makefileStr, "@BSTATIC@", Autoconf.bstatic);
makefileStr := System.stringReplace(makefileStr, "@BDYNAMIC@", Autoconf.bdynamic);
Expand All @@ -3598,8 +3610,9 @@ algorithm
makefileStr := System.stringReplace(makefileStr, "@DLLEXT@", Autoconf.dllExt);
makefileStr := System.stringReplace(makefileStr, "@NEED_RUNTIME@", "");
makefileStr := System.stringReplace(makefileStr, "@NEED_DGESV@", "");
makefileStr := System.stringReplace(makefileStr, "@NEED_SUNDIALS@", SUNDIALS);
makefileStr := System.stringReplace(makefileStr, "@FMIPLATFORM@", System.modelicaPlatform());
makefileStr := System.stringReplace(makefileStr, "@CPPFLAGS@", "-DOMC_MINIMAL_RUNTIME=1 -DCMINPACK_NO_DLL=1 -I" + includeDefaultFmi);
makefileStr := System.stringReplace(makefileStr, "@CPPFLAGS@", CPPFLAGS + " -DCMINPACK_NO_DLL=1");
makefileStr := System.stringReplace(makefileStr, "@LIBTYPE_DYNAMIC@", "1");
makefileStr := System.stringReplace(makefileStr, "@BSTATIC@", Autoconf.bstatic);
makefileStr := System.stringReplace(makefileStr, "@BDYNAMIC@", Autoconf.bdynamic);
Expand All @@ -3610,8 +3623,9 @@ algorithm
then false;
case {_}
algorithm
cmd := "cd \"" + fmutmp + "/sources\" && ./configure --host="+quote+platform+quote+" CFLAGS="+quote+"-Os"+quote+" CPPFLAGS="+quote+"-I"+includeDefaultFmi+quote+" LDFLAGS= && " +
nozip;
cmd := "cd \"" + fmutmp + "/sources\" && ./configure --host="+quote+platform+quote+
" CFLAGS=" + quote + "-Os" + quote + " CPPFLAGS=" + quote + CPPFLAGS + quote+
" LDFLAGS= && " + nozip;
if 0 <> System.systemCall(cmd, outFile=logfile) then
Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {System.readFile(logfile)});
System.removeFile(logfile);
Expand All @@ -3627,6 +3641,8 @@ algorithm
if 0 <> System.systemCall(cmd, outFile=logfile) then
Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {cmd + " failed:\n" + System.readFile(logfile)});
fail();
elseif verbose then
print(cmd + "\n" + System.readFile(logfile) +"\n");
end if;
cidFile := fmutmp+".cidfile";
if System.regularFileExists(cidFile) then
Expand All @@ -3639,6 +3655,8 @@ algorithm
// Cleanup
System.systemCall("docker volume rm " + volumeID);
fail();
elseif verbose then
print(cmd + "\n" + System.readFile(logfile) +"\n");
end if;
containerID := System.trim(System.readFile(cidFile));
System.removeFile(cidFile);
Expand All @@ -3650,6 +3668,8 @@ algorithm
System.systemCall("docker rm " + containerID);
System.systemCall("docker volume rm " + volumeID);
fail();
elseif verbose then
print(cmd + "\n" + System.readFile(logfile) +"\n");
end if;
// Copy the FMI headers to the container
cmd := "docker cp "+includeDefaultFmi+" "+containerID+":/data/fmiInclude";
Expand All @@ -3659,6 +3679,8 @@ algorithm
System.systemCall("docker rm " + containerID);
System.systemCall("docker volume rm " + volumeID);
fail();
elseif verbose then
print(cmd + "\n" + System.readFile(logfile) +"\n");
end if;
cmd := "docker run "+(if uid<>0 then "--user " + String(uid) else "")+" --rm -w /fmu -v "+volumeID+":/fmu "+stringDelimitList(rest," ")+ " sh -c " + dquote +
"cd " + dquote + "/fmu/" + System.basename(fmutmp) + "/sources" + dquote + " && " +
Expand All @@ -3671,12 +3693,16 @@ algorithm
System.systemCall("docker rm " + containerID);
System.systemCall("docker volume rm " + volumeID);
fail();
elseif verbose then
print(cmd + "\n" + System.readFile(logfile) +"\n");
end if;
// Copy the files back from the volume (via the container) to the filesystem
cmd := "docker cp " + quote + containerID + ":/data/" + fmutmp + quote + " .";
if 0 <> System.systemCall(cmd, outFile=logfile) then
Error.addMessage(Error.SIMULATOR_BUILD_ERROR, {cmd + ":\n" + System.readFile(logfile)});
fail();
elseif verbose then
print(cmd + "\n" + System.readFile(logfile) +"\n");
end if;
// Cleanup
System.systemCall("docker rm " + containerID);
Expand All @@ -3703,8 +3729,9 @@ algorithm
end if;
end configureFMU;

protected function buildModelFMU " author: Frenkel TUD
translates a model into cpp code and writes also a makefile"
protected function buildModelFMU
" Author: Frenkel TUD
Translates a model into target code and writes also a makefile."
input FCore.Cache inCache;
input FCore.Graph inEnv;
input Absyn.Path className "path for the model";
Expand All @@ -3723,7 +3750,10 @@ protected
SimCode.SimulationSettings simSettings;
list<String> libs;
Boolean isWindows;
list<String> fmiFlagsList;
Boolean needs3rdPartyLibs;
String FMUType = inFMUType;
Boolean debug = false;
algorithm
cache := inCache;
if not FMI.checkFMIVersion(FMUVersion) then
Expand Down Expand Up @@ -3800,9 +3830,18 @@ algorithm
return;
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;

// Configure the FMU Makefile
for platform in platforms loop
configureLogFile := System.realpath(fmutmp)+"/resources/"+System.stringReplace(listGet(Util.stringSplitAtChar(platform," "),1),"/","-")+".log";
configureFMU(platform, fmutmp, configureLogFile, isWindows);
configureFMU(platform, fmutmp, configureLogFile, isWindows, needs3rdPartyLibs);
if Flags.getConfigEnum(Flags.FMI_FILTER) == Flags.FMI_BLACKBOX then
System.removeFile(configureLogFile);
end if;
Expand All @@ -3827,7 +3866,9 @@ algorithm
fail();
end if;

System.removeDirectory(fmutmp);
if not debug then
System.removeDirectory(fmutmp);
end if;
end buildModelFMU;

protected function buildEncryptedPackage
Expand Down
10 changes: 5 additions & 5 deletions OMCompiler/Compiler/SimCode/SimCode.mo
Expand Up @@ -619,17 +619,17 @@ public uniontype FmiModelStructure
end FmiModelStructure;

public uniontype FmiSimulationFlags
record FMISIMULATIONFLAGS
record FMI_SIMULATION_FLAGS
String solver;
String nonLinearSolver;
end FMISIMULATIONFLAGS;
end FMI_SIMULATION_FLAGS;

record FMISIMULATIONFLAGSFILE
record FMI_SIMULATION_FLAGS_FILE
String path;
end FMISIMULATIONFLAGSFILE;
end FMI_SIMULATION_FLAGS_FILE;
end FmiSimulationFlags;

constant FmiSimulationFlags defaultFmiSimulationFlags = FMISIMULATIONFLAGS(solver="euler", nonLinearSolver="homotopy");
constant FmiSimulationFlags defaultFmiSimulationFlags = FMI_SIMULATION_FLAGS(solver="euler", nonLinearSolver="homotopy");

annotation(__OpenModelica_Interface="backend");
end SimCode;
117 changes: 63 additions & 54 deletions OMCompiler/Compiler/SimCode/SimCodeMain.mo
Expand Up @@ -703,8 +703,9 @@ algorithm
String fmutmp;
String guid;
Boolean b;
Boolean needSundials = false;
String fileprefix;
list<String> allFiles, sourceFiles, defaultFiles, extraFiles, runtimeFiles, dgesvFiles;
list<String> allFiles, sourceFiles, defaultFiles, extraFiles, runtimeFiles, dgesvFiles, sundialsFiles;
SimCode.VarInfo varInfo;
case (SimCode.SIMCODE(),"C")
algorithm
Expand Down Expand Up @@ -742,12 +743,12 @@ algorithm
local
SimCode.FmiSimulationFlags fmiSimFlags;
String pathToFlagsJson;
case SOME(fmiSimFlags as SimCode.FMISIMULATIONFLAGSFILE(path=pathToFlagsJson))
case SOME(fmiSimFlags as SimCode.FMI_SIMULATION_FLAGS_FILE(path=pathToFlagsJson))
algorithm
needSundials := true;
if 0 <> System.systemCall("cp -rf \"" + pathToFlagsJson + "\" \"" + fmutmp + "/resources/" + simCode.fileNamePrefix+"_flags.json\"") then
Error.addInternalError("Failed to copy " + pathToFlagsJson + " to " + fmutmp + "/resources/" + simCode.fileNamePrefix + "_flags.json", sourceInfo());
end if;
listAppend(simCode.modelInfo.resourcePaths, {pathToFlagsJson});
then();
else
then();
Expand All @@ -774,6 +775,13 @@ algorithm
allFiles := {};
allFiles := listAppend(RuntimeSources.commonHeaders, listAppend(RuntimeSources.commonFiles, allFiles));
allFiles := listAppend(if FMUVersion=="1.0" then RuntimeSources.fmi1Files else RuntimeSources.fmi2Files, allFiles);
if isSome(simCode.fmiSimulationFlags) then
allFiles := listAppend(RuntimeSources.external3rdPartyFiles, allFiles);
sundialsFiles := RuntimeSources.cvodeRuntimeFiles;
allFiles := listAppend(sundialsFiles, allFiles);
else
sundialsFiles := {""};
end if;
if varInfo.numLinearSystems > 0 then
allFiles := listAppend(RuntimeSources.lsFiles, allFiles);
end if;
Expand All @@ -798,7 +806,7 @@ algorithm
Tpl.tplNoret(function CodegenFMU.translateModel(in_a_FMUVersion=FMUVersion, in_a_FMUType=FMUType, in_a_sourceFiles=sourceFiles), simCode);
extraFiles := SimCodeUtil.getFunctionIndex();
copyFiles(listAppend(dgesvFiles, allFiles), source=Settings.getInstallationDirectoryPath() + "/include/omc/c/", destination=fmutmp+"/sources/");
Tpl.closeFile(Tpl.tplCallWithFailErrorNoArg(function CodegenFMU.fmuMakefile(a_target=Config.simulationCodeTarget(), a_simCode=simCode, a_FMUVersion=FMUVersion, a_sourceFiles=listAppend(extraFiles, defaultFiles), a_dgesvObjectFiles=list(System.stringReplace(f,".c",".o") for f guard Util.endsWith(f, ".c") in dgesvFiles), a_runtimeObjectFiles=list(System.stringReplace(f,".c",".o") for f in runtimeFiles)),
Tpl.closeFile(Tpl.tplCallWithFailErrorNoArg(function CodegenFMU.fmuMakefile(a_target=Config.simulationCodeTarget(), a_simCode=simCode, a_FMUVersion=FMUVersion, a_sourceFiles=listAppend(extraFiles, defaultFiles), a_runtimeObjectFiles=list(System.stringReplace(f,".c",".o") for f in runtimeFiles), a_dgesvObjectFiles=list(System.stringReplace(f,".c",".o") for f guard Util.endsWith(f, ".c") in dgesvFiles), a_sundialsObjectFiles=list(System.stringReplace(f,".c",".o") for f guard Util.endsWith(f, ".c") in sundialsFiles)),
txt=Tpl.redirectToFile(Tpl.emptyTxt, simCode.fileNamePrefix+".fmutmp/sources/Makefile.in")));
Tpl.closeFile(Tpl.tplCallWithFailError(CodegenFMU.settingsfile, simCode,
txt=Tpl.redirectToFile(Tpl.emptyTxt, simCode.fileNamePrefix+".fmutmp/sources/omc_simulation_settings.h")));
Expand Down Expand Up @@ -1415,56 +1423,57 @@ algorithm
// The updated variable 'numEquations' (by SimCodeUtil.addNumEqns) is not even used in createCrefToSimVarHT :/
// crefToSimVarHT := SimCodeUtil.createCrefToSimVarHT(modelInfo);

simCode := SimCode.SIMCODE(modelInfo,
{}, // Set by the traversal below...
recordDecls,
includes,
{},
{},
{},
{},
{},
initialEquations,
{},
removedInitialEquations,
startValueEquations,
nominalValueEquations,
minValueEquations,
maxValueEquations,
parameterEquations,
{},
{},
{},
{},
{},
{},
{},
zeroCrossings,
relations,
timeEvents,
discreteModelVars,
extObjInfo,
makefileParams,
SimCode.DELAYED_EXPRESSIONS(delayedExps, maxDelayedExpIndex),
SymbolicJacs,
simSettingsOpt,
filenamePrefix,
"",
"",
HpcOmSimCode.emptyHpcomData,
AvlTreeCRToInt.EMPTY(),
HashTableCrIListArray.emptyHashTable(),
HashTableCrILst.emptyHashTable(),
crefToSimVarHT,
HashTable.emptyHashTable(),
NONE(),
NONE(),
NONE(),
SimCode.emptyPartitionData,
daeModeData,
{},
NONE()
);
simCode := SimCode.SIMCODE(
modelInfo = modelInfo,
literals = {}, // Set by the traversal below...
recordDecls = recordDecls,
externalFunctionIncludes = includes,
localKnownVars = {},
allEquations = {},
odeEquations = {},
algebraicEquations = {},
clockedPartitions = {},
initialEquations = initialEquations,
initialEquations_lambda0 = {},
removedInitialEquations = removedInitialEquations,
startValueEquations = startValueEquations,
nominalValueEquations = nominalValueEquations,
minValueEquations = minValueEquations,
maxValueEquations = maxValueEquations,
parameterEquations = parameterEquations,
removedEquations = {},
algorithmAndEquationAsserts = {},
equationsForZeroCrossings = {},
jacobianEquations = {},
stateSets = {},
constraints = {},
classAttributes = {},
zeroCrossings = zeroCrossings,
relations = relations,
timeEvents = timeEvents,
discreteModelVars = discreteModelVars,
extObjInfo = extObjInfo,
makefileParams = makefileParams,
delayedExps = SimCode.DELAYED_EXPRESSIONS(delayedExps, maxDelayedExpIndex),
jacobianMatrixes = SymbolicJacs,
simulationSettingsOpt = simSettingsOpt,
fileNamePrefix = filenamePrefix,
fullPathPrefix = "",
fmuTargetName = "",
hpcomData = HpcOmSimCode.emptyHpcomData,
valueReferences = AvlTreeCRToInt.EMPTY(),
varToArrayIndexMapping = HashTableCrIListArray.emptyHashTable(),
varToIndexMapping = HashTableCrILst.emptyHashTable(),
crefToSimVarHT = crefToSimVarHT,
crefToClockIndexHT = HashTable.emptyHashTable(),
backendMapping = NONE(),
modelStructure = NONE(),
fmiSimulationFlags = NONE(),
partitionData = SimCode.emptyPartitionData,
daeModeData = daeModeData,
inlineEquations = {},
omsiData = NONE()
);

(simCode, (_, _, lits)) := SimCodeUtil.traverseExpsSimCode(simCode, SimCodeFunctionUtil.findLiteralsHelper, literals);
simCode.literals := listReverse(lits);
Expand Down

0 comments on commit 1014b60

Please sign in to comment.