Skip to content

Commit

Permalink
[FMI] added model structure for discrete states
Browse files Browse the repository at this point in the history
  • Loading branch information
Willi Braun authored and OpenModelica-Hudson committed Mar 6, 2018
1 parent 1453d7d commit d66515a
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 14 deletions.
16 changes: 14 additions & 2 deletions Compiler/BackEnd/BackendDAEUtil.mo
Expand Up @@ -1729,6 +1729,9 @@ algorithm
eqs := system.orderedEqs;
vars := system.orderedVars;
states := BackendVariable.getAllStateVarFromVariables(vars);
if Config.languageStandardAtLeast(Config.LanguageStandard.'3.3') then
states := listAppend(states, BackendVariable.getAllClockedStatesFromVariables(vars));
end if;
for v in states loop
if BackendVariable.isVarOnTopLevelAndOutput(v) then
// generate new output var and add it
Expand Down Expand Up @@ -3047,10 +3050,16 @@ algorithm
(varslst,p) = BackendVariable.getVar(cr, vars);
res = incidenceRowExp1withInput(varslst,p,pa,1);
then (inExp,false,(vars,res));

case (DAE.CALL(path = Absyn.IDENT(name = "previous"),expLst = {DAE.CREF(componentRef = cr)}),(vars,pa))
equation
cr = ComponentReference.makeCrefQual(DAE.previousNamePrefix, DAE.T_REAL_DEFAULT, {}, cr);
(varslst,p) = BackendVariable.getVar(cr, vars);
res = incidenceRowExp1withInput(varslst,p,pa,1);
then (inExp,false,(vars,res));

/* pre(v) is considered a known variable */
case (DAE.CALL(path = Absyn.IDENT(name = "pre"),expLst = {DAE.CREF()}),_) then (inExp,false,inTpl);
/* previous(v) is considered a known variable */
case (DAE.CALL(path = Absyn.IDENT(name = "previous"),expLst = {DAE.CREF()}),_) then (inExp,false,inTpl);

else (inExp,true,inTpl);
end matchcontinue;
Expand Down Expand Up @@ -3085,6 +3094,9 @@ algorithm
case (BackendDAE.VAR(varKind = BackendDAE.STATE_DER())::rest,i::irest,_,_)
guard not AvlSetInt.hasKey(vars, i)
then incidenceRowExp1(rest,irest,AvlSetInt.add(vars, i),diffindex);
case (BackendDAE.VAR(varKind = BackendDAE.CLOCKED_STATE())::rest,i::irest,_,_)
guard not AvlSetInt.hasKey(vars, i)
then incidenceRowExp1(rest,irest,AvlSetInt.add(vars, i),diffindex);
case (BackendDAE.VAR(varKind = BackendDAE.VARIABLE())::rest,i::irest,_,_)
guard not AvlSetInt.hasKey(vars, i)
then incidenceRowExp1(rest,irest,AvlSetInt.add(vars, i),diffindex);
Expand Down
29 changes: 29 additions & 0 deletions Compiler/BackEnd/BackendVariable.mo
Expand Up @@ -1492,6 +1492,18 @@ algorithm
outVar := setVarKind(outVar,BackendDAE.JAC_DIFF_VAR());
end createpDerVar;

public function createClockedState
"Creates a variable with $CLKPRE.v as cref for jacobian variables."
input BackendDAE.Var inVar;
output BackendDAE.Var outVar;
protected
DAE.ComponentRef cr;
algorithm
cr := ComponentReference.makeCrefQual(DAE.previousNamePrefix, DAE.T_REAL_DEFAULT, {}, inVar.varName);
outVar := copyVarNewName(cr,inVar);
outVar := setVarKind(outVar,BackendDAE.JAC_DIFF_VAR());
end createClockedState;

public function createAliasDerVar
"Creates an alias variable with the name $DER_inCref for a der-call."
input DAE.ComponentRef inCref;
Expand Down Expand Up @@ -3485,6 +3497,13 @@ algorithm
v_lst := traverseBackendDAEVars(inVariables,traversingisStateVarFinder,{});
end getAllStateVarFromVariables;

public function getAllClockedStatesFromVariables
input BackendDAE.Variables inVariables;
output list<BackendDAE.Var> v_lst;
algorithm
v_lst := traverseBackendDAEVars(inVariables,traversingisClockedStateVarFinder,{});
end getAllClockedStatesFromVariables;

