Skip to content

Commit

Permalink
generate partial derivatives for fmus with initialization DAE (#8477)
Browse files Browse the repository at this point in the history
  • Loading branch information
arun3688 committed Feb 18, 2022
1 parent dfa5ea6 commit 00da4a9
Show file tree
Hide file tree
Showing 27 changed files with 605 additions and 34 deletions.
10 changes: 10 additions & 0 deletions OMCompiler/Compiler/BackEnd/BackendVariable.mo
Expand Up @@ -1540,6 +1540,16 @@ algorithm
end match;
end isOutputVar;

public function isRealVar "Return true if variable is type Real"
input BackendDAE.Var inVar;
output Boolean outBoolean;
algorithm
outBoolean := match (inVar)
case (BackendDAE.VAR(varType = DAE.T_REAL())) then true;
else false;
end match;
end isRealVar;

public function isRealOutputVar "Return true if variable is declared as output and type is Real. Note that the output
attribute sticks with a variable even if it is originating from a sub
component, which is not the case for Dymola."
Expand Down
151 changes: 150 additions & 1 deletion OMCompiler/Compiler/BackEnd/SymbolicJacobian.mo
Expand Up @@ -1769,6 +1769,153 @@ else
end try;
end createFMIModelDerivatives;

public function createFMIModelDerivativesForInitialization
"This function genererate the stucture output and the
partial derivatives for FMI, which are basically the jacobian matrices."
input BackendDAE.BackendDAE initDAE;
input BackendDAE.BackendDAE simDAE;
input list<BackendDAE.Var> depVars;
input list<BackendDAE.Var> indepVars;
input BackendDAE.Variables orderedVars;
input BackendDAE.SparsePattern sparsePattern_;
input BackendDAE.SparseColoring sparseColoring_;
output BackendDAE.SymbolicJacobians outJacobianMatrixes = {};
protected
BackendDAE.BackendDAE backendDAE, backendDAE_1, emptyBDAE;
BackendDAE.EqSystem eqSyst, currentSystem;
Option<BackendDAE.SymbolicJacobian> outJacobian;
list<BackendDAE.Var> varlst, knvarlst, states, inputvars, outputvars, paramvars, indepVars_1, depVars_1;
BackendDAE.Variables v, globalKnownVars, statesarr, inputvarsarr, paramvarsarr, outputvarsarr, depVarsArr;
BackendDAE.SparsePattern sparsePattern;
BackendDAE.SparseColoring sparseColoring;
DAE.FunctionTree funcs, functionTree;
BackendDAE.ExtraInfo ei;
FCore.Cache cache;
FCore.Graph graph;
BackendDAE.EquationArray newEqArray, newOrderedEquationArray;
BackendDAE.Shared shared;
DAE.Exp lhs, rhs;
BackendDAE.Equation eqn;
list<Integer> eqlistToRemove;
DAE.ComponentRef cr;
list<DAE.ComponentRef> crefsVarsToRemove;
BackendDAE.Variables newVars;
algorithm
try

backendDAE_1 := BackendDAEUtil.copyBackendDAE(initDAE);
backendDAE_1 := BackendDAEOptimize.collapseIndependentBlocks(backendDAE_1);

//BackendDump.printBackendDAE(backendDAE_1);
//BackendDump.dumpVariables(simDAE.shared.globalKnownVars, "check global vars");

/* add the calculated parameter equations here which does not have constant binding
parameter Real x = 10;
Real m = x; */
BackendDAE.DAE(currentSystem::{}, shared) := backendDAE_1;
for var in depVars loop
if BackendVariable.isParam(var) and not BackendVariable.varHasConstantBindExp(var) then
//print("\n PARAM_CHECK: " + ComponentReference.printComponentRefStr(var.varName));
lhs := BackendVariable.varExp(var);
rhs := BackendVariable.varBindExpStartValueNoFail(var) "bindings are optional";
eqn := BackendDAE.EQUATION(lhs, rhs, DAE.emptyElementSource, BackendDAE.EQ_ATTR_DEFAULT_BINDING);
//BackendDump.printEquation(eqn);
BackendEquation.add(eqn, currentSystem.orderedEqs);
if not BackendVariable.containsCref(var.varName, currentSystem.orderedVars) then
currentSystem := BackendVariable.addVarDAE(BackendVariable.makeVar(var.varName), currentSystem);
end if;
end if;
end for;

// remove equations and vars of the form a = $START.b from Eqsyst to simplify jacobian calculations
newOrderedEquationArray := BackendEquation.emptyEqns();
crefsVarsToRemove:= {};
for eq in BackendEquation.equationList(currentSystem.orderedEqs) loop
if not BackendEquation.isAlgorithm(eq) then
lhs := BackendEquation.getEquationLHS(eq);
rhs := BackendEquation.getEquationRHS(eq);
// print("\nlhs :" + anyString(lhs));
// print("\nrhs :" + anyString(rhs));
// BackendDump.printEquation(eq);
if Expression.isExpCref(lhs) and Expression.isExpCref(rhs) and (ComponentReference.isStartCref(Expression.expCref(rhs)) and ComponentReference.crefEqual(ComponentReference.popCref(Expression.expCref(rhs)), Expression.expCref(lhs))) then
crefsVarsToRemove := Expression.expCref(lhs) :: crefsVarsToRemove;
else
BackendEquation.add(eq, newOrderedEquationArray);
end if;
else
BackendEquation.add(eq, newOrderedEquationArray);
end if;
end for;

newVars := BackendVariable.emptyVars();
for var in BackendVariable.varList(currentSystem.orderedVars) loop
if not listMember(var.varName, crefsVarsToRemove) then
newVars := BackendVariable.addVar(var, newVars);
end if;
end for;

currentSystem := BackendDAEUtil.setEqSystEqs(currentSystem, newOrderedEquationArray);
currentSystem := BackendDAEUtil.setEqSystVars(currentSystem, newVars);

// put the shared globalknown Vars
// for var in BackendVariable.varList(simDAE.shared.globalKnownVars) loop
// if not BackendVariable.containsCref(var.varName, currentSystem.orderedVars) then
// shared := BackendVariable.addGlobalKnownVarDAE(var, shared);
// end if;
// end for;


backendDAE_1 := BackendDAE.DAE({currentSystem}, shared);
backendDAE_1 := BackendDAEUtil.transformBackendDAE(backendDAE_1, SOME((BackendDAE.NO_INDEX_REDUCTION(),BackendDAE.EXACT())),NONE(),NONE());

//BackendDump.printBackendDAE(backendDAE_1);

//prepare simulation DAE
backendDAE := BackendDAEUtil.copyBackendDAE(simDAE);
backendDAE := BackendDAEOptimize.collapseIndependentBlocks(backendDAE);

eqSyst::{} := backendDAE.eqs;
v := eqSyst.orderedVars;
// get state var from simulation DAE
states := if Config.languageStandardAtLeast(Config.LanguageStandard.'3.3') then
BackendVariable.getAllClockedStatesFromVariables(v) else {};
states := listAppend(BackendVariable.getAllStateVarFromVariables(v), states);

// prepare all needed variables from initialization DAE
varlst := BackendVariable.varList(currentSystem.orderedVars);
knvarlst := BackendVariable.varList(simDAE.shared.globalKnownVars);
//BackendDump.dumpVarList(knvarlst, "shared simulation DAE");
inputvars := List.select(knvarlst, BackendVariable.isVarOnTopLevelAndInput);

// Generate empty jacobian martices
if Flags.isSet(Flags.DIS_SYMJAC_FMI20) then
cache := initDAE.shared.cache;
graph := initDAE.shared.graph;
ei := initDAE.shared.info;
emptyBDAE := BackendDAE.DAE({BackendDAEUtil.createEqSystem(BackendVariable.emptyVars(), BackendEquation.emptyEqns())}, BackendDAEUtil.createEmptyShared(BackendDAE.JACOBIAN(), ei, cache, graph));
outJacobianMatrixes := (SOME((emptyBDAE,"FMIDERINIT",{},{},{}, {})), BackendDAE.emptySparsePattern, {})::outJacobianMatrixes;
else
// prepare more needed variables
paramvars := List.select(knvarlst, BackendVariable.isParam);
statesarr := BackendVariable.listVar1(states);
inputvarsarr := BackendVariable.listVar1(inputvars);
paramvarsarr := BackendVariable.listVar1(paramvars);
depVarsArr := BackendVariable.listVar1(depVars);

//(outJacobian, outFunctionTree, _, _) := generateGenericJacobian(backendDAE_1, indepVars, BackendVariable.emptyVars(), BackendVariable.emptyVars(), BackendVariable.emptyVars(), depVarsArr, depVars, "FMIDERINIT", Flags.isSet(Flags.DIS_SYMJAC_FMI20));
(outJacobian, _, _, _) := generateGenericJacobian(backendDAE_1, indepVars, statesarr, inputvarsarr, paramvarsarr, depVarsArr, varlst, "FMIDERINIT", Flags.isSet(Flags.DIS_SYMJAC_FMI20));

if Flags.isSet(Flags.JAC_DUMP2) then
BackendDump.dumpSparsityPattern(sparsePattern_, "FMI sparsity");
end if;
outJacobianMatrixes := (outJacobian, sparsePattern_, sparseColoring_)::outJacobianMatrixes;
end if;
else
Error.addInternalError("function createFMIModelDerivativesForInitialization failed", sourceInfo());
outJacobianMatrixes := {};
end try;
end createFMIModelDerivativesForInitialization;

protected function createLinearModelMatrixes "This function creates the linear model matrices column-wise
author: wbraun"
input BackendDAE.BackendDAE inBackendDAE;
Expand Down Expand Up @@ -1979,7 +2126,9 @@ algorithm
outJacobian := NONE();
end if;
// generate sparse pattern
(outSparsePattern,outSparseColoring) := generateSparsePattern(inBackendDAE, inDiffVars, BackendVariable.varList(inDifferentiatedVars));
if (not stringEq(inName, "FMIDERINIT")) then
(outSparsePattern,outSparseColoring) := generateSparsePattern(inBackendDAE, inDiffVars, BackendVariable.varList(inDifferentiatedVars));
end if;
else
fail();
end try;
Expand Down
11 changes: 11 additions & 0 deletions OMCompiler/Compiler/FrontEnd/Expression.mo
Expand Up @@ -9690,6 +9690,17 @@ algorithm
outBoolean:= expContains(inExp2,inExp1);
end containsExp;

public function isExpCref
"Returns true if expression is a componentRef"
input DAE.Exp e;
output Boolean res;
algorithm
res := match(e)
case(DAE.CREF(_,_)) then true;
else false;
end match;
end isExpCref;

public function isExpCrefOrIfExp
"Returns true if expression is a componentRef or an if expression"
input DAE.Exp e;
Expand Down
3 changes: 3 additions & 0 deletions OMCompiler/Compiler/SimCode/SimCode.mo
Expand Up @@ -631,6 +631,8 @@ end FmiDiscreteStates;
public uniontype FmiInitialUnknowns
record FMIINITIALUNKNOWNS
list<FmiUnknown> fmiUnknownsList;
list<tuple<Integer, DAE.ComponentRef>> sortedUnknownCrefs "use the sorted crefs to get the ValueReference of unknowns";
list<tuple<Integer, DAE.ComponentRef>> sortedknownCrefs "use the sorted crefs to get the ValueReference of knowns";
end FMIINITIALUNKNOWNS;
end FmiInitialUnknowns;

Expand All @@ -639,6 +641,7 @@ public uniontype FmiModelStructure
FmiOutputs fmiOutputs;
FmiDerivatives fmiDerivatives;
Option<JacobianMatrix> continuousPartialDerivatives;
Option<JacobianMatrix> initialPartialDerivatives;
FmiDiscreteStates fmiDiscreteStates;
FmiInitialUnknowns fmiInitialUnknowns;
end FMIMODELSTRUCTURE;
Expand Down

0 comments on commit 00da4a9

Please sign in to comment.