Skip to content

Commit

Permalink
Extend FMI2 export with DiscreteState
Browse files Browse the repository at this point in the history
So far clocked Modelica states are exported as discrete FMU states.
Strict FMI 2.0 ompatibility is maintained for models without
synchronous features; no DiscreteState appears in this case.
  • Loading branch information
rfranke committed Oct 10, 2015
1 parent 0a6d92e commit b0d49ab
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 25 deletions.
4 changes: 4 additions & 0 deletions Compiler/SimCode/SerializeModelInfo.mo
Expand Up @@ -941,6 +941,10 @@ algorithm
equation
File.write(file,"dummy state");
then ();
case BackendDAE.CLOCKED_STATE()
equation
File.write(file,"clocked state");
then ();
case BackendDAE.DISCRETE()
equation
File.write(file,"discrete");
Expand Down
7 changes: 7 additions & 0 deletions Compiler/SimCode/SimCode.mo
Expand Up @@ -629,6 +629,12 @@ public uniontype FmiDerivatives
end FMIDERIVATIVES;
end FmiDerivatives;

public uniontype FmiDiscreteStates
record FMIDISCRETESTATES
list<FmiUnknown> fmiUnknownsList;
end FMIDISCRETESTATES;
end FmiDiscreteStates;

public uniontype FmiInitialUnknowns
record FMIINITIALUNKNOWNS
list<FmiUnknown> fmiUnknownsList;
Expand All @@ -639,6 +645,7 @@ public uniontype FmiModelStructure
record FMIMODELSTRUCTURE
FmiOutputs fmiOutputs;
FmiDerivatives fmiDerivatives;
FmiDiscreteStates fmiDiscreteStates;
FmiInitialUnknowns fmiInitialUnknowns;
end FMIMODELSTRUCTURE;
end FmiModelStructure;
Expand Down
30 changes: 27 additions & 3 deletions Compiler/SimCode/SimCodeUtil.mo
Expand Up @@ -11306,8 +11306,8 @@ public function createFMIModelStructure
protected
list<tuple<DAE.ComponentRef, list<DAE.ComponentRef>>> spTA, spTB;
list<tuple<Integer, list<Integer>>> sparseInts;
list<SimCode.FmiUnknown> derivatives, outputs;
list<SimCodeVar.SimVar> varsA, varsB;
list<SimCode.FmiUnknown> derivatives, outputs, discreteStates;
list<SimCodeVar.SimVar> varsA, varsB, clockedStates;
SimCode.HashTableCrefToSimVar crefSimVarHT;
list<DAE.ComponentRef> diffCrefsA, diffedCrefsA, derdiffCrefsA;
list<DAE.ComponentRef> diffCrefsB, diffedCrefsB;
Expand Down Expand Up @@ -11363,13 +11363,37 @@ algorithm
//print("-- sorted vars for CD\n");

outputs := translateSparsePatterInts2FMIUnknown(sparseInts, {});

//TODO: create DiscreteStates with dependencies, like derivatives
clockedStates := List.filterOnTrue(inModelInfo.vars.algVars, isClockedStateSimVar);
discreteStates := List.map(clockedStates, createFmiUnknownFromSimVar);

//print("-- finished createFMIModelStructure\n");
outFmiModelStructure := SOME(SimCode.FMIMODELSTRUCTURE(SimCode.FMIOUTPUTS(outputs), SimCode.FMIDERIVATIVES(derivatives), SimCode.FMIINITIALUNKNOWNS({})));
outFmiModelStructure := SOME(SimCode.FMIMODELSTRUCTURE(SimCode.FMIOUTPUTS(outputs), SimCode.FMIDERIVATIVES(derivatives), SimCode.FMIDISCRETESTATES(discreteStates), SimCode.FMIINITIALUNKNOWNS({})));
else
outFmiModelStructure := NONE();
end try;
end createFMIModelStructure;

protected function isClockedStateSimVar
"Returns true for state and der(state) variables, false otherwise."
input SimCodeVar.SimVar inVar;
output Boolean outBoolean;
algorithm
outBoolean := match (inVar)
case (SimCodeVar.SIMVAR(varKind = BackendDAE.CLOCKED_STATE(_))) then true;
else false;
end match;
end isClockedStateSimVar;