public function getNumStateVarFromVariables
input BackendDAE.Variables inVariables;
output Integer count;
Expand All @@ -3502,6 +3521,16 @@ algorithm
v_lst := List.consOnTrue(isStateVar(v),v,inVars);
end traversingisStateVarFinder;

protected function traversingisClockedStateVarFinder
input BackendDAE.Var inVar;
input list<BackendDAE.Var> inVars;
output BackendDAE.Var v;
output list<BackendDAE.Var> v_lst;
algorithm
v := inVar;
v_lst := List.consOnTrue(isClockedStateVar(v),v,inVars);
end traversingisClockedStateVarFinder;

protected function traversingisStateCount
input output BackendDAE.Var v;
input output Integer count;
Expand Down
39 changes: 35 additions & 4 deletions Compiler/BackEnd/SymbolicJacobian.mo
Expand Up @@ -1200,13 +1200,13 @@ algorithm
if debug then execStat("generateSparsePattern -> do start "); end if;
// prepare crefs
depCompRefsLst := List.map(dependentVars, BackendVariable.varCref);
inDepCompRefsLst := List.map(independentVars, BackendVariable.varCref);
depCompRefs := listArray(depCompRefsLst);
inDepCompRefs := listArray(inDepCompRefsLst);
sizeM := arrayLength(depCompRefs);

// create jacobian vars
jacDiffVars := list(BackendVariable.createpDerVar(v) for v in independentVars);
(jacDiffVars,inDepCompRefsLst) := createInDepVars(independentVars);
inDepCompRefs := listArray(inDepCompRefsLst);
sizeN := arrayLength(inDepCompRefs);
sizeM := arrayLength(depCompRefs);

// generate adjacency matrix including diff vars
(syst1 as BackendDAE.EQSYSTEM(orderedVars=varswithDiffs,orderedEqs=orderedEqns)) := BackendDAEUtil.addVarsToEqSystem(syst,jacDiffVars);
Expand Down Expand Up @@ -1646,6 +1646,33 @@ algorithm
end if;
end createBipartiteGraph;

protected function createInDepVars
"This function creates variables for the dependecy
analysis, this needs to cosider different behavoir
clock stated and continuous states.
continuous states: der(x) > dependent and x > independent
clocked states: previous(x) > independent and x > dependent
"
input list<BackendDAE.Var> independentVars;
output list<BackendDAE.Var> outVars = {};
output list<DAE.ComponentRef> outCrefs = {};
protected
BackendDAE.Var var;
algorithm
for v in independentVars loop
if BackendVariable.isClockedStateVar(v) then
var := BackendVariable.createClockedState(v);
outVars := var::outVars;
outCrefs := var.varName::outCrefs;
else
outVars := BackendVariable.createpDerVar(v)::outVars;
outCrefs := v.varName::outCrefs;
end if;
end for;
outVars := listReverse(outVars);
outCrefs := listReverse(outCrefs);
end createInDepVars;

public function createFMIModelDerivatives
"This function genererate the stucture output and the
partial derivatives for FMI, which are basically the jacobian matrices.
Expand Down Expand Up @@ -1687,6 +1714,10 @@ try
knvarlst := BackendVariable.varList(globalKnownVars);
states := BackendVariable.getAllStateVarFromVariables(v);

if Config.languageStandardAtLeast(Config.LanguageStandard.'3.3') then
states := listAppend(states, BackendVariable.getAllClockedStatesFromVariables(v));
end if;

inputvars := List.select(knvarlst,BackendVariable.isVarOnTopLevelAndInput);
outputvars := List.select(varlst, BackendVariable.isVarOnTopLevelAndOutput);

