Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit bba4362

Browse files
Willi BraunOpenModelica-Hudson
authored andcommitted
fixing FMI directional derivatives and model structure
- enable directional derivatives for fmi 2.0 by default and generation of the corresponding symbolic jacobians - rewrite the structure for the dependencies and the partial derivatives generation adjust C-runtime code generation - fixing model structure for output states - rename debug flag disableSymbolicLinearization to disableDirectionalDerivatives Belonging to [master]: - #1715 - OpenModelica/OpenModelica-testsuite#722
1 parent a766c29 commit bba4362

File tree

14 files changed

+331
-254
lines changed

14 files changed

+331
-254
lines changed

Compiler/BackEnd/BackendDAE.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@ public constant Integer SymbolicJacobianDIndex = 4;
709709
public constant String derivativeNamePrefix = "$DERAlias";
710710
public constant String partialDerivativeNamePrefix = "$pDER";
711711
public constant String functionDerivativeNamePrefix = "$funDER";
712+
public constant String outputStateAliasPrefix = "$outputStateAlias_";
712713

713714
public constant String optimizationMayerTermName = "$OMC$objectMayerTerm";
714715
public constant String optimizationLagrangeTermName = "$OMC$objectLagrangeTerm";

Compiler/BackEnd/BackendDAEUtil.mo

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ import ExpressionSimplify;
9393
import ExpressionSolve;
9494
import FindZeroCrossings;
9595
import Flags;
96+
import FMI;
9697
import Global;
9798
import HpcOmEqSystems;
9899
import IndexReduction;
@@ -1707,6 +1708,53 @@ algorithm
17071708
end match;
17081709
end reduceEqSystem;
17091710