protected function createFmiUnknownFromSimVar
"create a basic FMIUNKNOWN without dependencies from a SimVar"
input SimCodeVar.SimVar var;
output SimCode.FmiUnknown unknown;
algorithm
unknown := SimCode.FMIUNKNOWN(var.index + 1, {}, {});
end createFmiUnknownFromSimVar;

protected function translateSparsePatterInts2FMIUnknown
"function translates simVar integers to fmi unknowns."
input list<tuple<Integer, list<Integer>>> inSparsePattern;
Expand Down
2 changes: 1 addition & 1 deletion Compiler/Template/CodegenFMU1.tpl
Expand Up @@ -64,7 +64,7 @@ case SIMCODE(__) then
<%fmiModelDescriptionAttributes(simCode,guid)%>>
<%fmiTypeDefinitions(modelInfo, "1.0")%>
<%DefaultExperiment(simulationSettingsOpt)%>
<%fmiModelVariables(modelInfo, "1.0")%>
<%fmiModelVariables(simCode, "1.0")%>
<%if isFMICSType(FMUType) then Implementation()%>
</fmiModelDescription>
>>
Expand Down
2 changes: 1 addition & 1 deletion Compiler/Template/CodegenFMU2.tpl
Expand Up @@ -78,7 +78,7 @@ case SIMCODE(__) then
<Category name="logFmi2Call" />
</LogCategories>
<%DefaultExperiment(simulationSettingsOpt)%>
<%fmiModelVariables(modelInfo, "2.0")%>
<%fmiModelVariables(simCode, "2.0")%>
<%ModelStructureHelper(modelStructure)%>
</fmiModelDescription>
>>
Expand Down
62 changes: 43 additions & 19 deletions Compiler/Template/CodegenFMUCommon.tpl
Expand Up @@ -64,69 +64,71 @@ case SIMCODE(__) then
>>
end ModelExchange;

template fmiModelVariables(ModelInfo modelInfo, String FMUVersion)
template fmiModelVariables(SimCode simCode, String FMUVersion)
"Generates code for ModelVariables file for FMU target."
::=
match simCode
case SIMCODE(modelInfo=modelInfo) then
match modelInfo
case MODELINFO(vars=SIMVARS(stateVars=stateVars)) then
<<
<ModelVariables>
<%System.tmpTickReset(0)%>
<%vars.stateVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.derivativeVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.algVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.discreteAlgVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.paramVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.aliasVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%System.tmpTickReset(0)%>
<%vars.intAlgVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.intParamVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.intAliasVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%System.tmpTickReset(0)%>
<%vars.boolAlgVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.boolParamVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.boolAliasVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%System.tmpTickReset(0)%>
<%vars.stringAlgVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.stringParamVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%vars.stringAliasVars |> var =>
ScalarVariable(stateVars, var, FMUVersion)
ScalarVariable(simCode, stateVars, var, FMUVersion)
;separator="\n"%>
<%System.tmpTickReset(0)%>
<%externalFunctions(modelInfo)%>
</ModelVariables>
>>
end fmiModelVariables;

template ScalarVariable(list<SimVar> stateVars, SimVar simVar, String FMUVersion)
template ScalarVariable(SimCode simCode, list<SimVar> stateVars, SimVar simVar, String FMUVersion)
"Generates code for ScalarVariable file for FMU target."
::=
match simVar
Expand All @@ -136,13 +138,16 @@ case SIMVAR(__) then
else if stringEq(crefStr(name),"der($dummy)") then
<<>>
else if isFMIVersion20(FMUVersion) then
//if intGt(getVariableIndex(simVar), 0) then
<<
<!-- Index of variable = "<%getVariableIndex(simVar)%>" -->
<ScalarVariable
<%ScalarVariableAttribute2(simVar)%>>
<%ScalarVariableAttribute2(simCode, simVar)%>>
<%ScalarVariableType2(simVar, stateVars)%>
</ScalarVariable>
>>
//else let valueReference = '<%System.tmpTick()%>'
//<<>>
else
<<
<ScalarVariable
Expand Down Expand Up @@ -302,6 +307,7 @@ case SOME(fmistruct as FMIMODELSTRUCTURE(__)) then
<ModelStructure>
<%ModelStructureOutputs(fmistruct.fmiOutputs)%>
<%ModelStructureDerivatives(fmistruct.fmiDerivatives)%>
<%ModelStructureDiscreteStates(fmistruct.fmiDiscreteStates)%>
<%ModelStructureInitialUnknowns(fmistruct.fmiInitialUnknowns)%>
</ModelStructure>
>>
Expand Down Expand Up @@ -336,6 +342,22 @@ case FMIDERIVATIVES(__) then
>>
end ModelStructureDerivatives;