Expand Down
49 changes: 41 additions & 8 deletions Compiler/SimCode/SimCodeUtil.mo
Expand Up @@ -12742,7 +12742,7 @@ public function createFMIModelStructure
protected
list<tuple<DAE.ComponentRef, list<DAE.ComponentRef>>> spTA, spTB;
list<tuple<Integer, list<Integer>>> sparseInts;
list<SimCode.FmiUnknown> derivatives, outputs, discreteStates;
list<SimCode.FmiUnknown> allUnknowns, derivatives, outputs, discreteStates;
list<SimCodeVar.SimVar> varsA, varsB, clockedStates;
list<DAE.ComponentRef> diffCrefsA, diffedCrefsA, derdiffCrefsA;
list<DAE.ComponentRef> diffCrefsB, diffedCrefsB;
Expand All @@ -12757,6 +12757,7 @@ protected
list<SimCodeVar.SimVar> tempvars;
SimCodeVar.SimVars vars;
SimCode.HashTableCrefToSimVar crefSimVarHT;
list<Integer> intLst;
algorithm
try
//print("Start creating createFMIModelStructure\n");
Expand All @@ -12778,11 +12779,23 @@ algorithm
//print("-- created vars for AB\n");
sparseInts := sortSparsePattern(varsA, spTA, true);
//print("-- sorted vars for AB\n");
allUnknowns := translateSparsePatterInts2FMIUnknown(sparseInts, {});

derivatives := translateSparsePatterInts2FMIUnknown(sparseInts, {});
// get derivatives pattern
intLst := list(getVariableIndex(v) for v in inModelInfo.vars.derivativeVars);
derivatives := list(fmiUnknown for fmiUnknown guard(Util.boolOrList(list(isFmiUnknown(i, fmiUnknown) for i in intLst))) in allUnknowns);

(derivatives, outputs) := List.split(derivatives, inModelInfo.varInfo.numStateVars);
// get output pattern
varsA := List.filterOnTrue(inModelInfo.vars.algVars, isOutputSimVar);
intLst := list(getVariableIndex(v) for v in varsA);
outputs := list(fmiUnknown for fmiUnknown guard(Util.boolOrList(list(isFmiUnknown(i, fmiUnknown) for i in intLst))) in allUnknowns);

// get discrete states pattern
clockedStates := List.filterOnTrue(inModelInfo.vars.algVars, isClockedStateSimVar);
intLst := list(getVariableIndex(v) for v in clockedStates);
discreteStates := list(fmiUnknown for fmiUnknown guard(Util.boolOrList(list(isFmiUnknown(i, fmiUnknown) for i in intLst))) in allUnknowns);

// discreteStates
if not checkForEmptyBDAE(optcontPartDer) then
contPartDer := {(optcontPartDer,spPattern,spColors)};
({contSimJac}, uniqueEqIndex) := createSymbolicJacobianssSimCode(contPartDer, crefSimVarHT, uniqueEqIndex, {"FMIDer"}, {});
Expand All @@ -12794,10 +12807,6 @@ algorithm
contPartSimDer := NONE();
end if;

//TODO: create DiscreteStates with dependencies, like derivatives
clockedStates := List.filterOnTrue(inModelInfo.vars.algVars, isClockedStateSimVar);
discreteStates := List.map1(clockedStates, createFmiUnknownFromSimVar, 2*listLength(derivatives)+1);

outFmiModelStructure :=
SOME(
SimCode.FMIMODELSTRUCTURE(
Expand All @@ -12813,7 +12822,7 @@ end try;
end createFMIModelStructure;

protected function isClockedStateSimVar
"Returns true for state and der(state) variables, false otherwise."
"Returns true for discrete state variable, false otherwise."
input SimCodeVar.SimVar inVar;
output Boolean outBoolean;
algorithm
Expand All @@ -12823,6 +12832,30 @@ algorithm
end match;
end isClockedStateSimVar;

protected function isOutputSimVar
"Returns true for output variable, false otherwise."
input SimCodeVar.SimVar inVar;
output Boolean outBoolean;
algorithm
outBoolean := match (inVar)
case (SimCodeVar.SIMVAR(causality = SimCodeVar.OUTPUT())) then true;
else false;
end match;
end isOutputSimVar;

protected function isFmiUnknown
input Integer index;
input SimCode.FmiUnknown inFMIUnknown;
output Boolean out;
algorithm
out := match (inFMIUnknown)
local
Integer i;
case (SimCode.FMIUNKNOWN(index=i)) guard (intEq(i,index)) then true;
else false;
end match;
end isFmiUnknown;

protected function createFmiUnknownFromSimVar
"create a basic FMIUNKNOWN without dependencies from a SimVar"
input SimCodeVar.SimVar var;
Expand Down

0 comments on commit d66515a

Please sign in to comment.