diff --git a/Compiler/BackEnd/BackendDAEUtil.mo b/Compiler/BackEnd/BackendDAEUtil.mo index 41b124c486..fe2602a0c8 100644 --- a/Compiler/BackEnd/BackendDAEUtil.mo +++ b/Compiler/BackEnd/BackendDAEUtil.mo @@ -8287,6 +8287,16 @@ algorithm varLst := List.flatten(List.map(globalKnownVars::List.map(eqs, BackendVariable.daeVars), BackendVariable.varList)); end getAllVarLst; +public function getOrderedVarsLst "retrieve all orderedVars variables of the dae by collecting them from each equation system" + input BackendDAE.BackendDAE dae; + output list varLst; +protected + BackendDAE.EqSystems eqs; +algorithm + BackendDAE.DAE(eqs=eqs) := dae; + varLst := List.flatten(List.map(List.map(eqs, BackendVariable.daeVars), BackendVariable.varList)); +end getOrderedVarsLst; + public function isClockedSyst input BackendDAE.EqSystem inSyst; output Boolean out; diff --git a/Compiler/BackEnd/SymbolicJacobian.mo b/Compiler/BackEnd/SymbolicJacobian.mo index 657fea7bab..705a052a38 100644 --- a/Compiler/BackEnd/SymbolicJacobian.mo +++ b/Compiler/BackEnd/SymbolicJacobian.mo @@ -1139,7 +1139,7 @@ algorithm end matchcontinue; end checkLinearSystem; -protected function generateSparsePattern "author: wbraun +public function generateSparsePattern "author: wbraun Function generated for a given set of variables and equations the sparsity pattern and a coloring of Jacobian matrix A^(NxM). col: N = size(diffVars) diff --git a/Compiler/SimCode/SimCodeUtil.mo b/Compiler/SimCode/SimCodeUtil.mo index 0199d87a52..04e19b87be 100644 --- a/Compiler/SimCode/SimCodeUtil.mo +++ b/Compiler/SimCode/SimCodeUtil.mo @@ -487,7 +487,7 @@ algorithm // collect fmi partial derivative if FMI.isFMIVersion20(FMUVersion) then - (SymbolicJacsFMI, modelStructure, modelInfo, SymbolicJacsTemp, uniqueEqIndex) := createFMIModelStructure(inFMIDer, modelInfo, uniqueEqIndex); + (SymbolicJacsFMI, modelStructure, modelInfo, SymbolicJacsTemp, uniqueEqIndex) := createFMIModelStructure(inFMIDer, modelInfo, uniqueEqIndex, inInitDAE); SymbolicJacsNLS := listAppend(SymbolicJacsTemp, SymbolicJacsNLS); if debug then execStat("simCode: create FMI model structure"); end if; end if; @@ -11947,6 +11947,7 @@ public function createFMIModelStructure input BackendDAE.SymbolicJacobians inSymjacs; input SimCode.ModelInfo inModelInfo; input Integer inUniqueEqIndex; + input BackendDAE.BackendDAE inInitDAE; output list symJacFMI = {}; output Option outFmiModelStructure; output SimCode.ModelInfo outModelInfo = inModelInfo; @@ -11970,16 +11971,19 @@ protected list tempvars; SimCodeVar.SimVars vars; SimCode.HashTableCrefToSimVar crefSimVarHT; - list intLst; + list intLst, derivativesLst; + SimCode.FmiInitialUnknowns fmiInitUnknowns; + constant Boolean debug = false; algorithm try //print("Start creating createFMIModelStructure\n"); // combine the transposed sparse pattern of matrix A and B - // to obtain dependencies for the derivativesq + // to obtain dependencies for the derivatives and outputs SOME((optcontPartDer, spPattern as (_, spTA, (diffCrefsA, diffedCrefsA),_), spColors)) := SymbolicJacobian.getJacobianMatrixbyName(inSymjacs, "FMIDER"); crefSimVarHT := createCrefToSimVarHT(inModelInfo); //print("-- Got matrixes\n"); + (spTA, derdiffCrefsA) := translateSparsePatterCref2DerCref(spTA, crefSimVarHT, {}, {}); //print("-- translateSparsePatterCref2DerCref matrixes AB\n"); @@ -11995,8 +11999,8 @@ algorithm allUnknowns := 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); + derivativesLst := list(getVariableIndex(v) for v in inModelInfo.vars.derivativeVars); + derivatives := list(fmiUnknown for fmiUnknown guard(Util.boolOrList(list(isFmiUnknown(i, fmiUnknown) for i in derivativesLst))) in allUnknowns); // get output pattern varsA := List.filterOnTrue(inModelInfo.vars.algVars, isOutputSimVar); @@ -12021,6 +12025,11 @@ algorithm else contPartSimDer := NONE(); end if; + if debug then print("-- FMI directional derivatives created\n"); end if; + + // create initial unknonw dependencies + fmiInitUnknowns := getFMIInitialDep(inInitDAE, crefSimVarHT, derivativesLst); + if debug then print("-- FMI initial unknown created\n"); end if; outFmiModelStructure := SOME( @@ -12029,7 +12038,7 @@ algorithm SimCode.FMIDERIVATIVES(derivatives), contPartSimDer, SimCode.FMIDISCRETESTATES(discreteStates), - SimCode.FMIINITIALUNKNOWNS({}))); + fmiInitUnknowns)); else // create empty model structure try @@ -12181,6 +12190,74 @@ algorithm end match; end mergeSparsePatter; +protected function getFMIInitialDep + input BackendDAE.BackendDAE initDAE; + input SimCode.HashTableCrefToSimVar crefSimVarHT; + input list derivativesLst; + output SimCode.FmiInitialUnknowns fmiInitUnknowns; +protected + list initUnknowns, states, tmpinitUnknowns; + list diffCrefs, diffedCrefs, derdiffCrefs, tmpOutputCref; + list>> spT; + list>> sparseInts; + list unknowns; + list vars1, vars2, outputvars; + BackendDAE.BackendDAE tmpBDAE; + list intLst; +algorithm + try + //prepare initialUnknows + tmpBDAE := BackendDAEOptimize.collapseIndependentBlocks(initDAE); + tmpBDAE := BackendDAEUtil.transformBackendDAE(tmpBDAE, SOME((BackendDAE.NO_INDEX_REDUCTION(), BackendDAE.EXACT())), NONE(), NONE()); + + // TODO: filter the initUnknows for variables + // with causality = "output" and causality = "calculatedParameter" + // and all continuous-time states and all state derivatives + initUnknowns := BackendDAEUtil.getOrderedVarsLst(tmpBDAE); + + // get the output patterns with causality = "output" and intial = "calculated" + (tmpinitUnknowns, _) := List.extractOnTrue(initUnknowns,isVarOutputandNotfixed); + tmpOutputCref:= List.filterMap(tmpinitUnknowns,getVarCref); + outputvars := getSimVars2Crefs(tmpOutputCref, crefSimVarHT); + intLst := list(getVariableIndex(v) for v in outputvars); + + ((_, spT, (diffCrefs, diffedCrefs),_),_) := SymbolicJacobian.generateSparsePattern(tmpBDAE, initUnknowns, initUnknowns); + + // collect all variable + vars1 := getSimVars2Crefs(diffedCrefs, crefSimVarHT); + vars2 := getSimVars2Crefs(diffCrefs, crefSimVarHT); + vars1 := listAppend(vars1, vars2); + + sparseInts := sortSparsePattern(vars1, spT, true); + unknowns := translateSparsePatterInts2FMIUnknown(sparseInts, {}); + + // filter the initial unknowns with output and derivativelist index + unknowns := list(fmiUnknown for fmiUnknown guard(Util.boolOrList(list(isFmiUnknown(i, fmiUnknown) for i in listAppend(intLst,derivativesLst)))) in unknowns); + + fmiInitUnknowns := SimCode.FMIINITIALUNKNOWNS(unknowns); + else + fmiInitUnknowns := SimCode.FMIINITIALUNKNOWNS({}); + end try; +end getFMIInitialDep; + +public function getVarCref + input BackendDAE.Var inVar; + output DAE.ComponentRef outComponentRef; +algorithm + outComponentRef := BackendVariable.varCref(inVar); +end getVarCref; + +public function isVarOutputandNotfixed + input BackendDAE.Var inVar; + output Boolean outVar=false; +protected + Boolean direction; + algorithm + if (BackendVariable.isOutputVar(inVar) and not BackendVariable.varFixed(inVar)) then + outVar := true; + end if; +end isVarOutputandNotfixed; + public function getStateSimVarIndexFromIndex input list inStateVars; input Integer inIndex; diff --git a/Compiler/Template/CodegenFMUCommon.tpl b/Compiler/Template/CodegenFMUCommon.tpl index e2f6eb1da0..506a8b9512 100644 --- a/Compiler/Template/CodegenFMUCommon.tpl +++ b/Compiler/Template/CodegenFMUCommon.tpl @@ -482,7 +482,7 @@ match simVar let clockIndex = getClockIndex(simVar, simCode) let previous = match varKind case CLOCKED_STATE(__) then '<%getVariableIndex(cref2simvar(previousName, simCode))%>' let caus = getCausality2(causality, varKind, isValueChangeable) - let initial = getInitialType2(variability, caus, initialValue) + let initial = getInitialType2(variability, caus, initialValue, isFixed) << name="<%System.stringReplace(crefStrNoUnderscore(name),"$", "_D_")%>" valueReference="<%valueReference%>" @@ -540,7 +540,7 @@ match simCode else "" end getNumberOfEventIndicators; -template getInitialType2(String variability, String causality, Option initialValue) +template getInitialType2(String variability, String causality, Option initialValue, Boolean isFixed) "Returns the Initial Attribute of ScalarVariable." ::= match variability @@ -561,8 +561,10 @@ match variability match causality case "output" case "local" then - match initialValue - case SOME(exp) then "exact" + //match initialValue + //case SOME(exp) then "exact" + match isFixed + case true then "exact" else "calculated" else "" else "" @@ -599,7 +601,7 @@ template StartString2(SimVar simvar) match simvar case SIMVAR(aliasvar = SimCodeVar.ALIAS(__)) then '' -case SIMVAR(initialValue = initialValue, varKind = varKind, causality = causality, type_ = type_, isValueChangeable = isValueChangeable) then +case SIMVAR(initialValue = initialValue, varKind = varKind, causality = causality, type_ = type_, isValueChangeable = isValueChangeable, isFixed = isFixed) then match initialValue case SOME(e as ICONST(__)) then ' start="<%initValXml(e)%>"' case SOME(e as RCONST(__)) then ' start="<%initValXml(e)%>"' @@ -609,7 +611,7 @@ case SIMVAR(initialValue = initialValue, varKind = varKind, causality = causalit else let variability = getVariability2(varKind, type_) let caus = getCausality2(causality, varKind, isValueChangeable) - let initial = getInitialType2(variability, caus, initialValue) + let initial = getInitialType2(variability, caus, initialValue, isFixed) if boolOr(stringEq(initial, "exact"), boolOr(stringEq(initial, "approx"), stringEq(caus, "input"))) then ' start="<%initDefaultValXml(type_)%>"' else '' end StartString2;