template ModelStructureDiscreteStates(FmiDiscreteStates fmiDiscreteStates)
"Generates Model Structure DiscreteStates."
::=
match fmiDiscreteStates
case FMIDISCRETESTATES(__) then
if intGt(listLength(fmiUnknownsList), 0) then
<<
<DiscreteStates>
<%ModelStructureUnknowns(fmiUnknownsList)%>
</DiscreteStates>
>>
else
// don't generate if model has no discrete states for FMI 2.0 compatibility
<<>>
end ModelStructureDiscreteStates;

template ModelStructureInitialUnknowns(FmiInitialUnknowns fmiInitialUnknowns)
"Generates Model Structure InitialUnknowns."
::=
Expand Down Expand Up @@ -382,7 +404,7 @@ template FmiUnknownDependenciesKind(list<String> dependenciesKind)
>>
end FmiUnknownDependenciesKind;

template ScalarVariableAttribute2(SimVar simVar)
template ScalarVariableAttribute2(SimCode simCode, SimVar simVar)
"Generates code for ScalarVariable Attribute file for FMU 2.0 target."
::=
match simVar
Expand All @@ -392,13 +414,15 @@ match simVar
let variability = getVariability2(varKind, type_)
let caus = getCausality2(causality, varKind, isValueChangeable)
let initial = getInitialType2(variability, caus, initialValue)
let previous = match varKind case CLOCKED_STATE(__) then '<%getVariableIndex(cref2simvar(previousName, simCode))%>'
<<
name="<%System.stringReplace(crefStrNoUnderscore(name),"$", "_D_")%>"
valueReference="<%valueReference%>"
<%description%>
variability="<%variability%>"
causality="<%caus%>"
<%if boolNot(stringEq(initial, "")) then 'initial="'+initial+'"' %>
<%if boolNot(stringEq(previous, "")) then 'previous="'+previous+'"' %>
>>
end ScalarVariableAttribute2;

Expand Down
2 changes: 1 addition & 1 deletion Compiler/Template/CodegenFMUCpp.tpl
Expand Up @@ -187,7 +187,7 @@ case SIMCODE(__) then
<fmiModelDescription
<%CodegenCppInit.fmiModelDescriptionAttributes(simCode, guid)%>>
<%CodegenFMUCommon.DefaultExperiment(simulationSettingsOpt)%>
<%CodegenFMUCommon.fmiModelVariables(modelInfo,"1.0")%>
<%CodegenFMUCommon.fmiModelVariables(simCode, "1.0")%>
</fmiModelDescription>
>>
end fmiModelDescriptionCpp;
Expand Down
10 changes: 10 additions & 0 deletions Compiler/Template/SimCodeTV.mo
Expand Up @@ -700,6 +700,12 @@ package SimCode
end FMIDERIVATIVES;
end FmiDerivatives;

uniontype FmiDiscreteStates
record FMIDISCRETESTATES
list<FmiUnknown> fmiUnknownsList;
end FMIDISCRETESTATES;
end FmiDiscreteStates;

uniontype FmiInitialUnknowns
record FMIINITIALUNKNOWNS
list<FmiUnknown> fmiUnknownsList;
Expand All @@ -710,6 +716,7 @@ package SimCode
record FMIMODELSTRUCTURE
FmiOutputs fmiOutputs;
FmiDerivatives fmiDerivatives;
FmiDiscreteStates fmiDiscreteStates;
FmiInitialUnknowns fmiInitialUnknowns;
end FMIMODELSTRUCTURE;
end FmiModelStructure;
Expand Down Expand Up @@ -994,6 +1001,9 @@ package BackendDAE
record STATE_DER end STATE_DER;
record DUMMY_DER end DUMMY_DER;
record DUMMY_STATE end DUMMY_STATE;
record CLOCKED_STATE
DAE.ComponentRef previousName "the name of the previous variable";
end CLOCKED_STATE;
record DISCRETE end DISCRETE;
record PARAM end PARAM;
record CONST end CONST;
Expand Down

0 comments on commit b0d49ab

Please sign in to comment.