1711+
public function createAliasVarsForOutputStates
1712+
" creates for every state that is also output an
1713+
alias variable $outputStateAlias.stateName and
1714+
the corresponding equation"
1715+
input BackendDAE.BackendDAE inBDAE;
1716+
output BackendDAE.BackendDAE outBDAE = inBDAE;
1717+
protected
1718+
BackendDAE.EqSystems systems, returnSysts = {};
1719+
BackendDAE.Variables vars;
1720+
BackendDAE.EquationArray eqs;
1721+
list<BackendDAE.Var> states;
1722+
DAE.ComponentRef newCref;
1723+
BackendDAE.Var newVar;
1724+
BackendDAE.Equation newEqn;
1725+
algorithm
1726+
systems := inBDAE.eqs;
1727+
for system in systems loop
1728+
eqs := system.orderedEqs;
1729+
vars := system.orderedVars;
1730+
states := BackendVariable.getAllStateVarFromVariables(vars);
1731+
for v in states loop
1732+
if BackendVariable.isVarOnTopLevelAndOutput(v) then
1733+
// generate new output var and add it
1734+
newCref := ComponentReference.prependStringCref(BackendDAE.outputStateAliasPrefix, BackendVariable.varCref(v));
1735+
newVar := BackendVariable.copyVarNewName(newCref, v);
1736+
newVar := BackendVariable.setVarKind(newVar, BackendDAE.VARIABLE());
1737+
vars := BackendVariable.addVar(newVar, vars);
1738+
1739+
//update states to remove the output direction
1740+
v := BackendVariable.setVarDirection(v, DAE.BIDIR());
1741+
vars := BackendVariable.addVar(v, vars);
1742+
1743+
// generate new equation and add it
1744+
newEqn := BackendEquation.generateEquation(Expression.crefToExp(newCref), Expression.crefToExp(BackendVariable.varCref(v)), DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_BINDING);
1745+
eqs := BackendEquation.add(newEqn, eqs);
1746+
end if;
1747+
end for;
1748+
system.orderedVars := vars;
1749+
system.orderedEqs := eqs;
1750+
system := BackendDAEUtil.clearEqSyst(system);
1751+
returnSysts := system::returnSysts;
1752+
end for;
1753+
returnSysts := listReverse(returnSysts);
1754+
outBDAE.eqs := returnSysts;
1755+
outBDAE := BackendDAEUtil.transformBackendDAE(outBDAE, SOME((BackendDAE.NO_INDEX_REDUCTION(), BackendDAE.EXACT())), NONE(), NONE());
1756+
end createAliasVarsForOutputStates;
1757+
17101758
protected function translateArrayList
17111759
input Integer inElement;
17121760
input Integer inIndex;
@@ -7436,6 +7484,7 @@ end allPreOptimizationModules;
74367484
protected function allPostOptimizationModules
74377485
"This list contains all back end sim-optimization modules."
74387486
output list<tuple<BackendDAEFunc.optimizationModule, String>> allPostOptimizationModules = {
7487+
(BackendDAEUtil.createAliasVarsForOutputStates, "createAliasVarsForOutputStates"),
74397488
(BackendInline.lateInlineFunction, "lateInlineFunction"),
74407489
(DynamicOptimization.simplifyConstraints, "simplifyConstraints"),
74417490
(CommonSubExpression.wrapFunctionCalls, "wrapFunctionCalls"),
@@ -8638,6 +8687,17 @@ algorithm
86388687
end match;
86398688
end setSharedSymJacs;
86408689

8690+
public function getSharedSymJacs
8691+
input BackendDAE.Shared inShared;
8692+
output BackendDAE.SymbolicJacobians outSymjacs;
8693+
algorithm
8694+
outSymjacs := match inShared
8695+
local
8696+
BackendDAE.Shared shared;
8697+
case shared as BackendDAE.SHARED() then shared.symjacs;
8698+
end match;
8699+
end getSharedSymJacs;
8700+
86418701
public function setSharedFunctionTree
86428702
input BackendDAE.Shared inShared;
86438703
input DAE.FunctionTree inFunctionTree;

Compiler/BackEnd/BackendVariable.mo

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,6 +2318,17 @@ algorithm
23182318
end match;
23192319
end isVarKindVariable;
23202320

2321+
public function isVarKindState
2322+
input BackendDAE.VarKind inVarKind;
2323+
output Boolean result;
2324+
algorithm
2325+
result :=
2326+
match (inVarKind)
2327+
case (BackendDAE.STATE()) then true;
2328+
else false;
2329+
end match;
2330+
end isVarKindState;
2331+
23212332
public function isTopLevelInputOrOutput "author: LP
23222333

23232334
This function checks if the provided cr is from a var that is on top model

Compiler/BackEnd/Differentiate.mo

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,25 @@ algorithm
17621762
(res1, _) = Expression.makeZeroExpression(Expression.arrayDimension(tp));
17631763
then
17641764
(res1, inFunctionTree);
1765+
/* floor ceil and interger are expanded by the zeroCrossing index, thus they
1766+
have 2 arguments */
1767+
case ("floor", _, DAE.CALL_ATTR(ty=tp))
1768+
equation
1769+
(res1, _) = Expression.makeZeroExpression(Expression.arrayDimension(tp));
1770+
then
1771+
(res1, inFunctionTree);
1772+
1773+
case ("ceil", _, DAE.CALL_ATTR(ty=tp))
1774+
equation
1775+
(res1, _) = Expression.makeZeroExpression(Expression.arrayDimension(tp));
1776+
then
1777+
(res1, inFunctionTree);
1778+
1779+
case ("integer", _, DAE.CALL_ATTR(ty=tp))
1780+
equation
1781+
(res1, _) = Expression.makeZeroExpression(Expression.arrayDimension(tp));
1782+
then
1783+
(res1, inFunctionTree);
17651784

17661785
end match;
17671786
end differentiateCallExpNArg;

Compiler/BackEnd/SymbolicJacobian.mo

Lines changed: 90 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ algorithm
324324
case(_) equation
325325
true = Flags.getConfigBool(Flags.GENERATE_SYMBOLIC_LINEARIZATION);
326326
BackendDAE.DAE(eqs=eqs,shared=shared) = inBackendDAE;
327-
(linearModelMatrixes, funcs) = createLinearModelMatrixes(inBackendDAE, Config.acceptOptimicaGrammar(), Flags.isSet(Flags.DIS_SYMJAC_FMI20));
327+
(linearModelMatrixes, funcs) = createLinearModelMatrixes(inBackendDAE, Config.acceptOptimicaGrammar());
328328
shared = BackendDAEUtil.setSharedSymJacs(shared, linearModelMatrixes);
329329
functionTree = BackendDAEUtil.getFunctions(shared);
330330
functionTree = DAE.AvlTreePathFunction.join(functionTree, funcs);
@@ -1582,17 +1582,102 @@ algorithm
15821582
end if;
15831583
end createBipartiteGraph;
15841584

1585+
public function createFMIModelDerivatives
1586+
"This function genererate the stucture output and the
1587+
partial derivatives for FMI, which are basically the jacobian matrices.
1588+
author: wbraun"
1589+
input BackendDAE.BackendDAE inBackendDAE;
1590+
output BackendDAE.SymbolicJacobians outJacobianMatrixes = {};
1591+
output DAE.FunctionTree outFunctionTree;
1592+
protected
1593+
BackendDAE.BackendDAE backendDAE,emptyBDAE;
1594+
BackendDAE.EqSystem eqSyst;
1595+
Option<BackendDAE.SymbolicJacobian> outJacobian;
1596+
1597+
list<BackendDAE.Var> varlst, knvarlst, states, inputvars, outputvars, paramvars, indepVars, depVars;
1598+
1599+
BackendDAE.Variables v,globalKnownVars,statesarr,inputvarsarr,paramvarsarr,outputvarsarr, depVarsArr;
1600+
1601+
BackendDAE.SparsePattern sparsePattern;
1602+
BackendDAE.SparseColoring sparseColoring;
1603+
1604+
DAE.FunctionTree funcs, functionTree;
1605+
1606+
BackendDAE.ExtraInfo ei;
1607+
FCore.Cache cache;
1608+
FCore.Graph graph;
1609+
algorithm
1610+
try
1611+
// for now perform on collapsed system
1612+
backendDAE := BackendDAEUtil.copyBackendDAE(inBackendDAE);
1613+
backendDAE := BackendDAEOptimize.collapseIndependentBlocks(backendDAE);
1614+
backendDAE := BackendDAEUtil.transformBackendDAE(backendDAE,SOME((BackendDAE.NO_INDEX_REDUCTION(),BackendDAE.EXACT())),NONE(),NONE());
1615+
1616+
// get all variables
1617+
eqSyst::{} := backendDAE.eqs;
1618+
v := eqSyst.orderedVars;
1619+
globalKnownVars := backendDAE.shared.globalKnownVars;
1620+
1621+
// prepare all needed variables
1622+
varlst := BackendVariable.varList(v);
1623+
knvarlst := BackendVariable.varList(globalKnownVars);
1624+
states := BackendVariable.getAllStateVarFromVariables(v);
1625+
1626+
inputvars := List.select(knvarlst,BackendVariable.isVarOnTopLevelAndInput);
1627+
outputvars := List.select(varlst, BackendVariable.isVarOnTopLevelAndOutput);
1628+
1629+
// independent varibales states + inputs
1630+
indepVars := listAppend(states, inputvars);
1631+
1632+
// dependent varibales der(states) + outputs
1633+
depVars := listAppend(states, outputvars);
1634+
1635+
// Generate sparse pattern for matrices states
1636+
// prepare more needed variables
1637+
if Flags.isSet(Flags.DIS_SYMJAC_FMI20) then
1638+
// empty BackendDAE in case derivates should not calclulated
1639+
cache := backendDAE.shared.cache;
1640+
graph := backendDAE.shared.graph;
1641+
ei := backendDAE.shared.info;
1642+
emptyBDAE := BackendDAE.DAE({BackendDAEUtil.createEqSystem(BackendVariable.emptyVars(), BackendEquation.emptyEqns())}, BackendDAEUtil.createEmptyShared(BackendDAE.JACOBIAN(), ei, cache, graph));
1643+
1644+
(sparsePattern, sparseColoring) := generateSparsePattern(backendDAE, indepVars, depVars);
1645+
if Flags.isSet(Flags.JAC_DUMP2) then
1646+
BackendDump.dumpSparsityPattern(sparsePattern, "FMI sparsity");
1647+
end if;
1648+
outJacobianMatrixes := (SOME((emptyBDAE,"FMIDER",{},{},{})), sparsePattern, sparseColoring)::outJacobianMatrixes;
1649+
outFunctionTree := inBackendDAE.shared.functionTree;
1650+
else
1651+
// prepare more needed variables
1652+
paramvars := List.select(knvarlst, BackendVariable.isParam);
1653+
statesarr := BackendVariable.listVar1(states);
1654+
inputvarsarr := BackendVariable.listVar1(inputvars);
1655+
paramvarsarr := BackendVariable.listVar1(paramvars);
1656+
depVarsArr := BackendVariable.listVar1(depVars);
1657+
1658+
(outJacobian, outFunctionTree, sparsePattern, sparseColoring) := generateGenericJacobian(backendDAE,indepVars,statesarr,inputvarsarr,paramvarsarr,depVarsArr,varlst,"FMIDER", Flags.isSet(Flags.DIS_SYMJAC_FMI20));
1659+
if Flags.isSet(Flags.JAC_DUMP2) then
1660+
BackendDump.dumpSparsityPattern(sparsePattern, "FMI sparsity");
1661+
end if;
1662+
outJacobianMatrixes := (outJacobian, sparsePattern, sparseColoring)::outJacobianMatrixes;
1663+
end if;
1664+
else
1665+
Error.addInternalError("function createFMIModelDerivatives failed", sourceInfo());
1666+
outJacobianMatrixes := {};
1667+
outFunctionTree := inBackendDAE.shared.functionTree;
1668+
end try;
1669+
end createFMIModelDerivatives;
1670+
15851671
protected function createLinearModelMatrixes "This function creates the linear model matrices column-wise
15861672
author: wbraun"
15871673
input BackendDAE.BackendDAE inBackendDAE;
15881674
input Boolean useOptimica;
1589-
input Boolean noGenSymbolicJac;
15901675
output BackendDAE.SymbolicJacobians outJacobianMatrixes;
15911676
output DAE.FunctionTree outFunctionTree;
15921677

15931678
algorithm
15941679
(outJacobianMatrixes, outFunctionTree) :=
1595-
match (inBackendDAE, useOptimica, noGenSymbolicJac)
1680+
match (inBackendDAE, useOptimica)
15961681
local
15971682
BackendDAE.BackendDAE backendDAE,backendDAE2,emptyBDAE;
15981683

@@ -1616,42 +1701,7 @@ algorithm
16161701
FCore.Cache cache;
16171702
FCore.Graph graph;
16181703

1619-
case (backendDAE, false, true)
1620-
equation
1621-
backendDAE2 = BackendDAEUtil.copyBackendDAE(backendDAE);
1622-
backendDAE2 = BackendDAEOptimize.collapseIndependentBlocks(backendDAE2);
1623-
backendDAE2 = BackendDAEUtil.transformBackendDAE(backendDAE2,SOME((BackendDAE.NO_INDEX_REDUCTION(),BackendDAE.EXACT())),NONE(),NONE());
1624-
BackendDAE.DAE({BackendDAE.EQSYSTEM(orderedVars = v)}, BackendDAE.SHARED(globalKnownVars = globalKnownVars, functionTree = functionTree, cache=cache, graph=graph, info=ei)) = backendDAE2;
1625-
1626-
emptyBDAE = BackendDAE.DAE({BackendDAEUtil.createEqSystem(BackendVariable.emptyVars(), BackendEquation.emptyEqns())}, BackendDAEUtil.createEmptyShared(BackendDAE.JACOBIAN(), ei, cache, graph));
1627-
// Prepare all needed variables
1628-
varlst = BackendVariable.varList(v);
1629-
knvarlst = BackendVariable.varList(globalKnownVars);
1630-
states = BackendVariable.getAllStateVarFromVariables(v);
1631-
_ = List.select(knvarlst,BackendVariable.isInput);
1632-
_ = List.select(knvarlst, BackendVariable.isParam);
1633-
inputvars2 = List.select(knvarlst,BackendVariable.isVarOnTopLevelAndInput);
1634-
outputvars = List.select(varlst, BackendVariable.isVarOnTopLevelAndOutput);
1635-
1636-
// Generate sparse pattern for matrices A
1637-
(sparsePattern, sparseColoring) = generateSparsePattern(backendDAE2, states, states);
1638-
linearModelMatrices = {(SOME((emptyBDAE,"A",{},{},{})), sparsePattern, sparseColoring)};
1639-
1640-
// Generate sparse pattern for matrices B
1641-
(sparsePattern, sparseColoring) = generateSparsePattern(backendDAE2, inputvars2, states);
1642-
linearModelMatrices = listAppend(linearModelMatrices,{(SOME((emptyBDAE,"B",{},{},{})), sparsePattern, sparseColoring)});
1643-
1644-
// Generate sparse pattern for matrices C
1645-
(sparsePattern, sparseColoring) = generateSparsePattern(backendDAE2, states, outputvars);
1646-
linearModelMatrices = listAppend(linearModelMatrices,{(SOME((emptyBDAE,"C",{},{},{})), sparsePattern, sparseColoring)});
1647-
1648-
// Generate sparse pattern for matrices D
1649-
(sparsePattern, sparseColoring) = generateSparsePattern(backendDAE2, inputvars2, outputvars);
1650-
linearModelMatrices = listAppend(linearModelMatrices,{(SOME((emptyBDAE,"D",{},{},{})), sparsePattern, sparseColoring)});
1651-
then
1652-
(linearModelMatrices, functionTree);
1653-
1654-
case (backendDAE, false, _)
1704+
case (backendDAE, false)
16551705
equation
16561706
backendDAE2 = BackendDAEUtil.copyBackendDAE(backendDAE);
16571707
backendDAE2 = BackendDAEOptimize.collapseIndependentBlocks(backendDAE2);
@@ -1709,7 +1759,7 @@ algorithm
17091759
then
17101760
(linearModelMatrices, functionTree);
17111761

1712-
case (backendDAE, true, _) // created linear model (matrixes) for optimization
1762+
case (backendDAE, true) // created linear model (matrixes) for optimization
17131763
equation
17141764
// A := der(x)
17151765
// B := {der(x), con(x), L(x)}

Compiler/SimCode/SimCode.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ public uniontype FmiModelStructure
487487
record FMIMODELSTRUCTURE
488488
FmiOutputs fmiOutputs;
489489
FmiDerivatives fmiDerivatives;
490+
Option<JacobianMatrix> continuousPartialDerivatives;
490491
FmiDiscreteStates fmiDiscreteStates;
491492
FmiInitialUnknowns fmiInitialUnknowns;
492493
end FMIMODELSTRUCTURE;

0 commit comments

Comments
 (0)